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

2023-08-01 10:19:34 浏览数 (1)

本文原创首发CSDN,本文链接https://blog.csdn.net/qq_41464123/article/details/108172276作者博客https://blog.csdn.net/qq_41464123,转载请带上本链接,谢谢配合。


一、前置工作

1.1 MyBatis简介

  • MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  • MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO为数据库中的记录。
  • 官方文档:https://mybatis.org/mybatis-3/zh/index.html

1.2 个人点评分析

  • MyBatis是一款优秀的持久层框架,通俗来说就是用来连接数据库。在没有JPA和MyBatis之前,原生JDBC式操作设置参数和获取结果集的工作非常臃肿枯燥。
  • 在MyBatis中可以通过简单的 XML或者Java注解实现JDBC大量代码才能完成的操作。
  • MyBatis简单易学,不需要第三方依赖,只需要看官方文档就可以学习。
  • MyBatis将SQL语句放到XML文件内,统一管理和优化。SQL作为数据库领域的霸主,基本可以实现我们所有的功能,而MyBatis可以很方便使用原生SQL。
  • 高内聚低耦合,SQL不放在Dao,使得系统设计清晰,而JPA没有做到这一点
  • 在最近参与的项目编写中,采用了Xboot框架,其中整合了MyBatis和JPA。从实际使用性来说,MyBatis的优势远远大于JPA。

1.3 idea新建项目配置

  • jdk 11.0.6
  • maven 3.6.2 阿里云
  • idea 2019.3
  1. 选择创建maven新项目,删除src目录,创建子module
  2. 在 File | Settings | Build, Execution, Deployment | Build Tools | Maven 中,配置maven
  3. 在 File | Settings | Build, Execution, Deployment | Compiler | Java Compiler 中,设置发行版本为 11
  4. File | Settings | Editor | File Encodings,编码改为UTF-8
  5. 在File | Project Setting | Modules 中,将版本设置为11

1.4 依赖、资源过滤

放在父 pom.xml 中即可

代码语言:javascript复制
<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.0</version>
    </dependency>
</dependencies>

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

1.5 创建数据库

因为关联外键、异步等原因,必须分步执行,否则会出错

代码语言:javascript复制
CREATE DATABASE `test`;
USE `test`

