MyBatis_记录(四)
Posted 小企鹅推雪球!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis_记录(四)相关的知识,希望对你有一定的参考价值。
文章目录
文章目录Java Java
MyBatis foreach标签
- 对于一些 SQL 语句中含有 in 条件,需要迭代条件集合来生成的情况,可以使用 foreach 来实现 SQL 条件的迭代。
- Mybatis foreach 标签用于循环语句,支持了数据和 List、set 接口的集合,并对此提供遍历的功能
<foreach item="item" index="index" collection="list|array|map key" open="(" separator="," close=")">
参数值
</foreach>
- foreach 标签的属性
- item:表示集合中每一个元素进行迭代时的别名。
- index:指定一个名字,表示在迭代过程中每次迭代到的位置。
- open:表示该语句以什么开始(既然是 in 条件语句,所以必然以(开始)。
- separator:表示在每次进行迭代之间以什么符号作为分隔符(既然是 in 条件语句,所以必然以,作为分隔符)。
- close:表示该语句以什么结束(既然是 in 条件语句,所以必然以)开始)。
- 使用 foreach 标签时,最关键、最容易出错的是 collection 属性,该属性是必选的
- collection 主要有三种情况
- 如果传入的是单参数且参数类型是一个 List,collection 属性值为 list。
- 如果传入的是单参数且参数类型是一个 array 数组,collection 的属性值为 array。
- 如果传入的参数是多个,需要把它们封装成一个 Map,当然单参数也可以封装成 Map。Map 的 key 是参数名,collection 属性值是传入的 List 或 array 对象在自己封装的 Map 中的 key。
MyBatis foreach标签样例
- WebsiteMapper.xml
<select id="selectWebsite"
parameterType="net.biancheng.po.Website"
resultType="net.biancheng.po.Website">
SELECT id,name,url,age,country
FROM website WHERE age in
<foreach item="age" index="index" collection="list" open="("
separator="," close=")">
#{age}
</foreach>
</select>
- WebsiteMapper 类中相应方法
public List<Website> selectWebsite(List<Integer> ageList);
- 测试代码
public class Test {
public static void main(String[] args) throws IOException {
// 读取配置文件mybatis-config.xml
InputStream config = Resources.getResourceAsStream("mybatis-config.xml"); // 根据配置文件构建
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
// 通过SqlSessionFactory创建SqlSession
SqlSession ss = ssf.openSession();
List<Integer> ageList = new ArrayList<Integer>();
ageList.add(10);
ageList.add(12);
List<Website> siteList = ss.selectList("net.biancheng.mapper.WebsiteMapper.selectWebsite", ageList);
for (Website ws : siteList) {
System.out.println(ws);
}
}
}
- 在使用 foreach 标签时,应提前预估一下 collection 对象的长度。因为大量数据的 in 语句会影响性能,且还有一些数据库会限制执行的 SQL 语句长度。
MyBatis bind标签
- 每个数据库的拼接函数或连接符号都不同,例如 mysql 的 concat 函数、Oracle 的连接符号“||”等。SQL 映射文件就需要根据不同的数据库提供不同的实现,显然比较麻烦,且不利于代码的移植
- MyBatis 提供了 bind 标签来解决这一问题。
- bind 标签可以通过 OGNL 表达式自定义一个上下文变量。
- 按照网站名称进行模糊查询,SQL 映射文件如下
<select id="selectWebsite" resultType="net.biancheng.po.Website">
<bind name="pattern" value="'%'+_parameter+'%'" />
SELECT id,name,url,age,country
FROM website
WHERE name like #{pattern}
</select>
- bind元素属性:
- value:对应传入实体类的某个字段,可以进行字符串拼接等特殊处理。
- name:给对应参数取的别名。
- “_parameter”代表传递进来的参数,它和通配符连接后,赋给了 pattern,然后就可以在 select 语句中使用这个变量进行模糊查询
MyBatis bind标签样例
- WebsiteMapper 类中方法
public List<Website> selectWebsite(Website site);
- SQL 映射文件代码
<select id="selectWebsite" resultType="net.biancheng.po.Website">
<bind name="pattern_name" value="'%'+name+'%'" />
<bind name="pattern_url" value="'%'+url+'%'" />
SELECT id,name,url,age,country
FROM website
WHERE name like #{pattern_name}
AND url like #{pattern_url}
</select>
- 测试代码
public class Test {
public static void main(String[] args) throws IOException {
// 读取配置文件mybatis-config.xml
InputStream config = Resources.getResourceAsStream("mybatis-config.xml"); // 根据配置文件构建
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
// 通过SqlSessionFactory创建SqlSession
SqlSession ss = ssf.openSession();
Website site = new Website();
site.setname("编程");
site.setUrl("http");
List<Website> siteList = ss.selectList("net.biancheng.mapper.WebsiteMapper.selectWebsite", site);
for (Website ws : siteList) {
System.out.println(ws);
}
}
}
MyBatis trim标签
- trim 一般用于去除 SQL 语句中多余的 AND 关键字、逗号,或者给 SQL 语句前拼接 where、set 等后缀,可用于选择性插入、更新、删除或者条件查询等操作
- trim 语法格式如下:
<trim prefix="前缀" suffix="后缀" prefixOverrides="忽略前缀字符" suffixOverrides="忽略后缀字符">
SQL语句
</trim>
- trim 中属性如下:
- prefix:给SQL语句拼接的前缀,为 trim 包含的内容加上前缀
- suffix:给SQL语句拼接的后缀,为 trim 包含的内容加上后缀
- prefixOverrides:去除 SQL 语句前面的关键字或字符,该关键字或者字符由 prefixOverrides 属性指定。
- suffixOverrides:去除 SQL 语句后面的关键字或者字符,该关键字或者字符由 suffixOverrides 属性指定。
MyBatis trim标签样例
- WebsiteMapper.xml
<select id="selectWebsite" resultType="net.biancheng.po.Website">
SELECT id,name,url,age,country
FROM website
<trim prefix="where" prefixOverrides="and">
<if test="name != null and name !=''">
AND name LIKE CONCAT ('%',#{name},'%')
</if>
<if test="url!= null">
AND url like concat ('%',#{url},'%')
</if>
</trim>
</select>
- WebsiteMapper 类中方法
public List<Website> selectWebsite(Website website);
- 测试类代码
public class Test {
public static void main(String[] args) throws IOException {
// 读取配置文件mybatis-config.xml
InputStream config = Resources.getResourceAsStream("mybatis-config.xml"); // 根据配置文件构建
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
// 通过SqlSessionFactory创建SqlSession
SqlSession ss = ssf.openSession();
Website site = new Website();
site.setname("编程");
site.setUrl("http");
List<Website> siteList = ss.selectList("net.biancheng.mapper.WebsiteMapper.selectWebsite", site);
for (Website ws : siteList) {
System.out.println(ws);
}
}
}
MyBatis分页功能
- MyBatis 的分页功能是基于内存的分页,即先查询出所有记录,再按起始位置和页面容量取出结果。
- WebsiteMapper 中方法
/**
*
* @param site
* @param currentPageNo 起始位置
* @param pageSize 页面容量
* @return
*/
public List<Website> selectWebsite(@Param("site") Website site, @Param("from") Integer currentPageNo,
@Param("pageSize") Integer pageSize);
- 相比原来的 selectWebsite 方法,增加了两个参数,起始位置(from)和页面容量(pageSize),用于实现分页查询。
- 修改 WebsiteMapper.xml 的查询语句,增加 limit 关键字,SQL 映射代码
<select id="selectWebsite" resultType="net.biancheng.po.Website">
SELECT id,name,url,age,country
FROM website
<trim prefix="where" prefixOverrides="and">
<if test="site.name != null and site.name !=''">
AND name LIKE CONCAT ('%',#{site.name},'%')
</if>
<if test="site.url!= null and site.url !=''">
AND url LIKE CONCAT ('%',#{site.url},'%')
</if>
ORDER BY id limit #{from},#{pageSize}
</trim>
</select>
- 测试类代码
public static void main(String[] args) throws IOException {
// 读取配置文件mybatis-config.xml
InputStream config = Resources.getResourceAsStream("mybatis-config.xml");
// 根据配置文件构建
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
// 通过SqlSessionFactory创建SqlSession
SqlSession ss = ssf.openSession();
Website site = new Website();
// site.setname("编程");
site.setUrl("http");
Integer pageSize = 3;
Integer currentPageNo = 0;
List<Website> siteList = new ArrayList<Website>();
siteList = ss.getMapper(WebsiteMapper.class).selectWebsite(site, currentPageNo, pageSize);
for (Website ws : siteList) {
System.out.println(ws);
}
}
- MyBatis 实现分页查询属于 DAO 层操作,由于 DAO 层不牵涉任何业务实现,所以实现分页的方法中第一个参数为 limit 的起始位置(下标从 0 开始),而不是用户输入的真正页码(页码从1开始)
MyBatis缓存
- 缓存可以将数据保存在内存中,目前流行的缓存服务器有 MongoDB、Redis、Ehcache 等。
- 缓存是在计算机内存上保存的数据,读取时无需再从磁盘读入,因此具备快速读取和使用的特点。
- MyBatis 提供了一级缓存和二级缓存的支持。默认情况下,MyBatis 只开启一级缓存
MyBatis一级缓存
- 一级缓存是基于 PerpetualCache(MyBatis自带)的 HashMap 本地缓存,作用范围为 session 域内
- 当 session flush(刷新)或者 close(关闭)之后,该 session 中所有的 cache(缓存)就会被清空。
- 在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调用同一个 mapper 的方法,往往只执行一次 SQL。。因为使用 SqlSession 第一次查询后,MyBatis 会将其放在缓存中,再次查询时,如果没有刷新,并且缓存没有超时的情况下,SqlSession 会取出当前缓存的数据,而不会再次发送 SQL 到数据库
- SqlSession 是相互隔离的,如果使用不同的 SqlSession 对象,即使调用相同的 Mapper、参数和方法,MyBatis 还是会再次发送 SQL 到数据库执行,返回结果。
MyBatis二级缓存
- 二级缓存是全局缓存,作用域超出 session 范围之外,可以被所有 SqlSession 共享。
- 一级缓存缓存的是 SQL 语句,二级缓存缓存的是结果对象。
二级缓存的配置
- MyBatis 的全局缓存配置需要在 mybatis-config.xml 的 settings 元素中设置
<settings>
<setting name="cacheEnabled" value="true" />
</settings>
- 在 mapper 文件(如 WebMapper.xml)中设置缓存,默认不开启缓存。需要注意的是,二级缓存的作用域是针对 mapper 的 namescape 而言,即只有再次在 namescape 内(net.biancheng.WebsiteMapper)的查询才能共享这个缓存,
- mapper代码:
<mapper namescape="net.biancheng.WebsiteMapper">
<!-- cache配置 -->
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true" />
...
</mapper>
- eviction:代表的是缓存回收策略,目前 MyBatis 提供以下策略:
- LRU:使用较少,移除最长时间不用的对象
- FIFO:先进先出,按对象进入缓存的顺序来移除它们;
- SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
- WEAK:弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象
- flushInterval:刷新间隔时间,单位为毫秒,这里配置的是 100 秒刷新,如果省略该配置,那么只有当 SQL 被执行的时候才会刷新缓存。
- size:引用数目,正整数,代表缓存最多可以存储多少个对象,不宜设置过大。设置过大会导致内存溢出。这里配置的是 1024 个对象。
- readOnly:只读,默认值为 false,意味着缓存数据只能读取而不能修改,这样设置的好处是可以快速读取缓存,缺点是没有办法修改缓存。
- 在 mapper 文件配置支持 cache 后,如果需要对个别查询进行调整,可以单独设置 cache
<select id="getWebsiteList" resultType="net.biancheng.po.Website" usecache="true">
...
</select>
- MyBatis 缓存仅作了解因为面对一定规模的数据量,内置的 Cache 方式就派不上用场了,并且对查询结果集做缓存并不是 MyBatis 所擅长的,它专心做的应该是 SQL 映射。对于缓存,采用 OSCache、Memcached 等专门的缓存服务器来做更为合理。
以上是关于MyBatis_记录(四)的主要内容,如果未能解决你的问题,请参考以下文章
MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段
[mybatis]动态sql_sql_抽取可重用的sql片段