02 Mybatis学习笔记

Mybatis学习笔记

结果映射(resultMap)

  • association

    – 一个复杂类型的关联;许多结果将包装成这种类型

    • 嵌套结果映射 – 关联可以是 resultMap 元素,或是对其它结果映射的引用
  • collection

    – 一个复杂类型的集合

    • 嵌套结果映射 – 集合可以是 resultMap 元素,或是对其它结果映射的引用

SQL:

CREATE table `teacher`(
  `id` int(10) not null ,
  `name` varchar(30) default null,
  primary key (`id`)
)engine=INNODB default charset =utf8;

insert into teacher() values (1,"贾老板");

create table `student`(
  `id` int(10) not null ,
  `name` varchar(30) default null,
  `tid` int(10) default null,
  primary key (id),
  key  `fktid` (`tid`),
  constraint `fktid` foreign key (`tid`) references `teacher`(`id`)
)engine = innodb default charset = utf8;

insert into `student` values (1,'小白',1),(2,'小于',1),(3,'小红',1),(4,'小蓝',1),(5,'小黑',1),(6,'小花',1);

多对一的形式

测试环境搭建

  1. 导入lombok

  2. 新建实体类Teacher、Student

  3. 建立Mapper接口

  4. 建立Mapper.xml文件

    按照子查询

    <select id="getStudent" resultMap="Student_tea">
        select * from mybatis.student
    </select>
    <resultMap id="Student_tea" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--复杂的属性需要单独处理
                对象:association
                集合:collection
            -->
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>
    <select id="getTeacher" resultType="Teacher">
        select * from mybatis.teacher where id=#{id}
    </select>
    

    按照结果查询

    <select id="getStudent2" resultMap="Student_tea2">
        select s.id sid, s.name sname, t.name tname
        from student s,teacher t
        where s.tid = t.id
    </select>
    <resultMap id="Student_tea2" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="Teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>
    
  5. 在核心被配置文件注册我们的Mapper接口或者文件

  6. 测试

一对多的形式

测试环境搭建**

  1. 导入lombok

  2. 新建实体类Teacher、Student

  3. 建立Mapper接口

  4. 建立Mapper.xml文件

    按照结果查询

    <select id="getTeacherById" resultMap="TeacherStudent">
        select s.id sid, s.name sname, t.name tname, t.id tid
        from mybatis.student s, mybatis.teacher t
        where s.tid = t.id and tid = #{tid}
    </select>
    
    <resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <!--复杂的属性,需要单独处理 对象:associate 集合:collection
                javaType="" 指定属性的类型
                集合中泛型信息,我们使用ofType获取
            -->
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>
    
  5. 在核心被配置文件注册我们的Mapper接口或者文件

  6. 测试

回顾Mysql多对一进行查询

  • 子查询
  • 联表查询

总结

  1. 关联 - associate【多对一】
  2. 集合 - collection 【一对多】
  3. JavaType & ofType
    1. javaType用来指定实体类中属性的类型
    2. ofType用来指定映射到List或者集合中的pojo类型,泛型中的约束类型

动态SQL

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

https://mybatis.org/mybatis-3/zh/dynamic-sql.html

If

<select id = "queryBlog" parameterType="map" resultType="blog">
	SELECT * FROM User WHERE  1=1
    <if test="title != null">
        and title=#{title}
    </if> 
</select>

choose,when,otherwise

它有点像 Java 中的 switch 语句。whenotherwise是choose中的标签

choose类似于switch

when类似于case

otherwise类似于default

trim,where,set

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

<where></where> 注意where中的第一个sql语句不用添加and,其他的需要在开头添加and

set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号

<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>

SQL片段

有时候,可能将一些功能的部分抽取出来,方便复用

  1. 使用SQL标签抽取公共部分

    <sql id="if-title-author">
        <if test="title != null">
        	title = #{title}
        </if>
    </sql>
    
  2. 需要使用的地方使用include标签

    <select id ="queryBlog" parametertype="map" resultType="blog">
    	<where>
        	<include refid="if-title-author"/>
        </where>
    </select>
    

注意事项:

  • 最好基于单表来定义SQL片段
  • 不要存在Where标签

foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。比如:

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!

提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

至此,我们已经完成了与 XML 配置及映射文件相关的讨论。下一章将详细探讨 Java API,以便你能充分利用已经创建的映射配置。

Mybatis缓存

简介

  1. 什么是缓存[Cache]?
    • 存在内存中的临时数据
    • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决高并发系统的性能问题
  2. 为什么使用缓存?
    • 减少和数据库的交互次数,减少系统开销,提高系统效率
  3. 什么样的数据能使用缓存?
    • 经常查询且不经常改变的数据【可以使用缓存】

MyBatis缓存

  • MyBatis包含一个非常强大的查询缓存特性,它可以非常方便的定制和配置缓存。缓存可以极大的提升查询效率
  • MyBatis系统中默认定义了两级缓存:一级缓存二级缓存
    • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
    • 二级缓存需要手动开启和配置,它是基于namespace级别的缓存
    • 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来定义二级缓存

一级缓存

也成为本地缓存

  • 与数据库同一次会话期间查询到的数据会放在本地缓存中
  • 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库

二级缓存

  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存
  • 工作机制
    • 一个会话查询一条数据,这个数据就会被放在当前的一级缓存中
    • 如果当前会话关闭了,这个会话对应的一级缓存就没了,但是想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中
    • 新的会话查询信息,就可以从二级缓存中获取内容
    • 不同的mapper查出的数据会放在自己对应的缓存(map)中

步骤:

  1. 开启全局缓存

    <!--显示开启全局缓存-->
    <setting name="cacheEnabled" value="true">
    
  2. 在要使用二级缓存的Mapper中开启

    <!--在当前Mapper.xml中使用二级缓存-->
    <cache/>
    

    也可以自定义参数

    <cache
      eviction="FIFO"
      flushInterval="60000"
      size="512"
      readOnly="true"/>
    
  3. 测试

    1. 问题:我们需要将实体类序列化,否则将会报错

      Caused by: java.io.NotSerializableException:com.xdu.pojo.User
      

小结:

  • 只要开启二级缓存,在同一个Mapper下就有效
  • 所有的数据都会先放在一级缓存中
  • 只有会话提交,或者关闭的时候,才会提交到二级缓存中

缓存顺序:

  1. 先走二级缓存(Mapepr)

     			2. 如果没有二级缓存,再走一级缓存(SqlSession)
     			3. 如果没有一级缓存,再走数据库
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值