CREATE TABLE `user`(
	`id` VARCHAR(50) NOT NULL,
	`name` VARCHAR(10) DEFAULT NULL,
	`age` INT(10) DEFAULT NULL,
	PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=UTF8;

CREATE TABLE `teacher`(
	`id` VARCHAR(50) NOT NULL,
	`name` VARCHAR(10) DEFAULT NULL,
	PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

CREATE TABLE `student`(
	`id` VARCHAR(50) NOT NULL,
	`name` VARCHAR(10) DEFAULT NULL,
	`teacher` VARCHAR(50) DEFAULT NULL ,
	PRIMARY KEY (`id`),
	FOREIGN KEY(`teacher`) REFERENCES teacher(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8

create table `book`(
    `id` varchar(50) primary key,
    `name` varchar(20) default null,
    `money` double default 0.0,
    `buy_date` datetime
)engine=InnoDB default charset=utf8

INSERT INTO `user`(`id`,`name`,`age`) VALUES 
(0,"ZWZ01","123456"),
(1,"ZWZ02","123456"),
(2,"ZWZ03","123456");

INSERT INTO `teacher`(`id`,`name`) VALUES (1,'ZWZ');
INSERT INTO `student`(`id`,`name`,`teacher`) VALUES (1,'ZWZ01',1);
INSERT INTO `student`(`id`,`name`,`teacher`) VALUES (2,'ZWZ02',1);
INSERT INTO `student`(`id`,`name`,`teacher`) VALUES (3,'ZWZ03',1);
INSERT INTO `student`(`id`,`name`,`teacher`) VALUES (4,'ZWZ04',1);
INSERT INTO `student`(`id`,`name`,`teacher`) VALUES (5,'ZWZ05',1);

1.6 idea连接MySQL

设置时区后,点击 Test Connection

属性

serverTimezone

Asia/Shanghai

二、增删改查

2.1 公用类

数据库配置

db.properties,用于连接数据库的重要信息,一般为驱动名、URL地址、用户名、密码

代码语言:javascript复制
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false
username=root
password=123456

mybatis配置

mybatis-config.xml,mybatis的配置文件

代码语言:javascript复制
<?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="db.properties"/>

    <settings>
        <!--开启日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--驼峰转换-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <typeAliases>
        <package name="zwz.pojo"/>
    </typeAliases>

    <environments default="zwz">
        <environment id="zwz">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper class="zwz.mapper.UserMapper"/>
    </mappers>
</configuration>

实体类

用户类User,包含id、name、age三个变量,其中Id由工具类 IdUtils 自动生成

代码语言:javascript复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String id;
    private String name;
    private int age;
}

SqlSession工具类

  • 用于获取session对象
  • 先从 SqlSessionFactoryBuilder 工厂构造器构建SqlSessionFactory
  • 再从SqlSessionFactory工厂生产SqlSession
  • 为了简化代码,封装成一个工具类
代码语言:javascript复制
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

随机ID工具类

该类用于随机生成ID,其中横线被替换为空,也可以替换成其他值

代码语言:javascript复制
public class IdUtils {
    public static String getId(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }
}

2.2 增加用户

mapper层接口

要实现增加用户,第一步先写一个接口,在用XML具体实现这个接口

代码语言:javascript复制
public interface UserMapper {
    // 增加用户
    int addUser(User user);
}

XML具体实现

  • namespace是命名空间,必须和接口的地址相对应
  • id为接口方法名,必须对应
  • parameterType为传入参数类型,因为已配置别名,一般使用首字母小写的类名
  • #{}中的字符串,要和实体类变量名对应,或用resultMap
代码语言:javascript复制
<?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.UserMapper">

    <insert id="addUser" parameterType="user">
        insert into user(id, name, age) VALUES (#{id},#{name},#{age});
    </insert>
</mapper>

Insert, Update, Delete 元素的属性如下

属性

描述

id

在命名空间中唯一的标识符,可以被用来引用这条语句。

parameterType

将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。

parameterMap

用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。

flushCache

将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。

timeout

这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。

statementType

可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。

useGeneratedKeys

(仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。

keyProperty

(仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。

keyColumn

(仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。

databaseId

如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。

测试

  • 测试方法中,增加了六个用户
  • 增删改操作之后必须提交事务,否则无效
代码语言:javascript复制
/**
* 增加用户
*/
@Test
public void testAddUser(){
    SqlSession session = MybatisUtils.getSqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    mapper.addUser(new User(IdUtils.getId(),"ZWZ1",18));
    mapper.addUser(new User(IdUtils.getId(),"ZWZ2",18));
    mapper.addUser(new User(IdUtils.getId(),"ZWZ3",18));
    mapper.addUser(new User(IdUtils.getId(),"ZWZ4",18));
    mapper.addUser(new User(IdUtils.getId(),"ZWZ5",18));
    mapper.addUser(new User(IdUtils.getId(),"ZWZ6",18));
    session.commit();
    session.close();
}

日志输出

可以看到,系统执行了六次insert SQL语句,成功插入

代码语言:javascript复制
Created connection 1552326679.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5c86a017]
==>  Preparing: insert into user(id, name, age) VALUES (?,?,?); 
==> Parameters: 9e3eed6af6da4214b520535cac13f13a(String), ZWZ1(String), 18(Integer)
<==    Updates: 1
==>  Preparing: insert into user(id, name, age) VALUES (?,?,?); 
==> Parameters: 7322170480104981a58b28f51fdb2288(String), ZWZ2(String), 18(Integer)
<==    Updates: 1
==>  Preparing: insert into user(id, name, age) VALUES (?,?,?); 
==> Parameters: f0d102cd857645c9aaca4ded53abb0e8(String), ZWZ3(String), 18(Integer)
<==    Updates: 1
==>  Preparing: insert into user(id, name, age) VALUES (?,?,?); 
==> Parameters: e4993aecfd4f4322905eb6dc0cf039b9(String), ZWZ4(String), 18(Integer)
<==    Updates: 1
==>  Preparing: insert into user(id, name, age) VALUES (?,?,?); 
==> Parameters: 4e387cafc50840468c4dfeec54940e1c(String), ZWZ5(String), 18(Integer)
<==    Updates: 1
==>  Preparing: insert into user(id, name, age) VALUES (?,?,?); 
==> Parameters: 35ee11b46afa47a68be7713ecdeccd7e(String), ZWZ6(String), 18(Integer)
<==    Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5c86a017]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5c86a017]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5c86a017]
Returned connection 1552326679 to pool.

Process finished with exit code 0

2.3 删除用户

mapper层接口

删除、修改、查询原理同增加用户

代码语言:javascript复制
// 删除用户
int deleteUser(@Param("id") String id);

XML具体实现

代码语言:javascript复制
<delete id="deleteUser" parameterType="string">
    delete from user where id = #{id};
</delete>

测试

其中删除方法deleteUser中的参数ID,根据实际情况修改

代码语言:javascript复制
/**
* 删除用户
*/
@Test
public void testDeleteUser(){
    SqlSession session = MybatisUtils.getSqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    // 根据数据库用户ID自行填写
    mapper.deleteUser("35ee11b46afa47a68be7713ecdeccd7e");
    session.commit();
    session.close();
}

日志输出

可以看出,系统执行了一条delete语句,用户成功被删除

代码语言:javascript复制
Created connection 1473981203.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@57db2b13]
==>  Preparing: delete from user where id = ?; 
==> Parameters: 35ee11b46afa47a68be7713ecdeccd7e(String)
<==    Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@57db2b13]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@57db2b13]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@57db2b13]
Returned connection 1473981203 to pool.

