二级缓存的原理
二级缓存的原理和一级缓存一样,第一次查询会将数据放到缓存中,然后第二次查询直接去缓存读取。
但是一级缓存是基于 SqlSession 的,二级缓存是基于 mapper 的 namespace 的。
也就是说,多个 SqlSession 可以共享同一个二级缓存区域。如果两个 mapper 的 namespace 相同,那么即使是两个 mapper,这两个 mapper 执行 sql 查询的数据也将保存在相同的二级缓存区域中。
二级缓存的原理和一级缓存一样,第一次查询会将数据放到缓存中,然后第二次查询直接去缓存读取。
但是一级缓存是基于 SqlSession 的,二级缓存是基于 mapper 的 namespace 的。
也就是说,多个 SqlSession 可以共享同一个二级缓存区域。如果两个 mapper 的 namespace 相同,那么即使是两个 mapper,这两个 mapper 执行 sql 查询的数据也将保存在相同的二级缓存区域中。
在 MyBatis 中,一级缓存是默认开启的。
通过场景来理解:
1、在一个 SqlSession 中,对 User 表进行两次根据 ID 的查询,查看发出 sql 语句的情况。
/**
* 根据ID查询用户
*
* @param id
* @return
*/
@Select("select * from user where id=#{id}")
User findUserById(Integer id);
@Before
public void before() throws Exception {
System.out.println("before...");
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//根据 sqlSessionFactory 产生 session
sqlSession = sqlSessionFactory.openSession();
// 这样也是可以的,这样的话后面就不用每次都设置了
// sqlSession = sqlSessionFactory.openSession(true);
userMapper = sqlSession.getMapper(IUserMapper.class);
}
@Test
public void testFindUserById() {
//第一次查询,发出sql语句,并将查询出来的结果放进缓存中
User user = userMapper.findUserById(1);
System.out.println(user);
//第二次查询,由于是同一个sqlSession,会在缓存中查询结果 //如果有,则直接从缓存中取出来,不和数据库进行交互
User user2 = userMapper.findUserById(1);
System.out.println(user2);
}
缓存就是内存中的数据,常常来自对数据库查询结果的保存。
使用缓存可以避免频繁与数据库交互,进而提高响应速度。
MyBatis 也提供了对缓存的支持,分为 一级缓存 和 二级缓存。可以用下面的图来理解:
实现复杂映射我们之前可以在映射文件中通过配置来实现,使用注解开发后,我们可以通过 @Results 注解,@Result 注解,@One 注解和 @Many 注解组合完成复杂关系的配置。
| 注解 | 说明 |
|---|---|
| @Results |
代替的是标签 <ResultMap>,该注解中可以使用单个的 @Result 注解,也可以使用 @Result 集合。使用方式: @Results({@Result(), @Result()}) 或者 @Results(@Result()) |
| @Result |
代替了 <id> 标签和 <result> 标签@Result 中的属性介绍 column:数据库中的列名 property:要装配的属性名 one:需要使用 @One 注解( @Result(one=@One)() )many:需要使用 @Many 注解( @Result(many=@many)() ) |
| @One(一对一) | 代替了 <assocation> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。@One 注解属性介绍 select:指定用来多表查询的 sqlmapper 使用格式: @Result(column="", property="", one=(select="")) |
| @Many(多对一) | 代替了 <collection> 标签,是多表查询的关键,在注解中用来指定子查询返回对象集合。使用格式: @Result(property="", column="", many=@many(select="")) |
注解可以减少 Mapper 文件的编写,常用注解如下;
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以和@Result 一起使用,封装多个结果集
@One:实现一对一结果集封装
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用。
多对多查询的需求:查询所有用户的同时查询出该用户对应的所有角色。
@startuml
!theme plain
top to bottom direction
skinparam linetype ortho
class sys_role {
rolename: varchar(255)
roleDesc: varchar(255)
id: int(11)
}
class sys_user_role {
userid: int(11)
roleid: int(11)
}
class node2 as "user /* 用户表 */" {
username: varchar(50)
password: varchar(50)
birthday: varchar(50)
id: int(11)
}
sys_user_role ^-[#595959,plain]- sys_role : "roleid:id"
sys_user_role ^-[#595959,plain]- node2 : "userid:id"
@enduml
用户和订单表的关系为,一个用户有多个订单,一个订单只能属于一个用户。
一对多查询需求:查询多有用户,与此同时查询用户具有的订单信息。
对应的sql语句
select u.*,o.ordertime,o.total,o.uid from user u left join orders o on u.id = o.uid;
用户表和订单表的关系为:一个用户可以有多个订单,一个订单只能从属于一个用户
一对一查询需求:查询一个订单,同时查询出该订单所对应的用户
对应的sql语句:select * from orders o,user u where o.uid=u.id
查询结果如下:
| id | ordertime | total | uid | id | username | password | birthday |
|---|---|---|---|---|---|---|---|
| 1 | 2022-03-17 17:15:33 | 3000 | 1 | 1 | lucy | 123 | 2022-03-17 17:15:56 |
| 2 | 2022-03-17 17:15:33 | 4000 | 1 | 1 | lucy | 123 | 2022-03-17 17:15:56 |
| 3 | 2022-03-17 17:15:33 | 5000 | 2 | 2 | tom | 123 | 2022-03-17 17:15:56 |
1、利用Resources工具类加载配置文件,并转换成输入输出流
2、利用解析的配置,创建SqlSessionFactory工厂
3、生产SqlSession
4、SqlSession调用方法
Mybatis的官网:https://mybatis.org/mybatis-3/
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!--mybatis坐标-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql驱动坐标-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<!--单元测试坐标-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--⽇志坐标-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>