力扣MyBatis框架 三万多字干货,来了解一下?(四)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
日志服务 SLS,月写入数据量 50GB 1个月
简介: 力扣MyBatis框架 三万多字干货,来了解一下?

七、动态SQL


简介

  • 动态 SQL 是 MyBatis 的强大特性之一
  • 动态 SQL 用来拼接 SQL 语句


新实体类


Book

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
    private String id;
    private String name;
    private double money;
    private Date buyDate;
}


IF


mapper接口

public interface BookMapper {
    /**
     * if 标签测试
     *
     * 模拟查询书名和比某价格便宜的书
     * 两个条件都看
     */
    List<Book> findBookByNameAndMoney(@Param("name") String name, @Param("money") Double money);
}


XML具体实现

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="zwz.mapper.BookMapper">
    <select id="findBookByNameAndMoney" resultType="book">
        select * from book
        where 1 = 1
        <if test="name != ''">
            and name like #{name}
        </if>
        <if test="money != 0.0">
            and money &lt; #{money}
        </if>
    </select>
</mapper>


测试

/**
 * 模拟查询书名和比某价格便宜的书
 * 如果name为空   忽略
 * 如果价格为0.0  忽略
 */
@Test
public void testDynamicChoose(){
    SqlSession session = MybatisUtils.getSqlSession();
    BookMapper mapper = session.getMapper(BookMapper.class);
    List<Book> books = mapper.findBookByNameOrMoney("%设计%", 80.0);
    for (Book book : books) {
        System.out.println(book);
    }
}


Choose

public interface BookMapper {
    /**
     * choose 标签测试
     *
     * 模拟查询书名和比某价格便宜的书
     * 如果姓名不为空,只看姓名
     * 如果姓名为空,就看价格
     *
     * @param name
     * @param money
     * @return
     */
    List<Book> findBookByNameOrMoney(@Param("name") String name, @Param("money") Double money);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="zwz.mapper.BookMapper">
    <select id="findBookByNameOrMoney" resultType="book">
        select * from book
        where 1 = 1
        <choose>
            <when test="name != ''">
                and name like #{name}
            </when>
            <when test="money != 0.0">
                and money &lt; #{money}
            </when>
            <otherwise>
                and 1 = 1
            </otherwise>
        </choose>
    </select>
</mapper>
/**
 * 模拟查询书名和比某价格便宜的书
 * 如果name为空   忽略
 * 如果价格为0.0  忽略
 */
@Test
public void testDynamicChoose(){
    SqlSession session = MybatisUtils.getSqlSession();
    BookMapper mapper = session.getMapper(BookMapper.class);
    List<Book> books = mapper.findBookByNameOrMoney("%设计%", 80.0);
    for (Book book : books) {
        System.out.println(book);
    }
}


Foreach

public interface BookMapper {
    /**
     * foreach 标签测试
     *
     * 查询指定书名的书列表
     *
     * @param books
     * @return
     */
    List<Book> findInName(@Param("books") List<String> books);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="zwz.mapper.BookMapper">
    <select id="findInName" resultType="book" parameterType="list">
        select * from book
        where 1 = 1 and name in
        <foreach collection="books" index="index" item="item" open="(" close=")" separator=",">
            #{item}
        </foreach>
    </select>
</mapper>
/**
 * 查询指定书名的书列表
 */
@Test
public void testDynamicForeach(){
    SqlSession session = MybatisUtils.getSqlSession();
    BookMapper mapper = session.getMapper(BookMapper.class);
    List<String> bookNames = new ArrayList<>();
    bookNames.add("JavaScript程序设计");
    bookNames.add("JAVA程序设计");
    bookNames.add("C++程序设计");
    List<Book> books = mapper.findInName(bookNames);
    for (Book book : books) {
        System.out.println(book);
    }
}



八、缓存


8.1 一级缓存


MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制

默认情况下,只启用了本地的会话缓存(一级缓存),它仅仅对一个会话中的数据进行缓存


  • 映射语句文件中的所有 select 语句的结果将会被缓存。
  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
  • 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
  • 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
  • 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。


比如两次查询同样的用户,可以发现系统只执行了一次SQL指令

@Test
public void testCache1(){
    SqlSession session = MybatisUtils.getSqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    // 第一次查询
    User user = mapper.findUserById("7a0f791f1e7b416ea01b860470fa9aeb");
    System.out.println(user);
    System.out.println("+++++++++++++++++++++++++++++++++++++++");
    // 第二次查询
    User user2 = mapper.findUserById("7a0f791f1e7b416ea01b860470fa9aeb");
    System.out.println(user2);
    System.out.println(user == user2);
    session.close();
}


输出日志如下

Created connection 508512860.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e4f4a5c]
==>  Preparing: select * from user where id = ?; 
==> Parameters: 9e3eed6af6da4214b520535cac13f13a(String)
<==    Columns: id, name, age
<==        Row: 9e3eed6af6da4214b520535cac13f13a, ZWZ1改, 18
<==      Total: 1
User(id=9e3eed6af6da4214b520535cac13f13a, name=ZWZ1改, age=18)
+++++++++++++++++++++++++++++++++++++++
User(id=9e3eed6af6da4214b520535cac13f13a, name=ZWZ1改, age=18)
true
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e4f4a5c]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e4f4a5c]
Returned connection 508512860 to pool.
Process finished with exit code 0


8.2 二级缓存


关闭二级缓存

如果没有开启二级缓存,在两个不同的SqlSession中发起查询,系统会执行两次SQL指令