Process finished with exit code 0

2.4 修改用户

mapper层接口

代码语言:javascript复制
// 指定ID查询用户
User findUserById(@Param("id") String id);

XML具体实现

代码语言:javascript复制
<update id="updateUser" parameterType="user">
    update user set name = #{name}, age = #{age} where id = #{id};
</update>

测试

代码语言:javascript复制
/**
* 修改用户
*/
@Test
public void testUpdateUser(){
    SqlSession session = MybatisUtils.getSqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    // 根据数据库用户ID自行填写
    mapper.updateUser(new User("9e3eed6af6da4214b520535cac13f13a","ZWZ1改",18));
    session.commit();
    session.close();
}

日志输出

代码语言:javascript复制
Created connection 454884231.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1b1cfb87]
==>  Preparing: update user set name = ?, age = ? where id = ?; 
==> Parameters: ZWZ1改(String), 18(Integer), 9e3eed6af6da4214b520535cac13f13a(String)
<==    Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1b1cfb87]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1b1cfb87]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1b1cfb87]
Returned connection 454884231 to pool.

Process finished with exit code 0

2.5 单个查询

mapper层接口

其中传递非引用类型参数,建议加上@Param注解,注解中的字符串和XML文件#{}中对应

代码语言:javascript复制
// 指定ID查询用户
User findUserById(@Param("id") String id);

XML具体实现

代码语言:javascript复制
<select id="findUserById" resultType="user" parameterType="string">
    select * from user where id = #{id};
</select>

Select 元素的属性如下

属性

描述

id

在命名空间中唯一的标识符,可以被用来引用这条语句。

parameterType

将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。

parameterMap

用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。

resultType

期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。

resultMap

对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。

flushCache

将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。

useCache

将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。

timeout

这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。

fetchSize

这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。

statementType

可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。

resultSetType

FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。

databaseId

如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。

resultOrdered

这个设置仅针对嵌套结果 select 语句:如果为 true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。 这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:false。

resultSets

这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。

测试

代码语言:javascript复制
/**
 * 查询单个用户
 */
@Test
public void testFindUserById(){
    SqlSession session = MybatisUtils.getSqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    User user = mapper.findUserById("9e3eed6af6da4214b520535cac13f13a");
    System.out.println(user);
}

日志输出

可以看出系统执行了一条查询语句

代码语言:javascript复制
Created connection 2113748097.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7dfd3c81]
==>  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)

Process finished with exit code 0

2.6 查询全部

mapper层接口

代码语言:javascript复制
<select id="findAllUsers" resultType="user">
    select * from user;
</select>

XML具体实现

代码语言:javascript复制
// 查询全部用户
List<User> findAllUsers();

测试

代码语言:javascript复制
@Test
public void testFindAllUsers(){
    SqlSession session = MybatisUtils.getSqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    List<User> users = mapper.findAllUsers();
    for (User user : users) {
        System.out.println(user);
    }
}

日志输出

