mybatis

mybatis

致命三连

  1. 是什么:MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架(属于持久层ORM框架)

  2. 为什么:简化jdbc代码,简化持久层,sql语句从代码中分离,利用反射,将表中数据与java bean 属性一一映射即ORM

特点

  1. 持久层: 讲内存中对象数据,转移到数据库中的过程持久层

  2. ORM Object Relational Mapping 对象关系映射框架

  3. 半自化

    1. 表需要手动进行设计

    2. 提供sql

    3. 依赖与数据库平台

  4. 优点:学习成本低,使用简单,适合做一些业务多变的互联网项目

环境搭建

  1. 下载资源jar包

  2. 项目下新建lib路径,需要的jar包放入lib路径下(mybatis,jdbc,其他jar包),选中右键add as lib..

  3. 编写代码程序

    1. 核心配置文件

      1. 做mybatis使用的核心基本配置

      2. 数据库的连接信息

      3. 是否使用连接池技术

      4. SQL映射文件的扫描

    2. SQL映射文件 : 定义SQL语句

      1. namespace : 命名空间(定义sql映射文件的唯一) 要求:一个项目中不能重复 定义:包名.文件名 (不加后缀)

      2. select 相当于一个处理块

        1. id:一个命名空间中sql语句的唯一标识,见名知意不可重复

        2. resultType : 返回值类型,用Java中的某个类接收,如果返回值为一条结果就用一个类型接收,如果返回值是多条记录就用List<泛型>集合来接收。

        3. parameterType : 入参类型

      <mapper namespace="com.yjxxt.mappers.DeptMapper">
      <select id="queryAll" resultType="Dept" parameterType="">
            select * from dept
        </select>
      </mapper>
      基本数据类型|包装类 String Date JAVABEAN 数组 List Map
      1. JAVABEAN: 当sql需要的参数存在多个,并且为一个对象的不同属性,可以先把对个参数封装成javabean对象,然后作为一个入参传递 sql中占位符的名字需要匹配入参对象的属性名

        <select id="queryEmpByNameDeptno" parameterType="emp" resultType="Emp">
              select * from emp where ename=#{ename} and deptno = #{deptno}
          </select>

         

      2. 数组|list : sql需要的多个参数是同种类型,一个字段的多个值,适合使用数组|list,sql语句中需要使用foreach标签进行遍历

        <select id="queryEmpByidSome" resultType="Emp">
              select * from emp where empno in (
                  <foreach collection="array" item="item" separator=",">
                      #{item}
                  </foreach>
              )
          </select>

         

      3. Map:sql需要的多个参数,不属于一个对象的不不同属性值,可以封装为Map集合中的不同键值对sql中占位符的名字需要匹配键值对的key

        <select id="queryEmpBySalDeptno" parameterType="map" resultType="Emp">
              select * from emp where sal>#{sal} or deptno=#{deptno}
          </select>
        </mapper>

         

       

    3. 测试执行使用mybatis框架连接数据库,执行SQL语句,得到结果

      //1.加载XML核心配置文件
            InputStream is = Resources.getResourceAsStream("需要加载配置文件的文件名.xml");
            //2.创建SqlSessionFactory实例
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            //3.通过工厂获取回话SqlSession-->相当于Connection
            SqlSession session = factory.openSession();
            //4.执行指定的SQL语句
            //selectList("命名空间.id")
            List<Dept> list = session.selectList("需要执行的sql语句位置.sql语句id");
            //5.得到结果处理结果
            list.forEach(System.out::println);
            //6.关闭回话
            session.close();

配置文件的入参类型parameterType

    <!--查询-->
  <select id="queryAll" resultType="Dept">
      select * from dept
  </select>
  <!--insert-->
  <insert id="addDept">
      insert into dept values(88,'haha','shanghai')
  </insert>

  <delete id="deleteDept" parameterType="int">
      delete from dept where deptno = #{0}
  </delete>
 

 

接口绑定方案

致命三连

  1. 是什么:

  2. 为什么:可以得到接口类型的一个对象,方便方法的调用

  3. 怎么用:

流程

  1. 定义接口:接口名与映射文件名字保持一致,同时放在同一个包下

  2. 定义sql映射文件:

    1. SQL映射文件命名空间要求定义为: 与之绑定的接口的包名.文件名

    2. sql标签的id属性值要求与所对应的抽象方法的方法名保持一致

    3. SQL的参数与返回值要求与对应的抽象方法的参数与返回值保持一致

  3. 在核心配置文件中定义扫描接口方案

    <mappers>
          <!--扫描一个指定的接口-->
          <!--<mapper class="com.yjxxt.mappers.DeptMapper"/>-->
          <!--扫描一个包下的所有接口-->
          <package name="com.yjxxt.mappers"/>
      </mappers>

 

