动态SQL与分页插件
动态SQL与分页插件
1 动态SQL
MyBatis的映射文件中支持在基础SQL上添加一些逻辑操作,并动态拼接成完整的SQL之后再执行,以达到SQL复用、简化编程的效果。
- 动态查询 where标签和if标签组合使用
- 动态修改
1.1 < sql >
sql标签的作用是提取公共的sql代码片段
- sql id属性:唯一标识
- include refid属性:参照id
<!-- 定义SQL片段:抽取公共的SQL语句 -->
<sql id="product_col">
p_id pid,t_id tid ,p_name name ,p_time time ,p_image image,
p_price price, p_info info , isdel,p_state state
</sql>
<select id="selectAll" resultType="product">
select <include refid="product_col"/> from product
</select>
动态查询
1.2 < if >
if标签的作用适用于条件判断
<if test="判断条件"> 在test属性中获取对象属性值的时候,不需要#{} </if>
- test 属性:判断条件(必填)
<!--
if标签用于判断使用
注意:
1、在test中获取属性值的时候,不需要加上#{},在sql语句中获取属性值要加上#{}
2、在sql语句中进行使用特殊字符,最好不要使用 > 或者 <,应该使用 > <
-->
<select id="selectByCondition" resultType="product">
select <include refid="productSql"/> from product where 1 = 1
<if test="name != null">
and p_name like concat('%',#{name},'%')
</if>
<if test="time != null">
and p_time > #{time}
</if>
<if test="price != null">
and p_price > #{price}
</if>
<if test="state != null">
and p_state > #{state}
</if>
</select>
1.3 < where >
where 标签作用是添加where条件。一般和if标签配合使用
- 如果没有条件,不会加上where。
- 会自动去掉前的and、or、not等关键字
<!--
where标签用于添加where条件
特点:
1、如果where有条件自动加上where关键字,如果没有则不会where关键字
2、会自动去除前面的and或者or等关键字
-->
<select id="selectByCondition" resultType="product">
select <include refid="productSql"/> from product
<where>
<if test="name != null">
and p_name like concat('%',#{name},'%')
</if>
<if test="time != null">
and p_time > #{time}
</if>
<if test="price != null">
and p_price > #{price}
</if>
<if test="state != null">
and p_state > #{state}
</if>
</where>
</select>
1.4 < set >
set 标签的作用是添加set,与where类似
<!-- set标签用于添加修改的字段值
特点:
1、如果set有条件自动加上set关键字,如果没有则不会set关键字
2、会自动去除后面的,
-->
<update id="updateByCondition">
update product
<set>
<if test="name != null">
p_name = #{name},
</if>
<if test="time != null">
p_time = #{time},
</if>
<if test="state != null">
p_state = #{state},
</if>
<if test="price != null">
p_price = #{price},
</if>
p_id = #{pid}
</set>
where p_id = #{pid}
</update>
1.5 < choose >
choose标签作用是条件选择。类似于Java中的多重if
- choose 、when 、otherwise
<!--
choose、when、otherwise标签用于多值判断使用类似于java中的switch...case
-->
<select id="selectOrderByCondition" resultType="product">
select <include refid="productSql"/> from product order by
<choose>
<when test="price != null">
p_price desc
</when>
<when test="time != null">
p_time desc
</when>
<when test="state != null">
p_state desc
</when>
<otherwise>
p_id desc
</otherwise>
</choose>
</select>
1.6 < trim >
< trim prefix=“” suffix=“” prefixOverrides=“” suffixOverrides=“” >代替< where > 、< set >
- prefix 前缀
- suffix 后缀
- prefixOverrides 前缀覆盖
- suffixOverrides 后缀覆盖
<!--
trim:用灵活的定义任意的前缀和后缀,以及覆盖多余前缀和后缀
-->
<update id="updateByCondition">
update product
<trim prefix="set" suffixOverrides=",">
<if test="name != null">
p_name = #{name},
</if>
<if test="time != null">
p_time = #{time},
</if>
<if test="state != null">
p_state = #{state},
</if>
<if test="price != null">
p_price = #{price},
</if>
p_id = #{pid}
</trim>
where p_id = #{pid}
</update>
1.7 < foreach >
foreach 标签的作用是遍历集合或者数组
参数 | 描述 | 取值 |
---|---|---|
collection | 容器类型 | list、array、map(可以在形参上加注解改变名称) |
open | 起始符 | ( |
close | 结束符 | ) |
separator | 分隔符 | , |
index | 下标号 | 从0开始,依次递增 |
item | 当前项 | 任意名称(循环中通过 #{任意名称} 表达式访问) |
案例1:批量增加
<!-- insert into 表名 (字段名1,字段名2,...) values (值1,...),(值1,...) ,(值1,...) -->
<insert id="insertProduct">
insert into product (p_name,p_time,p_state,p_price) values
<foreach collection="productList" item="product" separator=",">
(#{product.name},#{product.time},#{product.state},#{product.price})
</foreach>
</insert>
案例2:批量删除
<!-- delete from 表名 where p_id in (id1,id2,..) -->
<delete id="deleteProduct">
delete from product where p_id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
2 mybatis缓存
mybatis一共有两级缓存,分别是一级缓存和二级缓存。默认开启了一级缓存
2.1 一级缓存
一级缓存是mybatis中默认开启的
生命周期:在同一个SqlSession下
- 一级缓存何时生效
- 默认生效
- 一级缓存何时失效
- 1、两次查询使用不是同一个SqlSession
- 2、手动将缓存清空
- 3、当sqlSession关闭之后
- 4、当两次查询操作中间,如果执行了增删改的操作,缓存失效
2.2 二级缓存
mybatis中二级缓存是需要手动开启
生命周期: 二级缓存是在namespace级别
- 二级缓存生效:
- 1、在主配置文件中开启二级缓存
- 2、在mapper映射文件中添加标签
- 3、在查询之间,SqlSession需要提交
- 4、如果没有缓存配置,那么这个类需要实现序列化接口
- 二级缓存失效
- 1、当两次查询操作中间,如果执行了增删改的操作,二级缓存失效
开启二级缓存
<configuration>
<!-- 开启二级缓存(当前这个版本是默认开启的) -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
...
</configuration>
mapper映射配置缓存
<!--
eviction:缓存淘汰策略 FIFO(先进先出) LRU(最近最少使用)
flushInterval:缓存的刷新时间
size:缓存的大小
readOnly:缓存只读
-->
<cache eviction="LRU"
flushInterval="60000"
size="512"
readOnly="true"/>
3 分页插件
3.1 概念
PageHelper是适用于MyBatis框架的一个分页插件,使用方式极为便捷,支持任何复杂的单表、多表分页查询操作。
3.2 访问与下载
官方网站:https://pagehelper.github.io/
下载地址:https://github.com/pagehelper/Mybatis-PageHelper
3.3 开发步骤
3.3.1 引入依赖
pom.xml中引入PageHelper依赖。
<!-- 引入分页插件依赖 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
3.3.2 配置MyBatis-config.xml
在MyBatis-config.xml中添加< plugins >。
<configuration>
<typeAliases></typeAliases>
<plugins>
<!-- 添加分页拦截器查询 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<environments>...</environments>
</configuration>
3.3.3 PageHelper使用
@Test
public void test01() throws IOException {
SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
SqlSessionFactory sf = sfb.build(Resources.getResourceAsReader("mybatis-config.xml"));
SqlSession sqlSession = sf.openSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
//在查询之前执行!!!!
PageHelper.startPage(3,3);
List<Emp> empList = empMapper.getAll();
PageInfo pageInfo = new PageInfo(empList);
//empList.stream().forEach(System.out::println);
System.out.println(pageInfo);
}
3.4 PageInfo对象
PageInfo对象中包含了分页操作中的所有相关数据。
PageInfo结构图 |
---|
![]() |
3.4.1 PageInfo应用方式
使用PageInfo保存分页查询结果。
/**
* 分页插件(物理分页 (sql语句中添加limit))
* 1、导入pageHelper依赖
* 2、在mybatis核心配置文件中添加插件(配置分页拦截器)
* 3、在执行查询操作之前执行 PageHelper.startPage(当前页,每页条数)
* 4、如果要获取完整结果,创建一个PageInfo对象即可(PageInfo pageInfo = new PageInfo(empList);)
*/
//创建一个分页信息类
PageInfo<Product> pageInfo = new PageInfo<>(productList);