代码语言:javascript复制
Created connection 352367347.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1500b2f3]
==>  Preparing: select * from user; 
==> Parameters: 
<==    Columns: id, name, age
<==        Row: 4e387cafc50840468c4dfeec54940e1c, ZWZ5, 18
<==        Row: 7322170480104981a58b28f51fdb2288, ZWZ2, 18
<==        Row: 9e3eed6af6da4214b520535cac13f13a, ZWZ1改, 18
<==        Row: e4993aecfd4f4322905eb6dc0cf039b9, ZWZ4, 18
<==        Row: f0d102cd857645c9aaca4ded53abb0e8, ZWZ3, 18
<==      Total: 5
User(id=4e387cafc50840468c4dfeec54940e1c, name=ZWZ5, age=18)
User(id=7322170480104981a58b28f51fdb2288, name=ZWZ2, age=18)
User(id=9e3eed6af6da4214b520535cac13f13a, name=ZWZ1改, age=18)
User(id=e4993aecfd4f4322905eb6dc0cf039b9, name=ZWZ4, age=18)
User(id=f0d102cd857645c9aaca4ded53abb0e8, name=ZWZ3, age=18)

Process finished with exit code 0

三、resultMap结果集映射

  • resultMap 是 MyBatis 中最重要最强大的元素。
  • 它可以进行一些 JDBC 不支持的操作。
  • 设计思想,对简单的语句做到零配置,对于复杂语句,只需要描述语句之间的关系

需要实现的功能

使用resultMap ,查询所有的User

mapper接口

mapper接口和之前一样,约束需要实现的功能

代码语言:javascript复制
public interface UserMapper {
    List<User> findAllUsers();
}

XML具体实现

  • findAllUsers 方法配置了 resultMap
  • userMap配置了数据库列和Java实体类的关系
代码语言:javascript复制
<?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.UserMapper">
    <select id="findAllUsers" resultMap="userMap">
        select * from user;
    </select>

    <resultMap id="userMap" type="user">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="age" property="age"/>
    </resultMap>
</mapper>

测试

代码语言:javascript复制
@Test
public void testResultMap(){
    SqlSession session = MybatisUtils.getSqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    List<User> users = mapper.findAllUsers();
    for (User user : users) {
        System.out.println(user);
    }
}

日志输出

可以看到和之前一样,也实现了查询操作

代码语言:javascript复制
Created connection 126189538.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7857fe2]
==>  Preparing: select * from user; 
==> Parameters: 
<==    Columns: id, name, age
<==        Row: 4e387cafc50840468c4dfeec54940e1c, ZWZ5, 18
<==        Row: 7322170480104981a58b28f51fdb2288, ZWZ2, 18
<==        Row: 9e3eed6af6da4214b520535cac13f13a, ZWZ1改, 18
<==        Row: e4993aecfd4f4322905eb6dc0cf039b9, ZWZ4, 18
<==        Row: f0d102cd857645c9aaca4ded53abb0e8, ZWZ3, 18
<==      Total: 5
User(id=4e387cafc50840468c4dfeec54940e1c, name=ZWZ5, age=18)
User(id=7322170480104981a58b28f51fdb2288, name=ZWZ2, age=18)
User(id=9e3eed6af6da4214b520535cac13f13a, name=ZWZ1改, age=18)
User(id=e4993aecfd4f4322905eb6dc0cf039b9, name=ZWZ4, age=18)
User(id=f0d102cd857645c9aaca4ded53abb0e8, name=ZWZ3, age=18)

Process finished with exit code 0

四、分页

4.1 XML版 limit

mapper层接口

代码语言:javascript复制
public interface UserMapper {
    // 使用Limit语句分页
    List<User> findAllByPageLimit(@Param("startPage") int startPage,@Param("pageSize") int pageSize);
}

XML具体实现

代码语言:javascript复制
<?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.UserMapper">

    <select id="findAllByPageLimit" resultType="user">
        select * from user limit #{startPage},#{pageSize};
    </select>
</mapper>

测试

下标从0开始,所以是输出第三个元素开始,输出三个用户

代码语言:javascript复制
@Test
public void testFindAllByPageLimit(){
    SqlSession session = MybatisUtils.getSqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    List<User> users = mapper.findAllByPageLimit(2, 3);
    for (User user : users) {
        System.out.println(user);
    }
}

日志输出

