SQL动态查询
if标签
当传递某个DTO时,需要根据某个属性是否存在而动态增加条件时,就可以使用if标签
xml
<select id="getUser" resultType="user">
select id, name, age, sex from user where 1=1
<if test="userDto.name != null and userDto.name !=''">
AND name = #{userDto.name}
</if>
<if test="userDto.age != null">
AND age = #{userDto.age}
</if>
</select>
如果test中的条件判断通过,则会将if标签中的内容拼接到前面的sql语句中,否则就不做处理
[!warning]
if标签中的test检测语句和if标签中的sql语句中不能出现<符号表示小于
因为<符号在xml文件中代表的是标签的开始
如果是test中,可以使用!进行反转; 如果在if标签中的sql语句,需要使用CDATA标签进行包裹,比如
xml<if test="userDto.age != null and !userDto.age >20"> <![CDATA[ AND age <= #{userDto.age} ]]> </if>
where标签
类似于上一段代码,书写 where 1=1 这样的语句时不规范的,所以就可以使用where标签代替
xml
<select id="getUser" resultType="user">
select id, name, age, sex from user
<where>
<if test="userDto.name != null and userDto.name !=''">
AND name = #{userDto.name}
</if>
<if test="userDto.age != null">
AND age = #{userDto.age}
</if>
</where>
</select>
如果if中的条件成立,则sql语句将会是select id, name, age, sex from user where name =? and age = ?
如果都不成立,则时期类语句是select id, name, age, sex from user
使用where标签时,会自动将第一个条件的 AND
或者 OR
替换掉
sql标签
如果在多个查询中存在校相同的sql片段,则可以使用sql标签抽取出来
xml
<sql id="columns" >
id, name, age, sex
</sql>
<select id="getUser" resultType="user">
select
<include refid="columns"/>
from user
</select>
在需要使用要这个sql片段的地方使用inclued标签进行引用
set标签
set标签使用在更新操作中,对应sql语句中的set
xml
<update id="updateUser">
update user
<set>
<if test="userDto.name != null and userDto.name !=''">
name = #{userDto.name},
</if>
<if test="userDto.age != null">
age = #{userDto.age},
</if>
</set>
</update>
set标签还具有省略sql语句嘴鸥一个后缀的功能,对应的sql为 update user set name = ?, age = ?
trim标签
Mybatis提供了trim标签来代替where和set标签
xml
<select id="getUser" resultType="user">
select id, name, age, sex from user
<trim prefix="where" prefixOverrides="AND">
<if test="userDto.name != null and userDto.name !=''">
AND name = #{userDto.name}
</if>
<if test="userDto.age != null">
AND age = #{userDto.age}
</if>
</trim>
</select>
trim 标签有四个属性 prefix(前缀) prefixOverrides(被替代的前缀) suffix(后缀) suffixOverrides(被替代的后缀)
比如上面的sql语句, 对应的是 select id, name, age, sex from user where name =? and age = ?
被替代的前缀是 AND
,替换为了前缀 where
,同理还可以用在set标签中替换最后一个逗号
foreach标签
循环标签通常用于插入、删除、更新和查询操作
xml
<insert id="saveUser">
insert into user(name, age)
values
<foreach collection="userList" item="user" separator=",">
(#{user.name}, #{user.age})
</foreach>
</insert>
<!------------------------------------------------------------------------------------>
<select id="getUsers" resultType="user">
select * from user where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
foreach提供了六个标签,分别是
- collection(传入的集合/数组)
- itme(集合/数组中的元素)
- separator(元素之间的分割符)
- open(开始符号)
- close(结束符号)
- index(元素下标,不经常使用)
第一句对应的sql是 insert into user(name, age) values(?,?),(?,?)...
第二局对应的sql是 select* from user where id in (?,?,?,?...)
Mybatis缓存
缓存就是存储在内存中的临时数据,将用户经常查询的数据放在缓存(内存)中,用户再次查询数据的时候就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,能够提高查询效率,解决了高并发系统的性能问题
优势:减少和数据库的交互次数,减少系统开销,提高系统效率
使用场景:经常查询并且不经常改变的数据
Mybatis提供了两级缓存:一级缓存和二级缓存
- 一级缓存是Sqlsession级别的缓存(本地缓存),默认开启,同一个SqlSession执行同构查询的时候,结果放入一级缓存
- 二级缓存是SqlSessionFactory级别的缓存,需要手动开启,同一个SqlSessionFactory构建的SqlSession执行同构查询,如果SqlSession关闭,查询结果保存在二级缓存中
全局缓存配置
xml
<!-- config.xml -->
<settings>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
Mapper中的配置
readOnly:只读
flushInterval:刷新时间,单位为毫秒
size:缓存的数据条目
eviction:缓存淘汰策略
LRU:最近最少使用回收,移除最长时间不被使用
FIFO:先进先出,按照缓存进入的顺序进行移除
SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
WEAK:弱引用,更积极的移除基于垃圾收集器和弱引用规则的对象
xml
<cache flushInterval="300000" readOnly="true" size="10000" eviction="LRU"/>
标签中的设置
设置属性useCache="true"
xml
<select id="getUsersInclude" resultMap="map2" useCache="true">
。。。。。
</select>
当开启二级缓存之后,在控制台可以看到Cache Hit Ratio [cn.cnmd.mapper.UserMapper]: 0.5
,代表缓存命中率
缓存命中率 = 缓存中查询数 总查询数 缓存命中率 = \frac{缓存中查询数}{总查询数} 缓存命中率=总查询数缓存中查询数
分页插件Page-Helper
maven配置
xml
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.1</version>
</dependency>
插件配置
xml
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper"/>
</plugins>
代码
java
SqlSession session = MybatisUtil.getSession();
PersonMapper mapper = session.getMapper(PersonMapper.class);
PageHelper.startPage(1, 5);//这一步必须在调用方法之前进行
List<Person> person = mapper.getPerson();
PageInfo<Person> pageInfo = new PageInfo<>(person);//查询出的数据必须封装在PageInfo对象中
System.out.println("总条数:" + pageInfo.getTotal());
System.out.println("总页数:" + pageInfo.getPages());
pageInfo.getList().forEach(System.out::println);// 当前页数据展示
结果
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1f59a598]
==> Preparing: SELECT count(0) FROM rbac.simple_table
==> Parameters:
<== Columns: count(0)
<== Row: 32
<== Total: 1
==> Preparing: SELECT * from rbac.simple_table LIMIT ?
==> Parameters: 5(Integer)
<== Columns: id, name, age, gender
<== Row: 1, 张三, 25, 男
<== Row: 2, 李四, 30, 女
<== Row: 3, 王五, 22, 男
<== Row: 4, 赵六, 28, 女
<== Row: 5, 孙七, 35, 男
<== Total: 5
总条数:32
总页数:7
Person(id=1, name=张三, age=25, gender=男)
Person(id=2, name=李四, age=30, gender=女)
Person(id=3, name=王五, age=22, gender=男)
Person(id=4, name=赵六, age=28, gender=女)
Person(id=5, name=孙七, age=35, gender=男)
配置数据源 Druid
maven配置
xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.20</version>
</dependency>
创建 DruidDataSourceFactory, 并继承 PooledDataSourceFactory,并替换数据源
java
public class DruidDataSourceFactory extends PooledDataSourceFactory {
public DruidDataSourceFactory() {
this.dataSource = new DruidDataSource();//替换数据源
}
}
xml
<dataSource type="cn.cnmd.dataSource.DruidDataSourceFactory">
<!--1.3配置连接池需要的参数-->
<!--修改为druid数据源时,一定要把driver修改为 driverClassName才能生效-->
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
控制台出现字样说明配置成功
七月 10, 2024 5:43:47 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
Row: 3, 王五, 22, 男
<== Row: 4, 赵六, 28, 女
<== Row: 5, 孙七, 35, 男
<== Total: 5
总条数:32
总页数:7
Person(id=1, name=张三, age=25, gender=男)
Person(id=2, name=李四, age=30, gender=女)
Person(id=3, name=王五, age=22, gender=男)
Person(id=4, name=赵六, age=28, gender=女)
Person(id=5, name=孙七, age=35, gender=男)
# 配置数据源 Druid
### maven配置
```xml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.20</version>
</dependency>
创建 DruidDataSourceFactory, 并继承 PooledDataSourceFactory,并替换数据源
java
public class DruidDataSourceFactory extends PooledDataSourceFactory {
public DruidDataSourceFactory() {
this.dataSource = new DruidDataSource();//替换数据源
}
}
xml
<dataSource type="cn.cnmd.dataSource.DruidDataSourceFactory">
<!--1.3配置连接池需要的参数-->
<!--修改为druid数据源时,一定要把driver修改为 driverClassName才能生效-->
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
控制台出现字样说明配置成功
七月 10, 2024 5:43:47 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited