介绍

  • 什么是 Mybatis ?

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

  • Mybatis 历史

Mybatis 是 Apache 软件基金会下的一个开源项目, 前身是 ibatis 框架。 2010 年这个项目由 apache 软件基金会迁移到 google code 下, 改名为 Mybatis。 2013 年 11 月又迁移到了 github

  • 通俗说 Mybatis 到底可以做什么?

平时我们都用 JDBC 访问数据库,除了需要自己写 SQL 之外,还必须操作 Connection, Statement, ResultSet,这些其实只是手段的辅助类。 不仅如此,访问不同的表,还会写很多相同的代码,显得繁琐和枯燥。

那么用了 Mybatis 之后,只需要自己提供 SQL 语句,其他的工作,诸如建立连接 Statement, JDBC 相关异常处理等等都交给 Mybatis 去做了,那些重复性的工作 Mybatis 也给做掉了,开发者只需要关注在增删改查等操作层面上,而 Mybatis 把技术细节都封装在了我们看不见的地方。

框架原理

1、Mybatis 配置文件 SqlMapConfig.xml :此文件作为 mybatis 的全局配置文件,定义了 mybatis 运行的基础环境信息,如数据库链接信息等。mapper.xml 文件,这些文件是 sql 映射文件,文件配置了操作数据库的 sql 语句,此文件需要在 SqlMapConfig.xml 中配置加载。

2、通过 mybatis 环境等配置信息构造 SqlSessionFactory,即会话工厂。

3、由会话工厂创建 sqlSession 即会话,操作数据库需要通过 sqlSession 进行。

4、mybatis 底层自定义了 Executor 执行器接口操作数据库,Executor 接口有两个实现,一个是基本执行器、一个是缓存执行器。

5、Mapped Statement 也是 mybatis 一个底层封装对象,它包装了 mybatis 配置信息及 sql 映射信息等。mapper.xml 文件中一个 sql 对应一个 Mapped Statement 对象,sql 的 id 即是 Mapped statement 的 id。

6、Mapped Statement 对 sql 执行输入参数进行定义,包括 HashMap、基本类型、pojo,Executor 通过 Mapped Statement 在执行 sql 前将输入的 java 对象映射至 sql 中,输入参数映射就是 jdbc 编程中对 preparedStatement 设置参数。

7、Mapped Statement 对 sql 执行输出结果进行定义,包括 HashMap、基本类型、pojo,Executor 通过 Mapped Statement 在执行 sql 后将输出结果映射至 java 对象中,输出结果映射过程相当于 jdbc 编程中对结果的解析处理过程。

入门实现CRUD

  1. JDK:1.8
  2. mybatis:3.5.7
  3. maven 工程

1、创建 maven 工程,导入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>

<!-- 使得代码目录下的xml配置文件被解析 否则可能报错-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>

2、创建实体类

1
2
3
4
5
6
7
8
9
10
11
12
public class User {
private Integer id;
private String name;
private String password;

public User(Integer id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
/* getters, setters, toString*/
}

3、用户接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface UserDao {
/**
* 添加
*/
int saveUser(User user);

/**
* 更新
*/
void updateUserById(User user);

/**
* 查询
*/
List<User> findAll();

/**
* 删除
*/
int deleteById(int id);
}

4、编写配置文件

在 resources 文件夹中,创建 Mybatis 的主配置文件 SqlMapConfig.xml。它是 mybatis 核心配置文件,配置文件内容为数据源、事务管理。
配置环境:

  • 配置 mysql 的环境:
    1. 配置事务的类型;
    2. 配置连接池:配置连接数据库的 4 个基本信息;
  • 指定映射配置文件的位置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 数据源配置 -->
<!--
default: 当前环境默认数据库环境
-->
<environments default="mysql">
<!-- id: 每个数据库环境的 ID -->
<environment id="mysql">
<!-- 事务管理器,事务控制
jdbc: 数据源事务管理器 ,类似 Spring 的 DataSourceTransactiionManager -->
<transactionManager type="JDBC"></transactionManager>
<!-- type: 连接池类型
POOLED: 使用 mybatis 自带的数据源
UNPOOLED: 不使用数据源 -->
<dataSource type="POOLED">
<!-- 数据库链接配置 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?autoReconnect=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>

<mappers>
<!--
1、指定映射配置文件的位置,映射配置文件指的是每个 dao 独立的配置文件
2、路径必须是反斜杠
-->
<mapper resource="com/mobaijun/dao/mapper/UserDao.xml"/>
</mappers>
</configuration>

5、映射文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mobaijun.dao.UserDao">
<insert id="saveUser" parameterType="rfam.User">
INSERT INTO user
VALUES (#{id}, #{name}, #{password});
</insert>

<update id="updateUserById" parameterType="rfam.User">
UPDATE user
SET name =#{name}, password = #{password} WHERE id = #{id};
</update>

<delete id="deleteById" parameterType="int">
DELETE
FROM user WHERE id = #{id}
</delete>

<select id="findAll" resultType="rfam.User">
SELECT
id,name,password FROM user
</select>
</mapper>
  • 参数说明
  1. namespace:用来区别不同的类的名字
  2. id: 标识映射文件中的 sql,称为 statement 的 id 将 sql 语句封装到 mappedStatement 对象中,所以将 id 称为 statement 的 id
  3. sql:里面为表所有字段,可自定义或添加别名。
  4. parameterType: 指定输入参数的类型.
  5. resultType: 指定输出结果类型。mybatis 将 sql 查询结果的一行记录数据映射为 resultType 指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器 List 中
1
2
3
1、#{}: 一个占位符。preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换。#{} 可以有效防止 sql 注入。 #{} 可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值,#{} 括号中可以是 value 或其它名称。

2、${}: 表示拼接 sql 串,通过 ${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换,${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。

6、编写测试类

在 test->java 目录下创建测试类 com.mobaijun.test.MybatisTest。实现业务需求,共 7 步。

1
2
3
4
5
6
7
1. 扫描 mappper 配置文件 `SqlMapConfig.xml`
2. 创建 `SqlSessionFactoryBuilder` 工厂
3. 创建 `SqlSessionFactory` 工厂
4. 创建 `SqlSession`,包含 `CRUD` 方法
5. 获取 Mapper 接口的代理对象
6. 使用代理执行 CRUD 操作
7. 关闭资源
  • 示例代码
    利用工具类来获取sqlsession 避免重复代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package util;
    /***************/
    public class MybatisUtil {
    private static SqlSessionFactory ssf;
    static {
    String resource = "mybatis_config.xml";
    try {
    // 1. 读取配置文件
    InputStream is = Resources.getResourceAsStream(resource);
    // 2. 创建 SqlSessionFactory 工厂
    ssf = new SqlSessionFactoryBuilder().build(is);
    } catch (IOException e) {
    throw new RuntimeException(e);
    }
    }

    public static SqlSession getSqlSession() {
    // 3. 使用工厂生产 SqlSession 对象
    return ssf.openSession();
    }
    }
    注意增删改都需要提交事务
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    public class MybatisTest {

    public void getUsers() {
    SqlSession session = MybatisUtil.getSqlSession();
    UserDao ud = session.getMapper(UserDao.class);
    List<User> us = ud.findAll();
    for (User u : us) {
    System.out.println(u);
    }
    session.commit();
    session.close();
    }

    /**
    * 删除
    */
    public void deleteById() {
    SqlSession session = MybatisUtil.getSqlSession();
    // 4. 执行 Sql 语句
    UserDao userDao = session.getMapper(UserDao.class);
    // 5. 执行 SQL
    userDao.deleteById(1);
    // 6. 释放资源
    session.close();
    }
    /**
    * 更新
    */
    public void updateUserById(User user) {
    SqlSession session = MybatisUtil.getSqlSession();
    UserDao userDao = session.getMapper(UserDao.class);
    mapper.updateUserById(user);
    session.commit();
    session.close();
    }

    /**
    * 新增
    */
    public void saveUser() {
    SqlSession session = MybatisUtil.getSqlSession();
    // 4. 执行 Sql 语句
    UserDao userDao = session.getMapper(UserDao.class);
    User user;
    for (int i = 0; i < 100; i++) {
    user = new User(i+1, "aa", "bb", "123456");
    log.info("代理对象:" + userDao.getClass());
    // 5. 执行 SQL
    userDao.saveUser(user);
    // 6. 提交数据
    session.commit();
    System.out.println(user);
    }
    // 7. 释放资源
    session.close();
    }
    }

利用Map传参/获取结果

当实体类或数据库中的表 字段过多 可以考虑使用map

示例:
映射文件和UserDao中新增 saveUserWithMap sql语句中插入值可以通过map的键获取

1
2
3
4
<insert id="saveUserWithMap" parameterType="map">  
INSERT INTO user
VALUES (#{uid}, #{uname}, #{upwd});
</insert>

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void saveUserWithMap() {
SqlSession session = MybatisUtil.getSqlSession();
UserDao ud = session.getMapper(UserDao.class);
// 构造map
Map<String, Object> map = new HashMap<>();
map.put("uname", "bbb");
map.put("uid", 2);
map.put("upwd", "5351");
// 执行sql
ud.saveUserWithMap(map);
session.commit();
// 7. 释放资源
session.close();
}

配置文件

利用property引入外部/内部配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="path/to/f.properties">
<property name="username" value="root"/>
</properties>

<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<!-- 数据库链接配置 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?autoReconnect=true"/>
<property name="username" value="${username}"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="com/mobaijun/dao/mapper/UserDao.xml"/>
</mappers>
</configuration>

利用typeAlias取别名

这样在映射文件中使用别名就可以 减少冗余

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="path/to/f.properties">
<property name="username" value="root"/>
</properties>
<typeAliases>
<typeAlias type="rfam.User" alias="User"/>
</typeAliases>
<!-- .... -->
</configuration>

也可以指定包名 然后在实体类中通过注解取别名

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="path/to/f.properties">
<property name="username" value="root"/>
</properties>
<typeAliases>
<typeAlias package="rfam"/>
</typeAliases>
<!-- .... -->
</configuration>
1
2
3
4
5
6
7
8
9
10
11
12
13
@Alias("hello")
public class User {
private Integer id;
private String name;
private String password;

public User(Integer id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
/* getters, setters, toString*/
}

日志

STDOUT_LOGGING: 标准输出
LOG4J, SLF4J 需要在maven中导入对应的包

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="path/to/f.properties">
<property name="username" value="root"/>
</properties>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- .... -->
</configuration>

生命周期与作用域

  • SqlSessionFactoryBuilder: 一旦创建就不再需要
  • SqlSessionFactory: 创建后在应用的运行期间一直存在 适合单例/静态模式
  • SqlSession: 用于连接连接池, 不是线程安全的,因此不能共享 最佳作用域为方法作用域;用完应释放资源

resultMap

结果集映射
用于将数据库列名映射到类字段名 来构建类对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mobaijun.dao.UserDao">
<resultMap id="rmap" type="rfam.User">
<!-- column为数据库中的列 property为实体类中属性-->
<result column="pwd" property="password"/>
<result column="name" property="name"/>
<result column="id" property="id"/>
</resultMap>

<select id="findAll" resultMap="rmap">
SELECT id,name,pwd FROM user
</select>
</mapper>

分页

  1. 使用sql中原生的limit进行分页
  2. 使用rowBounds
    1
    2
    RowBounds rowBounds = new RowBounds(1,2);  
    List<User> us = session.selectList("dao.UserDao.getUsers", null, rowBounds);

注解开发

  1. 可以直接在接口上使用注解实现执行sql语句
    1
    2
    3
    4
    public interface AnnoUserDao {  
    @Select("select * from user")
    public List<User> getUsers();
    }
  2. 需要在配置文件中绑定接口
    1
    2
    3
    <mappers>  
    <mapper class="dao.AnnoUserDao"/>
    </mappers>
  3. 测试调用
    底层:反射,对mapper生成动态代理,用于处理后续的CRUD方法

CRUD

1
2
3
4
5
public interface AnnoUserDao {  
@Select("select * from user")
public List<User> getUsers();

}

多对一

对象当中还包含待查寻对象 (学生及其对应的老师)
测试环境:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
create table teacher  
(
id int(10) not null
primary key,
name varchar(30) null
)
charset = utf8;

create table student
(
id int(10) not null
primary key,
name varchar(30) null,
tid int(10) null,
constraint fktid
foreign key (tid) references teacher (id)
)
charset = utf8;

INSERT INTO student(id, name, tid) VALUES (1, 'SA', 1);
INSERT INTO student(id, name, tid) VALUES (2, 'SB', 1);
INSERT INTO student(id, name, tid) VALUES (3, 'SC', 1);
1
2
3
4
5
6
7
8
9
10
public class Student {  
private int id;
private String name;
private Teacher teacher;
// 注意这里需要无参构造函数 否则后续查询可能报错
public Student() {

}
// ....
}
1
2
3
4
5
6
7
public class Teacher {  
private int id;
private String name;
public Teacher() {

}
}

按照查询嵌套处理

查询学生信息:

  1. 获取所有学生信息
  2. 根据tid获取老师信息(子查询)

StudentMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<mapper namespace="multi.dao.StudentMapper">  
<!--使用resultMap将字段映射到对象-->
<select id="getStudents" resultMap="studentTeacher">
select * from student
</select>

<resultMap id="studentTeacher" type="multi.pojo.Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!-- 复杂属性需要单独处理 对象:association 集合:collection-->
<association property="teacher" column="tid" select="getTeacherById" javaType="multi.pojo.Teacher"/>
</resultMap>

<select id="getTeacherById" resultType="multi.pojo.Teacher">
select * from teacher where id = #{id}
</select>

</mapper>

测试输出即可得到结果

1
2
3
Student{id=1, name='SA', teacher=Teacher{id=1, name='Ms.Q'}}
Student{id=2, name='SB', teacher=Teacher{id=1, name='Ms.Q'}}
Student{id=3, name='SC', teacher=Teacher{id=1, name='Ms.Q'}}

按照结果嵌套处理

注意给所需的列名取别名

1
2
3
4
5
6
7
8
9
10
11
12
<select id="getStudents2" resultMap="st">  
select student.id sid, student.name sname, tid, teacher.name tname
from student, teacher where student.tid = teacher.id</select>

<resultMap id="st" type="multi.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="multi.pojo.Teacher">
<result column="tid" property="id"/>
<result column="tname" property="name"/>
</association>
</resultMap>

一对多

一个老师包含多个学生

1
2
3
4
5
public class Teacher {  
private int id;
private String name;
private List<Student> students;
}

按照查询嵌套处理

查询老师信息:

  1. 获取所有老师信息
  2. 根据tid获取所有学生
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <select id="getTeachers2" resultMap="ts2">  
    select * from teacher
    </select>

    <resultMap id="ts2" type="multi.pojo.Teacher">
    <result column="id" property="id"/>
    <result column="name" property="name"/>
    <collection property="students" javaType="ArrayList" ofType="multi.pojo.Student" column="id"
    select="getStudentByTeacher"/>
    </resultMap>

    <select id="getStudentByTeacher" resultType="multi.pojo.Student">
    select * from student where tid = #{id}
    </select>

按照结果嵌套处理

TeacherMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<select id="getTeachers" resultMap="ts">  
select student.id sid, student.name sname, tid, teacher.name tname
from student, teacher
where student.tid = teacher.id
</select>

<resultMap id="ts" type="multi.pojo.Teacher">
<result column="tid" property="id"/>
<result column="tname" property="name"/>
<!-- 指定 集合对象为Student 存入students字段 -->
<collection property="students" ofType="multi.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
</collection>
</resultMap>

测试输出即可得到结果

1
Teacher{id=1, name='Ms.Q', students=[Student{id=1, name='SA', teacher=null}, Student{id=2, name='SB', teacher=null}, Student{id=3, name='SC', teacher=null}]}

动态sql

就是指根据不同的条件生成不同的sql语句

环境搭建

1
2
3
4
5
6
7
CREATE TABLE blog (
id varchar(50) NOT NULL,
title varchar(100) NOT NULL,
author varcahr(30) NOT NULL,
create_time datetime NOT NULL,
views int(30) NOT NULL
) charset=utf8

Blog.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Blog {  
private String id;
private String title;
private String author;
private Date createTime;
private int views;

public Blog() {
}

public Blog(String title, String author, Date createTime, int views) {
this.id = UUID.randomUUID().toString().replace("-", "");
this.title = title;
this.author = author;
this.createTime = createTime;
this.views = views;
}
// ...
}

添加数据

BlogMapper.xml

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dynamic.dao.BlogMapper">
<insert id="addBlog" parameterType="dynamic.pojo.Blog">
insert into blog
values (#{id}, #{title}, #{author}, #{createTime}, #{views}) </insert>

</mapper>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SqlSession session = MybatisUtil.getSqlSession();  
BlogMapper bm = session.getMapper(BlogMapper.class);
String id = UUID.randomUUID().toString().replace("-", "");

Blog[] blogs = new Blog[]{
new Blog("TA", "Kat", new Date(), 100),
new Blog("TB", "Lana", new Date(), 500),
new Blog("TC", "Bart", new Date(), 368),
new Blog("TD", "Kat", new Date(), 100),

};
for (Blog blog : blogs) {
bm.addBlog(blog);
}

session.commit();
session.close();

if

通过if来拼接sql条件语句 if的判断条件写在test中

1
2
3
4
5
6
<select id="getBlogs" parameterType="Map" resultType="dynamic.pojo.Blog">  
select * from blog where 1=1
<if test="author != null">
and author = #{author}
</if>
</select>

测试

1
2
3
4
5
6
7
8
9
SqlSession session = MybatisUtil.getSqlSession();  
BlogMapper bm = session.getMapper(BlogMapper.class);
Map<String, Object> map = new HashMap<>();
// map.put("author", "Kat");
List<Blog> blogs = bm.getBlogs(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
session.close();
  • map中不放内容 结果:
    1
    2
    3
    4
    	Blog{id=b25806c7dc91491ab6af58bf3753d2dc, title='TA', author='Kat', createTime=Sun Feb 25 10:53:41 CST 2024, views=100}
    Blog{id=914bad57dafe42bc973f20522396777d, title='TB', author='Lana', createTime=Sun Feb 25 10:53:41 CST 2024, views=500}
    Blog{id=19f3610a2d6845b9bb54e4c31409dd3d, title='TC', author='Bart', createTime=Sun Feb 25 10:53:41 CST 2024, views=368}
    Blog{id=6e334e6bc75c4d8bb36042d378ca7005, title='TD', author='Kat', createTime=Sun Feb 25 10:53:41 CST 2024, views=100}
  • map.put("author", "Kat"); 结果:
    1
    2
    Blog{id=b25806c7dc91491ab6af58bf3753d2dc, title='TA', author='Kat', createTime=Sun Feb 25 10:53:41 CST 2024, views=100}
    Blog{id=6e334e6bc75c4d8bb36042d378ca7005, title='TD', author='Kat', createTime=Sun Feb 25 10:53:41 CST 2024, views=100}
  • map.put("author", "Kat"); map.put("title", "TA");结果:
    1
    Blog{id=b25806c7dc91491ab6af58bf3753d2dc, title='TA', author='Kat', createTime=Sun Feb 25 10:53:41 CST 2024, views=100}

choose, when, otherwise

类似switch语句 按序匹配 匹配到了就执行对应语句(仅一个) 然后结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<select id="getBlogs2" parameterType="Map" resultType="dynamic.pojo.Blog">  
select * from blog
<where>
<choose>
<!--有author就不匹配title-->
<when test="author != null">
author = #{author}
</when>
<when test="title != null">
and title = #{title}
</when>
</choose>
</where>
</select>

foreach

遍历集合类中的元素进行sql语句拼接

1
2
3
4
5
6
7
8
<select id="getBlogs3" parameterType="Map" resultType="dynamic.pojo.Blog">  
select * from blog
<where>
<foreach collection="ids" item="id" open="(" close=")" separator="or">
id = #{id}
</foreach>
</where>
</select>

缓存

一级缓存

也叫本地缓存 :SqlSession本身具备
与数据库同一次会话期间查询到的数据会放入本地缓存中;如需再获取相同数据,从缓存中拿即可

缓存失效的情况:

  • 查询不同的数据
  • 增删改操作后,缓存会刷新
  • 手动清理缓存: clearCache

二级缓存

也叫全局缓存,需在mapper.xml中添加<cache/>

  • 会话查询的数据首先会进入一级缓存中
  • 如果当前会话关闭,一级缓存中的数据会进入二级缓存
  • 新的会话就可以从二级缓存中获取数据
  • 不同mapper查询的数据会在自己对应的缓存中
2024-02-13

⬆︎TOP