代码语言:javascript复制
Created connection 1041109062.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3e0e1046]
==>  Preparing: select * from user limit ?,?; 
==> Parameters: 2(Integer), 3(Integer)
<==    Columns: id, name, age
<==        Row: 9e3eed6af6da4214b520535cac13f13a, ZWZ1改, 18
<==        Row: e4993aecfd4f4322905eb6dc0cf039b9, ZWZ4, 18
<==        Row: f0d102cd857645c9aaca4ded53abb0e8, ZWZ3, 18
<==      Total: 3
User(id=9e3eed6af6da4214b520535cac13f13a, name=ZWZ1改, age=18)
User(id=e4993aecfd4f4322905eb6dc0cf039b9, name=ZWZ4, age=18)
User(id=f0d102cd857645c9aaca4ded53abb0e8, name=ZWZ3, age=18)

Process finished with exit code 0

4.2 Java注解版 limit

XML可以实现分页,Java直接也可以实现分页

mapper接口

代码语言:javascript复制
public interface UserMapper {

    // 使用Java注解分页
    @Select("select * from user limit #{startPage},#{pageSize};")
    List<User> findAllByJava(@Param("startPage") int startPage,@Param("pageSize") int pageSize);
}

测试

代码语言:javascript复制
@Test
public void testFindAllByJava(){
    SqlSession session = MybatisUtils.getSqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    List<User> users = mapper.findAllByJava(2, 3);
    for (User user : users) {
        System.out.println(user);
    }
}

日志输出

代码语言:javascript复制
Created connection 1825719826.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@6cd24612]
==>  Preparing: select * from user limit ?,?; 
==> Parameters: 2(Integer), 3(Integer)
<==    Columns: id, name, age
<==        Row: 9e3eed6af6da4214b520535cac13f13a, ZWZ1改, 18
<==        Row: e4993aecfd4f4322905eb6dc0cf039b9, ZWZ4, 18
<==        Row: f0d102cd857645c9aaca4ded53abb0e8, ZWZ3, 18
<==      Total: 3
User(id=9e3eed6af6da4214b520535cac13f13a, name=ZWZ1改, age=18)
User(id=e4993aecfd4f4322905eb6dc0cf039b9, name=ZWZ4, age=18)
User(id=f0d102cd857645c9aaca4ded53abb0e8, name=ZWZ3, age=18)

Process finished with exit code 0

本文原创首发CSDN,本文链接https://blog.csdn.net/qq_41464123/article/details/108172276作者博客https://blog.csdn.net/qq_41464123,转载请带上本链接,谢谢配合。


五、多对一

需求

  • 对于学生而言,都有一位老师
  • 对于老师而言,有多名学生
  • 在学生角度看,学生和老师就是多对一的关系
  • 要求输出学生的所有信息,包括他的老师

新实体类

学生

代码语言:javascript复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private String id;
    private String name;
    private Teacher teacher;
}

老师

代码语言:javascript复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    private String id;
    private String name;
}

方法一

先查询学生信息,再根据老师ID,查询对应老师信息

mapper接口

代码语言:javascript复制
public interface StudentMapper {
    /**
     * 查询学生所有信息,包括其对应的老师 方法1
     * @return
     */
    List<Student> findAllStudentMessages1();
}

XML具体实现

代码语言:javascript复制
<?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.StudentMapper">

    <!--需求: 查询学生所有信息,包括其对应的老师-->

    <!-- 1. 查询所有学生,设置resultMap -->
    <select id="findAllStudentMessages1" resultMap="teacherAndStudent1">
        select * from student;
    </select>

    <!-- 2. 关联映射, association为对象标签 -->
    <resultMap id="teacherAndStudent1" type="student">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <!-- property:在Student类中的变量名 | column:数据库的字段 | javaType:Java对象 | select:数据来源 -->
        <association property="teacher" column="teacher" javaType="zwz.pojo.Teacher" select="findTeacherById"/>
    </resultMap>

    <!-- 3. 补充第二步的数据来源 -->
    <select id="findTeacherById" resultType="teacher">
        select * from teacher
        where id = #{teacher};
    </select>
</mapper>

测试

代码语言:javascript复制
@Test
public void testFindAllStudentMessages1(){
    SqlSession session = MybatisUtils.getSqlSession();
    StudentMapper mapper = session.getMapper(StudentMapper.class);
    List<Student> students = mapper.findAllStudentMessages1();
    for (Student student : students) {
        System.out.println(student);
    }
}

日志输出

可以看出,系统先执行 select * from student,然后根据查询到的老师ID,再执行 select * from teacher where id = ?