@Test
public void testCache2(){
    SqlSession session1 = MybatisUtils.getSqlSession();
    UserMapper2 mapper1 = session1.getMapper(UserMapper2.class);
    User2 user1 = mapper1.findUserById("9e3eed6af6da4214b520535cac13f13a");
    session1.close();
    SqlSession session2 = MybatisUtils.getSqlSession();
    UserMapper2 mapper2 = session2.getMapper(UserMapper2.class);
    User2 user2 = mapper2.findUserById("9e3eed6af6da4214b520535cac13f13a");
    session2.close();
}


输出日志如下

Created connection 2075952726.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7bbc8656]
==>  Preparing: select * from user where id = ?; 
==> Parameters: 9e3eed6af6da4214b520535cac13f13a(String)
<==    Columns: id, name, age
<==        Row: 9e3eed6af6da4214b520535cac13f13a, ZWZ1改, 18
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7bbc8656]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7bbc8656]
Returned connection 2075952726 to pool.
Opening JDBC Connection
Checked out connection 2075952726 from pool.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7bbc8656]
==>  Preparing: select * from user where id = ?; 
==> Parameters: 9e3eed6af6da4214b520535cac13f13a(String)
<==    Columns: id, name, age
<==        Row: 9e3eed6af6da4214b520535cac13f13a, ZWZ1改, 18
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7bbc8656]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7bbc8656]
Returned connection 2075952726 to pool.
Process finished with exit code 0


开启二级缓存


在mybatis-config.xml中配置全局缓存

<settings>
    <!--开启日志-->
    <setting name="logImpl" value="STDOUT_LOGGING"/>
    <!--驼峰转换-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!-- 开启全局缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>


在mapper层xml中,配置cache

<cache eviction="FIFO"
       flushInterval="60000"
       size="512"
       readOnly="true"/>


测试

@Test
public void testCache2(){
    SqlSession session1 = MybatisUtils.getSqlSession();
    UserMapper2 mapper1 = session1.getMapper(UserMapper2.class);
    User2 user1 = mapper1.findUserById("9e3eed6af6da4214b520535cac13f13a");
    session1.close();
    SqlSession session2 = MybatisUtils.getSqlSession();
    UserMapper2 mapper2 = session2.getMapper(UserMapper2.class);
    User2 user2 = mapper2.findUserById("9e3eed6af6da4214b520535cac13f13a");
    session2.close();
}


从日志输出中可以发现,系统只执行了一次SQL指令

Created connection 307829448.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@12591ac8]
==>  Preparing: select * from user where id = ?; 
==> Parameters: 9e3eed6af6da4214b520535cac13f13a(String)
<==    Columns: id, name, age
<==        Row: 9e3eed6af6da4214b520535cac13f13a, ZWZ1改, 18
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@12591ac8]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@12591ac8]
Returned connection 307829448 to pool.
Cache Hit Ratio [cache2.mapper.UserMapper2]: 0.5
Process finished with exit code 0
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
Java 数据库连接 Maven
后端框架学习-----mybatis(使用mybatis框架遇到的问题)
这篇文章总结了在使用MyBatis框架时可能遇到的几个常见问题及其解决方法,包括配置文件注册、接口绑定、方法名匹配、返回类型匹配、Maven资源导出、时区设置和字符编码问题。
|
9天前
|
SQL Java 数据库连接
持久层框架MyBatisPlus
持久层框架MyBatisPlus
25 1
持久层框架MyBatisPlus
|
23天前
|
缓存 Cloud Native 安全
探索阿里巴巴新型ORM框架:超越MybatisPlus?
【10月更文挑战第9天】在Java开发领域,Mybatis及其增强工具MybatisPlus长期占据着ORM(对象关系映射)技术的主导地位。然而,随着技术的发展,阿里巴巴集团推出了一种新型ORM框架,旨在提供更高效、更简洁的开发体验。本文将对这一新型ORM框架进行探索,分析其特性,并与MybatisPlus进行比较。
26 0
|
3月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
3月前
|
Java 数据库连接 mybatis
mybatis框架图
文章介绍了MyBatis框架的起源、发展和其作为持久层框架的功能,提供了MyBatis的框架图以帮助理解其结构和组件。
mybatis框架图
|
3月前
|
安全 Java 数据库连接
后端框架的学习----mybatis框架(3、配置解析)
这篇文章详细介绍了MyBatis框架的核心配置文件解析,包括环境配置、属性配置、类型别名设置、映射器注册以及SqlSessionFactory和SqlSession的生命周期和作用域管理。
后端框架的学习----mybatis框架(3、配置解析)
|
3月前
|
Java 数据库连接 mybatis
后端框架的学习----mybatis框架(9、多对一处理和一对多处理)
这篇文章介绍了在MyBatis框架中如何处理多对一和一对多的关联查询,通过定义`<resultMap>`和使用`<association>`与`<collection>`元素来实现对象间的关联映射。
|
3月前
|
Java 数据库连接 测试技术
后端框架的学习----mybatis框架(8、lombok)
这篇文章介绍了如何在MyBatis框架中使用lombok库来简化Java实体类的编写,包括在IDEA中安装Lombok插件、在项目中导入lombok依赖以及在实体类上使用Lombok提供的注解。
|
3月前
|
Java 数据库连接 数据库
后端框架的学习----mybatis框架(6、日志)
这篇文章介绍了如何在MyBatis框架中使用日志功能,包括配置MyBatis的日志实现、使用log4j作为日志工具,以及如何通过配置文件控制日志级别和输出格式。
|
4月前
|
Java 数据库连接 Spring
搭建 spring boot + mybatis plus 项目框架并进行调试
搭建 spring boot + mybatis plus 项目框架并进行调试
93 4