Mybatis之动态sql、缓存、分页、配置数据源

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

相关推荐
Frank牛蛙7 小时前
1.每日SQL----2024/11/7
数据库·sql
上海_彭彭7 小时前
【提效工具开发】Python功能模块执行和 SQL 执行 需求整理
开发语言·python·sql·测试工具·element
成富12 小时前
文本转SQL(Text-to-SQL),场景介绍与 Spring AI 实现
数据库·人工智能·sql·spring·oracle
songqq2712 小时前
SQL题:使用hive查询各类型专利top 10申请人,以及对应的专利申请数
数据库·sql
鹿屿二向箔13 小时前
基于SSM(Spring + Spring MVC + MyBatis)框架的汽车租赁共享平台系统
spring·mvc·mybatis
材料苦逼不会梦到计算机白富美13 小时前
golang分布式缓存项目 Day 1
分布式·缓存·golang
Java 第一深情13 小时前
高性能分布式缓存Redis-数据管理与性能提升之道
redis·分布式·缓存
HBryce2414 小时前
缓存-基础概念
java·缓存
时差95315 小时前
【面试题】Hive 查询:如何查找用户连续三天登录的记录
大数据·数据库·hive·sql·面试·database