最近又遇到mybatis的问题了,所以把之前写的和补充的笔记一起放上来~
一、动态sql
在编写项目的时候经常需要拼接一些复杂的SQL语句,而拼接过程中很容易导致错误。而Mybatis的动态SQL功能正好能够解决这种问题,可以通过使用 if, choose, when, otherwise, trim, where, set, foreach标签,组合成非常灵活的SQL语句,进而提高开发人员的效率。下面解释一下这些标签:
if:和一般编程语言中的if相同,可用于判断。
choose、when、otherwise:用于条件选择。
trim、set、where:也属于判断元素或者属性的值
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除,即当WHERE后紧随AND或则OR的时候,就去除AND或者OR。而set 元素可以用于动态包含需要更新的列,而舍去其它的。用法如下:
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
foreach:通常用在需要对集合或者数组进行遍历的时候。foreach允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。
bind:bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。OGNL是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。
bind如下用来存取值,使用时直接调用设置的name就可以了:
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>
二、输入映射与输出映射
Mybatis中在使用sql语句时通常会有个返回值类型,当只是单个返回值时使用resultType,假如是多个返回值时,如列表,而列表里每个元素都是一个pojo,这个时候就要使用resultMap。
如上图就是定义一个resultMap,里面是什么由自己决定,column就是查询出的列名,property时对应的pojo属性名,而jdbcType是它们在数据库中的类型。
当我们在使用输出映射时即使用resultType时,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。如果查询出来的列名和pojo中的属性名全部不一致,则说明之前没有创建pojo对象,而且只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象,但部分值会为null,因为这部分的值和sql查询出来的值对应不上。
使用resultMap如果查询出来的列名和pojo的属性名不一致,可以通过定义一个resultMap对列名和pojo属性名之间作一个映射关系,即使用resultMap作为statement的输出映射类型。
三、一级缓存和二级缓存
使用缓存可以减少服务器的压力,避免了每次查询都需要进入数据库,可以直接利用缓存(在缓存生效时间下)获取数据。这里放一张Mybatis的缓存机制整体设计图:
Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存的作用域默认是一个SqlSession。所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。如上图所示,一级缓存只是本地缓存,而二级缓存就是全局缓存,二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。开启二级缓存需要进行配置,实现二级缓存的时候,MyBatis要求返回的pojo必须是可序列化的。 即要求实现Serializable接口,配置方法很简单,只需要在映射XML文件配置就可以开启缓存了<cache/>,如果我们配置了二级缓存就意味着:
1、映射语句文件中的所有select语句将会被缓存。
2、映射语句文件中的所有insert、update和delete语句会刷新缓存。
3、缓存会使用默认的Least Recently Used(LRU,最近最少使用的)算法来收回。
4、根据时间表,比如No Flush Interval,(CNFI没有刷新间隔),缓存不会以任何时间顺序来刷新。
5、缓存会存储列表集合或对象(无论查询方法返回什么)的1024个引用
6、缓存会被视为是read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全的被调用者修改,不干扰其他调用者或线程所做的潜在修改。
但这里也需要注意:
对于同一个Mapper来讲,只能使用一个Cache,当同时使用了cache和cache-ref时,cache定义的优先级更高。Mapper使用的Cache是与我们的Mapper对应的namespace绑定的,一个namespace最多只会有一个Cache与其绑定。