测试批量修改

 

注意

当进行批量插入,删除,修改时,显示操作行记录,可在数据库中没有修改,可能是没有设置事务提交,可在Utils工具包下设置自动提交事务

session = factory.openSession(true);

 

MyBatis 的Auto-Mapping(自动映射)机制

  1. 为什么:当我们查询的数据字段与Java中属性名不一致时可通过在映射文件中添加自动映射机制来相互匹配

  2. 字段名与属性名不一致情况解决方案

    1. 通过resultMap标签自定义表与javabean类型的映射情况

      1. 不同名的字段必须手动设置映射关系

        <!--自定义结果的映射关系-->
          <resultMap id="deptMap" type="Dept">
              <!--id : 定义主键字段与属性的映射关系-->
              <id column="deptno" property="id"/>
              <!--id : 定义非主键字段与属性的映射关系-->
              <result column="dname" property="name" />
              <!--<result column="loc" property="loc" />-->
          </resultMap>
        //使用定义好的映射规则
        <select id="queryAll" resultMap="deptMap">
              select * from dept
          </select>
      2. 同名的字段可以不设置,默认会根据自动映射机制找同名

    2. 为字段起别名

      1. 要求字段的别名与类型对应的属性名保持一致

      <!--别名实现-->
      <select id="queryAll" resultType="dept">
            select deptno id,dname name,loc from dept
        </select>
一对一(内置Javabean)
 <!--自定义结果集中的字段与javabean类中属性的映射关系
<resultMap id="EmpDept" type="Emp">
<!--主键字段与属性的映射关系-->
  <id column="empno" property="empno"></id>
  <!--非主键字段与属性的映射关系-->
  <result column="ename" property="ename"></result>
   
  <!--association : 定义javabean类型属性与字段的映射关系-->
  <association property="pddDept" javaType="Dept">
  <id property="id" column="deptno" />
      <result property="name" column="dname" />
  </association>
</resultMap>
一对多(内置集合类型)
<!--自定义结果的映射关系-->
<resultMap id="deptMap" type="Dept">
<!--id : 定义主键字段与属性的映射关系-->
<id column="deptno" property="id"/>
<!--result : 定义非主键字段与属性的映射关系-->
<result column="dname" property="name" />

<!--属性为List集合,使用collection标签定义 ofType:集合中数据的类型-->
<collection property="empList" javaType="List" ofType="Emp" >
<id property="empno" column="empno" />
  <result property="sal" column="sal" />
</collection>
</resultMap>

 

mybatis缓存机制

致命三连

  1. 是什么:将数据库信息加载到本地内存当中

  2. 为什么:减少与数据库交互,查询越多对缓存性能来说越高

一级缓存

  1. 默认开启. 线程级别的缓存, SqlSession 的缓存;

  2. 在一个 SqlSession 生命周期中有效. SqlSession 关闭,缓存清空;

  3. 在同一个 SqlSession 中, Mybatis 会把执行的方法和参数通过算法生成缓存的键值, 将键值和结果存放在一个 Map 中, 如果后续的键值一样, 则直接从 Map 中获取数据;

  4. 不同的 SqlSession 之间的缓存是相互隔离的;

  5. 用一个 SqlSession, 可以通过配置使得在查询前清空缓存;flushCache="true"

  6. 任何的 UPDATE, INSERT, DELETE 语句都会清空缓存。

二级缓存

  1. 进程级别的缓存, SqlSessionFactory 的缓存

  2. 在一个SqlSessionFactory生命周期中有效. 可以在多个SqlSession 生命中期中共享.

  3. 默认关闭, 需要使用的时候, 要为某个命名空间开启二级缓存(在 mapper.xml 中配置cache).

<!-- 开启二级缓存, 要求实体类进行序列化 -->
<cache />
  1. 由于在更新时会刷新缓存, 因此需要注意使用场合:查询频率很高, 更新频率很低时使用, 即经常使用 select, 相对较少使用delete, insert, update。

  2. 缓存是以 namespace 为单位的,不同 namespace 下的操作互不影响。但刷新缓存是刷新整个 namespace 的缓存, 也就是你 update 了一个, 则整个缓存都刷新了。

  3. 缓存是以 namespace 为单位的,不同 namespace 下的操作互不影响。但刷新缓存是刷新整个 namespace 的缓存, 也就是你 update 了一个, 则整个缓存都刷新了。

二级缓存应用场景

用于实时性不高的场景,可降低与数据库交互,提高获取信息速度。根据需求设置相应的flushInterval:刷新间隔时间,比如三十分钟,24小时等

posted @ 2022-04-10 23:02  hello罗先生  阅读(34)  评论(0)    收藏  举报