代码语言:javascript复制
Created connection 1651162064.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@626abbd0]
==>  Preparing: select * from student; 
==> Parameters: 
<==    Columns: id, name, teacher
<==        Row: 5992b89d9cfd4f0ba79a2991e108d017, ZWZ5, 5992b89d9cfd4f0ba79a2991e108d0b7
====>  Preparing: select * from teacher where id = ?; 
====> Parameters: 5992b89d9cfd4f0ba79a2991e108d0b7(String)
<====    Columns: id, name
<====        Row: 5992b89d9cfd4f0ba79a2991e108d0b7, 郑老师
<====      Total: 1
<==        Row: 5992b89d9cfd4f0ba79a2991e108d1b7, ZWZ1, 5992b89d9cfd4f0ba79a2991e108d0b7
<==      Total: 2
Student(id=5992b89d9cfd4f0ba79a2991e108d017, name=ZWZ5, teacher=Teacher(id=5992b89d9cfd4f0ba79a2991e108d0b7, name=郑老师))
Student(id=5992b89d9cfd4f0ba79a2991e108d1b7, name=ZWZ1, teacher=Teacher(id=5992b89d9cfd4f0ba79a2991e108d0b7, name=郑老师))

Process finished with exit code 0

方法二

使用SQL语句做关联查询,再匹配到对应字段

mapper接口

代码语言:javascript复制
public interface StudentMapper {
    /**
     * 查询学生所有信息,包括其对应的老师 方法2
     * @return
     */
    List<Student> findAllStudentMessages2();
}

XML具体实现

代码语言:javascript复制
<?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.StudentMapper">

    <!--需求: 查询学生所有信息,包括其对应的老师-->
    
    <!-- 1. 查询所有学生和老师的关联结果,设置resultMap -->
    <select id="findAllStudentMessages2" resultMap="teacherAndStudent2">
        select t.id tid,t.name tname,s.id,s.name,s.teacher
        from teacher t,student s
        where s.teacher = t.id;
    </select>

    <!-- 2. 分别对应-->
    <resultMap id="teacherAndStudent2" type="student">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <association property="teacher" javaType="teacher">
            <result column="tid" property="id"/>
            <result column="tname" property="name"/>
        </association>
    </resultMap>
</mapper>

测试

代码语言:javascript复制
/**
 * 方法二
 */
@Test
public void testFindAllStudentMessages2(){
    SqlSession session = MybatisUtils.getSqlSession();
    StudentMapper mapper = session.getMapper(StudentMapper.class);
    List<Student> students = mapper.findAllStudentMessages2();
    for (Student student : students) {
        System.out.println(student);
    }
}

日志输出

可以看出,系统直接执行 select t.id tid,t.name tname,s.id,s.name,s.teacher from teacher t,student s where s.teacher = t.id;

代码语言:javascript复制
Created connection 1304589447.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4dc27487]
==>  Preparing: select t.id tid,t.name tname,s.id,s.name,s.teacher from teacher t,student s where s.teacher = t.id; 
==> Parameters: 
<==    Columns: tid, tname, id, name, teacher
<==        Row: 5992b89d9cfd4f0ba79a2991e108d0b7, 郑老师, 5992b89d9cfd4f0ba79a2991e108d017, ZWZ5, 5992b89d9cfd4f0ba79a2991e108d0b7
<==        Row: 5992b89d9cfd4f0ba79a2991e108d0b7, 郑老师, 5992b89d9cfd4f0ba79a2991e108d1b7, ZWZ1, 5992b89d9cfd4f0ba79a2991e108d0b7
<==      Total: 2
Student(id=5992b89d9cfd4f0ba79a2991e108d017, name=ZWZ5, teacher=Teacher(id=5992b89d9cfd4f0ba79a2991e108d0b7, name=郑老师))
Student(id=5992b89d9cfd4f0ba79a2991e108d1b7, name=ZWZ1, teacher=Teacher(id=5992b89d9cfd4f0ba79a2991e108d0b7, name=郑老师))

Process finished with exit code 0

六、一对多

需求

  • 对于学生而言,都有一位老师
  • 对于老师而言,有多名学生
  • 在老师角度看,老师和学生就是一对多的关系
  • 要求输出老师的所有信息,包括他的所有学生

实体类

学生

代码语言:javascript复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private String id;
    private String name;
    // 对应老师的ID即可
    private String teacher;
}

老师

代码语言:javascript复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    private String id;
    private String name;
    // 老师拥有的学生列表
    private List<Student> students;
}

具体实现

mapper接口

