MyBatis笔记(4)-动态SQL与缓存
动态SQL
在前面,我们学习了MyBatis的获取参数的功能,通过获取参数可以实现SQL的动态变化。在MyBatis中,还提供一种根据特定条件动态拼接SQL语句的功能,利用不同功能的标签,来动态拼接SQL语句。
if
if标签中我们可以指定test条件,这是一个条件表达式,如果表达式的结果为true,则会将标签中的内容进行拼接,反之则不会拼接。
1 |
|
注意这里的test中,表达式之间的与和或的关系使用and
和or
来表示
上面的SQL语句拼接,每个条件都有可能不成立,就导致都无法进行拼接。但是where后面一定需要根据
where
上面的示例中,我们使用where 1=1
来避免全部条件不匹配时的SQL语句错误问题,不过在MyBatis中也提供了where标签来实现相应的功能。
1 |
|
where标签一般和if标签结合使用,它可以达到以下的效果:
- 如果where标签中的if条件都不满足,则where标签不会添加where关键字
- 如果where标签中的if条件满足,则where标签会自动添加where关键字,并且会将条件最前方多余的and去除,但是不能去除条件后方多余的and
trim
前面的where可以用于动态添加where关键字以及去除条件最前面多余的关键字,而trim标签可以提供更多的功能,用于删除或添加内容。
trim标签的常用属性如下:
prefix
:在trim标签包裹内容的前面添加某些内容prefixOverrides
:在trim标签包裹内容的前面删除某些内容suffix
:在trim标签包裹内容的后面添加某些内容suffixOverrides
:在trim标签包裹内容的后面删除某些内容
1 |
|
上面的动态SQL语句,可以自动添加where关键字,并删除最后多余的and关键字。
choose,when,otherwise
choose、when、otherwise标签三者通常结合使用,表示在多选一的情况。
1 |
|
foreach
foreach可以用来进行集合的展开,在批量操作中非常好用。
1 |
|
这里的分隔符前后会自动添加空格。
sql片段
SQL片段对应sql
标签,它用来记录一段公共的SQL片段,在需要使用的地方,通过include标签进行引入即可。
1 |
|
缓存
MyBatis中存在缓存机制,分为一级和二级缓存。同时MyBatis中也提供了整合第三方缓存的功能。
一级缓存
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存。下次查询相同的数据,则会直接命中缓存,不需要从数据库重新访问。不过会有一些情况使得一级缓存失效:
- 不同的SqlSession对应不同的一级缓存
- 使用了同一个SqlSession,但是查询条件不同,无法命中缓存
- 同一个SqlSession的两次查询期间执行了增删改操作,导致缓存与数据库不一致,缓存失效
- 同一个SqlSession的两次查询期间手动清空了缓存,调用了SqlSession的
clearCache()
方法
二级缓存
二级缓存是SqlSessionFactory级别的,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存。
二级缓存开启的条件如下:
- 在核心配置文件中,设置全局配置属性
cacheEnabled
为true,当然它的默认值就是true - 在映射文件中设置标签
<cache/>
- 二级缓存在SqlSession关闭或提交后有效,一级缓存对应的SqlSession关闭或提交后,才会存入二级缓存中
- 查询的数据所对应的实体类类型必须要实现序列化接口(与后面的只读属性有关)
如果两次查询之间执行了任意的增删改操作,会使得一级和二级缓存同时失效。在查询的时候,优先查询二级缓存,然后再查询一级缓存,最后查询数据库。
在映射文件的<cache/>
标签中可以设置二级缓存的相关属性:
eviction
:缓存回收策略,可选值如下,默认值为LRU
LRU
:最近最少使用策略FIFO
:先进先出策略SOFT
:软引用WEAK
:弱引用
flushInterval
:表示缓存刷新间隔,单位为ms。默认情况没有设置,表示没有刷新间隔,在调用语句的时候刷新size
:表示引用数目,为正整数。代表缓存最多可以存储对象的个数,如果设置的过大容易导致内存溢出readOnly
:表示是否只读,可选值为true|false
,默认值为false
true
:只读缓存。在缓存命中的时候会给所有调用者返回缓存对象的相同示例,因此这些对象不能被修改。这种情况下性能更优。false
:读写缓存。在缓存命中的时候返回缓存对象的拷贝,因此需要对象实现序列化。这种情况下的性能差一些,但是更加安全。