Mybatis
1. Mybatis 注解开发
1.1 mybatis 的常用注解说明
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与 @Result 一起使用,封装多个结果集
@ResultMap:实现引用 @Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider:实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用
1.2 使用 Mybatis 注解实现基本 CRUD
单表的 CRUD 操作是最基本的操作,都是基于 Mybaits 的映射文件来实现的。
1.2.1 pom文件引入坐标
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
1.2.1 创建数据库并编写实体类
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名称',
`birthday` datetime NULL DEFAULT NULL COMMENT '生日',
`sex` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别',
`address` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 49 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'tom', '1996-09-03 19:42:13', '男', '北京市');
INSERT INTO `user` VALUES (2, 'kate', '1996-09-03 19:42:13', '女', '天津市');
INSERT INTO `user` VALUES (3, 'test', '2021-09-03 12:22:07', '女', '重庆市');
package com.spg.pojo;
import java.io.Serializable;
import java.util.Date;
/**
* 用户的实体类
*/
public class User implements Serializable {
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getUserBirthday() {
return userBirthday;
}
public void setUserBirthday(Date userBirthday) {
this.userBirthday = userBirthday;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", userBirthday=" + userBirthday +
", userSex='" + userSex + '\'' +
", userAddress='" + userAddress + '\'' +
'}';
}
}
1.2.2 使用注解方式开发持久层接口
package com.spg.dao;
import com.spg.pojo.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* 用户的持久层接口
*/
public interface UserDao {
/**
* 查询所有用户
*/
@Select("select * from user")
@Results(id = "userMap",
value = {
@Result(id = true, column = "id", property = "userId"),
@Result(column = "username", property = "userName"),
@Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"),
@Result(column = "birthday", property = "userBirthday")
})
List<User> findAll();
/**
* 根据 id 查询一个用户
*/
@Select("select * from user where id = #{userId} ")
@ResultMap("userMap")
User findById(Integer userId);
/**
* 保存操作
*/
@Insert("insert into user(username, sex, address, birthday) values(#{userName}, #{userSex}, #{userAddress}, #{userBirthday})")
@SelectKey(keyColumn = "id", keyProperty = "userId", resultType = Integer.class,
before = false, statement = {"select last_insert_id()"})
int saveUser(User user);
/**
* 更新操作
*/
@Update("update user set username = #{userName}, sex = #{userSex}, address = #{userAddress}, birthday = #{userBirthday} where id = #{userId}")
int updateUser(User user);
/**
* 删除用户
*/
@Delete("delete from user where id = #{userId} ")
int deleteUser(Integer userId);
/**
* 查询使用聚合函数
*/
@Select("select count(*) from user ")
int findTotal();
/**
* 模糊查询
*/
@Select("select * from user where username like #{userName} ")
@ResultMap("userMap")
List<User> findByName(String userName);
}
1.2.3 编写 mybatis-config 配置文件
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_db?serverTimezone=UTC
jdbc.username=root
jdbc.password=root
<?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 文件的位置 -->
<properties resource="jdbcConfig.properties"/>
<!-- 配置别名的注册 -->
<typeAliases>
<package name="com.spg.pojo"/>
</typeAliases>
<!-- 配置环境 -->
<environments default="mysql">
<!-- 配置 mysql 的环境 -->
<environment id="mysql">
<!-- 配置事务的类型是 JDBC -->
<transactionManager type="JDBC"/>
<!-- 配置数据源 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 配置映射信息 -->
<mappers>
<!-- 配置 dao 接口的位置,它有两种方式
第一种:使用 mapper 标签配置 class 属性
第二种:使用 package 标签,直接指定 dao 接口所在的包
-->
<package name="com.spg.dao"/>
</mappers>
</configuration>
1.2.4 编写测试方法
/**
* mybatis 的注解 crud 测试
*/
public class MybatisAnnotationCRUDTest {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
private UserDao userDao;
@Before//junit 的注解
public void init()throws Exception{
//1.读取配置文件
in = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
//3.创建 session
session = factory.openSession();
//4.创建代理对象
userDao = session.getMapper(UserDao.class);
}
@After//junit 的注解
public void destroy()throws Exception {
//提交事务
session.commit();
//释放资源
session.close();
//关闭流
in.close();
}
/**
* 测试查询所有
*/
@Test
public void testFindAll() {
List<User> userList = userDao.findAll();
for (User user : userList) {
System.out.println(user);
}
}
/**
* 测试查询一个
*/
@Test
public void testFindById() {
User user = userDao.findById(1);
System.out.println(user);
}
/**
* 测试保存
*/
@Test
public void testSave() {
User user = new User();
user.setUserName("Lily");
user.setUserSex("女");
user.setUserAddress("上海市");
user.setUserBirthday(new Date());
int result = userDao.saveUser(user);
System.out.println("影响数据库记录的行数: " + result);
System.out.println("插入的主键值: " + user.getUserId());
}
/**
* 测试更新
*/
@Test
public void testUpdate() {
User user = userDao.findById(3);
user.setUserName("test");
user.setUserBirthday(new Date());
user.setUserSex("女");
user.setUserAddress("重庆市");
int result = userDao.updateUser(user);
System.out.println(result);
}
/**
* 测试删除
*/
@Test
public void testDelete() {
int result = userDao.deleteUser(3);
System.out.println(result);
}
/**
* 测试查询使用聚合函数
*/
@Test
public void testFindTotal() {
int result = userDao.findTotal();
System.out.println(result);
}
/**
* 测试模糊查询
*/
@Test
public void testFindByName() {
List<User> userList = userDao.findByName("%m%");
for(User user : userList) {
System.out.println(user);
}
}
}
1.3 使用注解实现复杂关系映射开发
1.3.1 复杂关系映射的注解说明
@Results 注解
代替的是标签 <resultMap>
该注解中可以使用单个 @Result 注解,也可以使用 @Result 集合
@Results({@Result(), @Result() })或 @Results(@Result())
@Resutl 注解
代替了 <id> 标签和 <result>标签
@Result 中 属性介绍:
id 是否是主键字段
column 数据库的列名
property 需要装配的属性名
one 需要使用的 @One 注解(@Result(one=@One)()))
many 需要使用的 @Many 注解(@Result(many=@many)()))
@One 注解(一对一)
代替了<assocation>标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
@One 注解属性介绍:
select 指定用来多表查询的 sqlmapper
fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。。
使用格式:
@Result(column=" ",property="",one= @One(select=""))
@Many 注解(多对一)
代替了<Collection>标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。
注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType
(一般为 ArrayList)但是注解中可以不定义;
使用格式:
@Result(property="",column="",many= @Many(select=""))
1.3.2 使用注解实现一对一复杂关系映射及延迟加载
需求:加载账户信息时并且加载该账户的用户信息,根据情况可实现延迟加载。(注解方式实现)
(1)添加 User 实体类及 Account 实体类
package com.spg.pojo;
import java.io.Serializable;
import java.util.Date;
/**
* 用户的实体类
*/
public class User implements Serializable {
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getUserBirthday() {
return userBirthday;
}
public void setUserBirthday(Date userBirthday) {
this.userBirthday = userBirthday;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", userBirthday=" + userBirthday +
", userSex='" + userSex + '\'' +
", userAddress='" + userAddress + '\'' +
'}';
}
}
-- ----------------------------
-- Table structure for account
-- ----------------------------
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
`ID` int NOT NULL COMMENT '编号',
`UID` int NULL DEFAULT NULL COMMENT '用户编号',
`MONEY` double NULL DEFAULT NULL COMMENT '金额',
PRIMARY KEY (`ID`) USING BTREE,
INDEX `FK_Reference_8`(`UID`) USING BTREE,
CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of account
-- ----------------------------
INSERT INTO `account` VALUES (1, 1, 10000);
INSERT INTO `account` VALUES (2, 2, 6000);
INSERT INTO `account` VALUES (3, 2, 4000);
package com.spg.pojo;
import java.io.Serializable;
/**
* 账户的实体类
*/
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//多对一关系映射:从表方应该包含一个主表方的对象引用
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
", user=" + user +
'}';
}
}
(2)添加账户的持久层接口并使用注解配置
package com.spg.dao;
import com.spg.pojo.Account;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
/**
* 账户的持久层接口
*/
public interface AccountDao {
/**
* 查询所有账户,采用延迟加载的方式查询账户的所属用户
* @return
*/
@Select("select * from account")
@Results(id="accountMap",
value= {
@Result(id = true, column="id",property="id"),
@Result(column="uid",property="uid"),
@Result(column="money",property="money"),
@Result(column="uid", property="user",
one = @One(select="com.spg.dao.UserDao.findById", fetchType= FetchType.LAZY) )
})
List<Account> findAll();
}
(3)添加用户的持久层接口并使用注解配置
package com.spg.dao;
import com.spg.pojo.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* 用户的持久层接口
*/
public interface UserDao {
/**
* 查询所有用户
*/
@Select("select * from user")
@Results(id = "userMap",
value = {
@Result(id = true, column = "id", property = "userId"),
@Result(column = "username", property = "userName"),
@Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"),
@Result(column = "birthday", property = "userBirthday")
})
List<User> findAll();
/**
* 根据 id 查询一个用户
*/
@Select("select * from user where id = #{userId} ")
@ResultMap("userMap")
User findById(Integer userId);
}
(4)测试一对一关联及延迟加载
package com.spg.dao;
/**
* 账户的测试类
*/
public class AccountDaoTest {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
private AccountDao accountDao;
@Before//junit 的注解
public void init()throws Exception{
//1.读取配置文件
in = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
//3.创建 session
session = factory.openSession();
//4.创建代理对象
accountDao = session.getMapper(AccountDao.class);
}
@After//junit 的注解
public void destroy()throws Exception {
//提交事务
session.commit();
//释放资源
session.close();
//关闭流
in.close();
}
@Test
public void findAll() {
List<Account> accountList = accountDao.findAll();
for (Account account : accountList) {
System.out.println(account);
}
}
}
测试结果:
2021-09-03 21:08:23,981 351 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Opening JDBC Connection
2021-09-03 21:08:25,152 1522 [ main] DEBUG source.pooled.PooledDataSource - Created connection 396283472.
2021-09-03 21:08:25,153 1523 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@179ece50]
2021-09-03 21:08:25,155 1525 [ main] DEBUG com.spg.dao.AccountDao.findAll - ==> Preparing: select * from account
2021-09-03 21:08:25,194 1564 [ main] DEBUG com.spg.dao.AccountDao.findAll - ==> Parameters:
2021-09-03 21:08:25,253 1623 [ main] DEBUG com.spg.dao.AccountDao.findAll - <== Total: 3
2021-09-03 21:08:25,255 1625 [ main] DEBUG com.spg.dao.UserDao.findById - ==> Preparing: select * from user where id = ?
2021-09-03 21:08:25,256 1626 [ main] DEBUG com.spg.dao.UserDao.findById - ==> Parameters: 1(Integer)
2021-09-03 21:08:25,262 1632 [ main] DEBUG com.spg.dao.UserDao.findById - <== Total: 1
2021-09-03 21:08:25,263 1633 [ main] DEBUG m.spg.dao.AccountDao.findByUid - ==> Preparing: select * from account where uid = ?
2021-09-03 21:08:25,263 1633 [ main] DEBUG m.spg.dao.AccountDao.findByUid - ==> Parameters: 1(Integer)
2021-09-03 21:08:25,265 1635 [ main] DEBUG m.spg.dao.AccountDao.findByUid - <== Total: 1
Account{id=1, uid=1, money=10000.0, user=User{userId=1, userName='tom', userBirthday=Wed Sep 04 03:42:13 CST 1996, userSex='男', userAddress='北京市'}}
2021-09-03 21:08:25,266 1636 [ main] DEBUG com.spg.dao.UserDao.findById - ==> Preparing: select * from user where id = ?
2021-09-03 21:08:25,266 1636 [ main] DEBUG com.spg.dao.UserDao.findById - ==> Parameters: 2(Integer)
2021-09-03 21:08:25,268 1638 [ main] DEBUG com.spg.dao.UserDao.findById - <== Total: 1
2021-09-03 21:08:25,268 1638 [ main] DEBUG m.spg.dao.AccountDao.findByUid - ==> Preparing: select * from account where uid = ?
2021-09-03 21:08:25,269 1639 [ main] DEBUG m.spg.dao.AccountDao.findByUid - ==> Parameters: 2(Integer)
2021-09-03 21:08:25,271 1641 [ main] DEBUG m.spg.dao.AccountDao.findByUid - <== Total: 2
Account{id=2, uid=2, money=6000.0, user=User{userId=2, userName='kate', userBirthday=Wed Sep 04 03:42:13 CST 1996, userSex='女', userAddress='天津市'}}
Account{id=3, uid=2, money=4000.0, user=User{userId=2, userName='kate', userBirthday=Wed Sep 04 03:42:13 CST 1996, userSex='女', userAddress='天津市'}}
2021-09-03 21:08:25,272 1642 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@179ece50]
2021-09-03 21:08:25,276 1646 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@179ece50]
1.3.3 使用注解实现一对多复杂关系映射
需求: 查询用户信息时,也要查询他的账户列表。使用注解方式实现。
分析: 一个用户具有多个账户信息,所以形成了用户(User)与账户(Account)之间的一对多关系。
(1)User 实体类加入 List
//一对多关系映射:主表方法应该包含一个从表方的集合引用
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
(2)添加用户的持久层接口并使用注解配置
package com.spg.dao;
import com.spg.pojo.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
/**
* 用户的持久层接口
*/
public interface UserDao {
/**
* 查询所有用户
* @return
*/
@Select("select * from user")
@Results(id="userMap",
value= {
@Result(id = true, column="id", property = "userId"),
@Result(column = "username", property = "userName"),
@Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"),
@Result(column = "birthday", property = "userBirthday"),
@Result(column = "id", property = "accounts",
many = @Many(select="com.spg.dao.AccountDao.findByUid", fetchType= FetchType.LAZY ) )
})
List<User> findAll();
}
(3)添加账户的持久层接口并使用注解配置
package com.spg.dao;
/**
* 账户的持久层接口
*/
public interface AccountDao {
/**
* 根据用户 id 查询用户下的所有账户
* @param userId
* @return
*/
@Select("select * from account where uid = #{userId} ")
List<Account> findByUid(Integer userId);
}
(4)测试一对多关联
package com.spg.dao;
import com.spg.pojo.Account;
import com.spg.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class UserDaoTest {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
private UserDao userDao;
@Before//junit 的注解
public void init()throws Exception{
//1.读取配置文件
in = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
//3.创建 session
session = factory.openSession();
//4.创建代理对象
userDao = session.getMapper(UserDao.class);
}
@After//junit 的注解
public void destroy()throws Exception {
//提交事务
session.commit();
//释放资源
session.close();
//关闭流
in.close();
}
@Test
public void findAll() {
List<User> userList = userDao.findAll();
for (User user : userList) {
System.out.println(user);
}
}
}
测试结果:
2021-09-03 21:10:21,248 353 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Opening JDBC Connection
2021-09-03 21:10:22,500 1605 [ main] DEBUG source.pooled.PooledDataSource - Created connection 396283472.
2021-09-03 21:10:22,501 1606 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@179ece50]
2021-09-03 21:10:22,505 1610 [ main] DEBUG com.spg.dao.UserDao.findAll - ==> Preparing: select * from user
2021-09-03 21:10:22,547 1652 [ main] DEBUG com.spg.dao.UserDao.findAll - ==> Parameters:
2021-09-03 21:10:22,626 1731 [ main] DEBUG com.spg.dao.UserDao.findAll - <== Total: 3
2021-09-03 21:10:22,630 1735 [ main] DEBUG m.spg.dao.AccountDao.findByUid - ==> Preparing: select * from account where uid = ?
2021-09-03 21:10:22,630 1735 [ main] DEBUG m.spg.dao.AccountDao.findByUid - ==> Parameters: 1(Integer)
2021-09-03 21:10:22,634 1739 [ main] DEBUG m.spg.dao.AccountDao.findByUid - <== Total: 1
User{userId=1, userName='tom', userBirthday=Wed Sep 04 03:42:13 CST 1996, userSex='男', userAddress='北京市', accounts=[Account{id=1, uid=1, money=10000.0}]}
2021-09-03 21:10:22,635 1740 [ main] DEBUG m.spg.dao.AccountDao.findByUid - ==> Preparing: select * from account where uid = ?
2021-09-03 21:10:22,635 1740 [ main] DEBUG m.spg.dao.AccountDao.findByUid - ==> Parameters: 2(Integer)
2021-09-03 21:10:22,636 1741 [ main] DEBUG m.spg.dao.AccountDao.findByUid - <== Total: 2
User{userId=2, userName='kate', userBirthday=Wed Sep 04 03:42:13 CST 1996, userSex='女', userAddress='天津市', accounts=[Account{id=2, uid=2, money=6000.0}, Account{id=3, uid=2, money=4000.0}]}
2021-09-03 21:10:22,637 1742 [ main] DEBUG m.spg.dao.AccountDao.findByUid - ==> Preparing: select * from account where uid = ?
2021-09-03 21:10:22,637 1742 [ main] DEBUG m.spg.dao.AccountDao.findByUid - ==> Parameters: 3(Integer)
2021-09-03 21:10:22,639 1744 [ main] DEBUG m.spg.dao.AccountDao.findByUid - <== Total: 0
User{userId=3, userName='test', userBirthday=Fri Sep 03 20:22:07 CST 2021, userSex='女', userAddress='重庆市', accounts=[]}
2021-09-03 21:10:22,640 1745 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@179ece50]
2021-09-03 21:10:22,641 1746 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@179ece50]
1.4 mybatis 基于注解的二级缓存
1.4.1 在 mybatis-config 中开启二级缓存支持
<!-- 配置二级缓存 -->
<settings>
<!-- 开启二级缓存的支持 -->
<setting name="cacheEnabled" value="true"/>
</settings>
1.4.2 在持久层接口中使用注解配置二级缓存
/**
* 用户的持久层接口
*/
@CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存
public interface UserDao {}