代码语言:javascript复制
public interface TeacherMapper {
    List<Teacher> findAllTeacherMessage();
}

XML具体实现

collection 是一个一个复杂类型的集合

代码语言:javascript复制
<?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.TeacherMapper">

    <select id="findAllTeacherMessage" resultMap="teacherAndStudent">
        select t.id,t.name,s.id sid,s.name sname,s.teacher sTeacher
        from teacher t,student s
        where t.id = s.teacher;
    </select>

    <resultMap id="teacherAndStudent" type="teacher">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="students" ofType="student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="teacher" column="sTeacher"/>
        </collection>
    </resultMap>
</mapper>

测试

代码语言:javascript复制
@Test
public void testFindAllTeacherMessage(){
    SqlSession session = MybatisUtils.getSqlSession();
    TeacherMapper mapper = session.getMapper(TeacherMapper.class);
    List<Teacher> teachers = mapper.findAllTeacherMessage();
    for (Teacher teacher : teachers) {
        System.out.println(teacher);
    }
}

日志输出

可以看出系统直接执行 select t.id,t.name,s.id sid,s.name sname,s.teacher sTeacher from teacher t,student s where t.id = s.teacher; 查询到了结果

代码语言:javascript复制
Created connection 2142565033.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7fb4f2a9]
==>  Preparing: select t.id,t.name,s.id sid,s.name sname,s.teacher sTeacher from teacher t,student s where t.id = s.teacher; 
==> Parameters: 
<==    Columns: id, name, sid, sname, sTeacher
<==        Row: 5992b89d9cfd4f0ba79a2991e108d0b7, 郑老师, 5992b89d9cfd4f0ba79a2991e108d017, ZWZ5, 5992b89d9cfd4f0ba79a2991e108d0b7
<==        Row: 5992b89d9cfd4f0ba79a2991e108d0b7, 郑老师, 5992b89d9cfd4f0ba79a2991e108d1b7, ZWZ1, 5992b89d9cfd4f0ba79a2991e108d0b7
<==      Total: 2
Teacher(id=5992b89d9cfd4f0ba79a2991e108d0b7, name=郑老师, students=[Student(id=5992b89d9cfd4f0ba79a2991e108d017, name=ZWZ5, teacher=5992b89d9cfd4f0ba79a2991e108d0b7), Student(id=5992b89d9cfd4f0ba79a2991e108d1b7, name=ZWZ1, teacher=5992b89d9cfd4f0ba79a2991e108d0b7)])

Process finished with exit code 0

七、动态SQL

简介

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

新实体类

Book

代码语言:javascript复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
    private String id;
    private String name;
    private double money;
    private Date buyDate;
}

IF

mapper接口

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

XML具体实现

代码语言:javascript复制
<?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>

测试

代码语言:javascript复制
/**
 * 模拟查询书名和比某价格便宜的书
 * 如果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

代码语言:javascript复制
public interface BookMapper {
    /**
     * choose 标签测试
     *
     * 模拟查询书名和比某价格便宜的书
     * 如果姓名不为空,只看姓名
     * 如果姓名为空,就看价格
     *
     * @param name
     * @param money
     * @return
     */
    List<Book> findBookByNameOrMoney(@Param("name") String name, @Param("money") Double money);
}
代码语言:javascript复制
<?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>
代码语言:javascript复制
/**
 * 模拟查询书名和比某价格便宜的书
 * 如果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

代码语言:javascript复制
public interface BookMapper {
    /**
     * foreach 标签测试
     *
     * 查询指定书名的书列表
     *
     * @param books
     * @return
     */
    List<Book> findInName(@Param("books") List<String> books);
}
代码语言:javascript复制
<?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>
代码语言:javascript复制
/**
 * 查询指定书名的书列表
 */
@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指令

代码语言:javascript复制
@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();
}

输出日志如下

代码语言:javascript复制
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指令

代码语言:javascript复制
@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();
}

输出日志如下

代码语言:javascript复制
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中配置全局缓存

代码语言:javascript复制
<settings>
    <!--开启日志-->
    <setting name="logImpl" value="STDOUT_LOGGING"/>
    <!--驼峰转换-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!-- 开启全局缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>

在mapper层xml中,配置cache

代码语言:javascript复制
<cache eviction="FIFO"
       flushInterval="60000"
       size="512"
       readOnly="true"/>

测试

代码语言:javascript复制
@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指令

代码语言:javascript复制
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

0 人点赞