05-MyBatis【基于xml开发travel小案例、MyBatis注解开发、缓存】

文章目录

    • demo:基于xml开发travel小案例
      • 一、旅游网数据表的设计与存储
        • 1.1 数据库设计概要
        • 1.2 表与表之间关系
        • 1.3 业务需求
      • 二、根据业务需求使用 Mybatis获取数据库中数据
        • 1.1 题目要求
        • 1.2 需求
      • 三、代码演示
    • 六、MyBatis注解开发
      • 1、概述
      • 2、注解实现CURD
      • 3、注解之主键自增回填
      • 4、注解实现结果集映射
      • 5、注解实现动态sql
          • 方式1: 脚本标签
          • 方式2: @SelectProvider
          • 方式3:@SelectProvider+SQL类
      • 6、注解实现多表查询
          • 一对一
          • 一对多(了解)
      • 7、注解实现延迟加载
    • 七、Mybatis缓存【了解】
      • 1、一级缓存
      • 2、二级缓存

demo:基于xml开发travel小案例

一、旅游网数据表的设计与存储

1.1 数据库设计概要

`1)商家通过入驻旅游平台,可发布相关的旅游线路信息,一个旅游线路属于一个线路分类,同时一个线路分类下可关联多个旅游线路;

`2)普通用户注册并登录平台后,可浏览商家发布的旅游线路信息;

`3)普通用户可通过收藏夹收藏相关的旅游线路;

数据库名称:travel ,库下表名定义如下:

*表名* *描述*
tab_user 用户表
tab_route 路线表
tab_favorite 收藏表
tab_category 分类表
tab_seller 商家表

用户表 tab_user 用户信息的定义

*字段* *类型* *长度* *是否为空* *注释*
id bigint 18 N 主键
real_name varchar 200 N 姓名
telephone varchar 12 N 电话
sex char 200 Y 性别
username varchar 100 N 账户
password varchar 32 N 密码
birthday datetime 0 Y 生日
email varchar 100 Y 邮箱

路线表 tab_route 路线信息表定义

*字段* *类型* *长度* *是否为空* *注释*
id bigint 18 N 主键
route_name varchar 200 N 线路名称
price decimal (12,4) N 价格
route_Introduce varchar 2000 Y 线路描述
flag char 1 N 标记
is_theme_tour char 1 N 是否主题之旅
attention_count int 11 N 关注数
category_id bigint 18 N 分类ID
seller_id bigint 18 N 商家ID

收藏表 tab_favorite 用户收藏的线路关联表

*字段* *类型* *长度* *是否为空* *注释*
id bigint 18 N 主键
user_id bigint 18 N 用户Id
route_id bigint 18 N 路线Id

分类表 tab_category线路信息的分类管理

*字段* *类型* *长度* *是否为空* *注释*
id bigint 18 N 主键
category_name varchar 100 N 分类名称
category_url varchar 255 N 分类链接

商家表 tab_seller商家信息的定义,商家登录后台时的账户信息

*字段* *类型* *长度* *是否为空* *注释*
id bigint 18 N 主键
seller_name varchar 200 N 商家姓名
telephone varchar 12 N 电话
address varchar 200 Y 地址
username varchar 100 N 账户
password varchar 32 N 密码
birthday datetime 0 Y 生日

1.2 表与表之间关系

05-MyBatis【基于xml开发travel小案例、MyBatis注解开发、缓存】_第1张图片

1.3 业务需求

根据以下要求,编写SQL(操作过程中**可以往表中自由添加测试数据,校验SQL)

1) 按照业务需求定义商家表,用户表,线路表,线路分类和收藏表(SqlYog可视化操作导出SQL或手写DDL皆可)

2) 给用户表中telephone添加唯一约束(SqlYog可视化操作导出SQL或手写DDL皆可)

3) 使用SQL向用户表全字段批量插入2条测试数据 

4) 使用SQL完成user_id为2的用户对route_id为2的线路的收藏(insert语句)与取消收藏(delete语句)功能

5) 使用select语句查询姓名为'XXX'的用户收藏过哪些旅游线路(显示线路的所有字段信息)

6) 使用SQL统计每个线路分类下各有多少旅游线路数量(显示线路分类名称,数量)

7) 使用SQL统计每个线路分类下用户的收藏数量,并倒叙排序(查询字段包含线路分类名称,数量)

补充:线路分类下对应的线路收藏数如果为0,则不显示;

8) 使用SQL查询id为2的用户收藏过哪些旅游线路,包含线路表所有字段,线路分类名称和商家电话

9) 使用SQL根据商家名称(比如seller_name = 'XXX')查询其发布的旅游线路有哪些用户收藏(显示用户表所有字段信息)(5分)

二、根据业务需求使用 Mybatis获取数据库中数据

1.1 题目要求

搭建Mybatis开发环境

  1. 导入依赖相关依赖jar,配置Mybatis核心配置文件

  2. 定义pojo类:User,Category,Favorite,Route,Seller;

  3. 创建相关接口,并与xml映射文件绑定

  4. 加载核心配置文件,完成业务功能

1.2 需求

1) 定义好各个Pojo类,mapper接口和映射文件,完成根据用户id(比如id=1)查询用户信息功能(10分)

2) 使用Mybatis完成用户注册功能(insert插入)(5分)

3) 使用Mybatis完成user_id为1的用户对route_id为6的线路的收藏(insert语句)与取消收藏(delete语句)功能(5分)

4) 使用Mybatis根据用户名(比如张三)查询其收藏过哪些旅游线路(显示线路的所有字段信息)(5分)

5) 使用Mybatis统计每个线路分类下各有多少旅游线路数量(查询字段包含线路分类名称,数量)(5分)

6) 使用Mybatis统计每个线路分类下用户的收藏数量,并降序排序(查询字段包含线路分类名称,收藏数量)(5分)

7) 使用Mybatis查询id为2的用户收藏过哪些旅游线路,,包含线路表所有字段,线路分类名称和商家电话(5分);

8) 使使用Mybatis根据商家名称(比如:xxx)查询其发布过的旅游线路有哪些用户收藏(5分)

三、代码演示

六、MyBatis注解开发

1、概述

Mybatis为用户提供了快速的开发方式,因为有时候大量的XML配置文件的编写时非常繁琐的,

因此Mybatis也提供了更加简便的基于注解(Annnotation)的配置方式。

注解配置的方式在很多情况下能够取代mybatis的映射文件,提高开发效率。

2、注解实现CURD

@Insert:保存
         Value:sql语句(和xml的配置方式一模一样)
@Update:更新
         Value:sql语句
@Delete: 删除
         Value:sql语句
@Select: 查询
         Value:sql语句
@Options:可选配置(获取主键)
         userGeneratedKeys:开关,值为true表示可以获取主键 相当于select last_insert_id()
         keyProperty     :对象属性
         keyColumn       : 列名
【第一步】将mybatis全局配置文件mybatis‐config.xml中的mapper路径改为包扫描或者class路径
 说明:因为没有了映射文件,所以我们这里采用加载接口方式,
 需要告知mybatis哪个接口的方法上的注解需要被执行。
【第二步】编写接口和注解
【第三步】测试

代码演示

1) 配置核心配置文件
<mappers>
    <!--基于扫包方式加载mapper接口-->
    <package name="com.day08.mapper"/>
</mappers>

2) 定义接口
public interface UserMapper {
     
    @Insert("insert into tb_user values(null,#{userName},#{password},#{name}," +
    "#{age},#{sex})")
    Integer addUser(User user);
    
    @Delete("delete from tb_user where id=#{id}")
	Integer deleteByUserId(@Param("id") Integer id);

    @Update("update tb_user set user_name=#{userName},password=#{password}," +
    "name=#{name},age=#{age},sex=#{sex} where id=#{id}")
    Integer updateUser(User user);
    
    @Select("select * from tb_user")
	List<User> findAll();
}

3) 测试
public void test(){
       
    UserMapper userMapper = MybatisUtil.getMapper(UserMapper.class);
    ........
}

3、注解之主键自增回填

1) 接口
@Insert("insert into tb_user values(null,#{userName},#{password},#{name}," +
"#{age},#{sex})")
@Options(useGeneratedKeys = true,keyColumn = "id" ,keyProperty = "id")
Integer addUserAndGetFk(User user);

2) 测试
@Test
public void test6(){
     
    UserMapper mapper = 
    MybatisUtil.getMapper(UserMapper.class);
    User user = new User();
    user.setAge(18);
    user.setName("小明");
    user.setSex(0);
    user.setUserName("xiaoming");
    user.setPassword("12345");
    mapper.addUserAndGetFk(user);
    System.out.println(user.getId());
    MybatisUtil.commit();
    MybatisUtil.close();
}

4、注解实现结果集映射

如果数据表的列名和pojo实体类的属性名不一致,会导致数据表的数据无法封装到实体类属性值中,

对此我们有如下解决方案:

public @interface Results {
     
    Result[] value() default {
     };
}

// value属于Result数组类型,而Result属于一个注解,注解的属性如下:
public @interface Result {
     
    //对应数据表的列
    String column() default "";
    //对应pojo类的属性
    String property() default "";
    //javaType:返回的对象类型
    Class<?> javaType() default void.class;
    //one: 一对一配置 相当于xml中association标签
    One one() default @One;
    //many: 一对多配置 相当于xml中collection标签
    Many many() default @Many;
}
目标:使用注解的方式给取别名后的字段,映射到实体类中,并查询所有用户信息;
注意:为方便演示效果,可将之前核心配置文件中的开启驼峰自动映射设置为false1) 接口
@Select("select * from tb_user where id=#{id}")
@Results(id="userMap",
 value = {
     
 @Result(column = "id",property = "id",id=true),
 @Result(column = "user_name",property = "userName")
 })
User findById(Long id);
2) 测试
@Test
public void test5(){
     
    UserMapper userMapper = MybatisUtil.getMapper(UserMapper.class);
    User user = userMapper.findById(1L);
    System.out.println(user);
    MybatisUtil.close();
}

5、注解实现动态sql

方式1: 脚本标签
在接口上添加: 标签,标签体中编写sql语句,
sql语句与之前XML配置文件中的一致即可;
这种方式在写法上面和 XML 中的写法是一样,支持 XML 的动态SQL语法,可以在上面的字符串中
写  等 标签的语法。
1) 定义接口
@Select("<script>
        select * from tb_user where sex=1\n" +
    " \n" +
    " and user_name like concat('%',#{uName},'%')\n" +
    " </if>
        </script>")
@ResultMap(value = "userMap")
List<User> findUserByName(@Param("uName") String name);
方式2: @SelectProvider
使用 @SelectProvider 注解,注解中的type 参数是提供构建 SQL 的类,method 是构建 SQL 的方法。
构建 SQL 的方法的参数要和接口的参数一致,并且多个参数要使用@Param命名参数。
1)接口
@SelectProvider(type = SqlProvider.class,method = "findUserByName")
@ResultMap(value = "userMap")
List<User> findUserByName2(@Param("uName") String name);
2)创建提供sql的工具类
public class SqlProvider {
     
    public String findUserByName(@Param("uName") String name){
     
        String sql="select * from tb_user where sex=1";
        if(name!=null){
     
         	sql+=" and user_name like concat('%',#{uName},'%')";
         }
        return sql;
     }
}
方式3:@SelectProvider+SQL类
上述实现过程中,sql拼接容易出错,
我们可借助mybatis提供的一个对象:SQL完成sql语句拼接。
创建SQL对象   SQL sql = new SQL();
链式编程,    每个方法返回值都是SQL类对象;
1) 定义接口
@SelectProvider(type = SqlProvider.class,method = "findUserByName3")
@ResultMap(value = "userMap")
List<User> findUserByName3(@Param("uName") String name);
2) 定义提供sql的类
public String findUserByName3(@Param("uName") String name){
     
     SQL sql = new SQL();
     sql = sql.SELECT("*").FROM("tb_user").WHERE("sex=1");
     if(name!=null){
     
     	sql = sql.AND().WHERE("user_name like concat('%',#{uName},'%')");
     }
     return sql.toString();
}
测试
@Test
public void test8(){
     
    UserMapper mapper = MybatisUtils.getMapper(UserMapper.class);
    //select * from tb_user where sex=1;
     // List users = mapper.findUserByName(null);
     //select * from tb_user where sex=1 and user_name like concat('%',?,'%')
    List<User> users = mapper.findUserByName("zhang");
    System.out.println(users);
    MybatisUtils.close();
}

6、注解实现多表查询

注意:使用注解方式实现多表查询只能按照分步查询,不能使用连接查询

一对一
一对一映射核心映射注解:
@Results(value = {
     
//主键属性
@Result(column = "xx",property = "xx",id = true),
//普通属性
@Result(column = "xx",property = "xx"),
 //一对一关联查询
 @Result(column = "xx",property = "xx",javaType = xx.class,one = @One(select = "方法全限定名"))
})

【需求】注解方式实现,查询订单编号20140921003订单信息,并查询出下单人信息;

【步骤】
【SQL分析】
-- 基于xml:
select tb_user.*,tb_order.id as order_id,tb_order.order_number from tb_user,tb_order where tb_user.id=tb_order.user_id
and tb_order.order_number='20140921003';

-- 如果基于注解开发,不同的表下的数据,必须分段加载
-- 查询订单信息
select * from tb_order where order_number='20140921003'; -- user_id:1
-- 查询用户信息
select * from tb_user where id=1;

1)定义根据id查询用户的接口
@Select("select * from tb_user where id=#{userId}")
@ResultMap(value = "userMap")
User findById(@Param("userId") Long id);

2)定义根据订单标号查询订单的接口
public interface OrderMapper {
     
     @Select("select * from tb_order where order_number=#{orderNumber}")
     @Results(value = {
     
     @Result(column = "id",property = "id",id = true),
     @Result(column = "order_number",property = "orderNumber"),
     @Result(column = "user_id",
     one = @One(select = 
    "com.heima.mapper.UserMapper.findById"),
     property = "user"
)})
 Order findByOrderNumber(@Param("orderNumber") String orderNumber);
}

3)测试
@Test
public void test11(){
     
     OrderMapper orderMapper = MybatisUtils.getMapper(OrderMapper.class);
     Order order = orderMapper.findByOrderNumber("20140921003");
     System.out.println(order);
     MybatisUtils.close();
}
4)效果

05-MyBatis【基于xml开发travel小案例、MyBatis注解开发、缓存】_第2张图片

一对多(了解)
一对多核心映射配置:
@Results(value = {
     
    //主键映射
    @Result(column = "xx",property = "xx",id=true),
    //普通字段映射
    @Result(column = "xx",property = "xx"),
    //一对多关联查询
     @Result(column = "xx",property = "xx",javaType = List.class,many = @Many(
     select = "从表查询集合方法的全限定名称"
    ))
})

需求:查询id为1的用户及其订单信息 分步查询
说明:查询id是1的用户,一个用户可以有多个订单。所以用户和订单是一对多关系。

第一步:根据需求书写分步查询的sql语句;
-- 查询id为1的用户及其订单信息 分步查询
select * from tb_user where id=1;
-- 根据用户id查询订单集合
select * from tb_order where user_id=1;


第二步:给OrderMapper接口添加根据用户ID查询订单信息的方法;
@Select("select * from tb_order where user_id=#{uId}")
@Results(value = {
     
 @Result(column = "id",property = "id",id=true),
 @Result(column = "order_number",property = "orderNumber"),
})
List<Order> findOrdersByUserId(@Param("uId") Long userId);


第三步:在UserMapper接口添加根据id查询用户数据,并完成一对多映射配置;
@Select("select * from tb_user where id=#{uId}")
@Results(id="userInfoMap",
     value = {
     
     @Result(column = "id",property = "id",id=true),
     @Result(column = "user_name",property = "userName"),
     @Result(column = "id",
     many = @Many(select = "com.day08.mapper.OrderMapper.findOrdersByUserId"),
     property = "orders"
    )
})
User findUserInfoByUserId(@Param("uId") Long userId);

第四步:测试;
@Test
public void test13(){
     
    UserMapper mapper = MybatisUtil.getMapper(UserMapper.class);
    User user = mapper.findUserInfoByUserId(1L);
    System.out.println(user);
    MybatisUtil.close();
}

7、注解实现延迟加载

第一步:完成根据订单号查询订单及下单人(一对一)的注解查询;

第二步:在注解中添加延迟加载

1.因为基于xml的延迟加载配置作用域是全局的,对所有的接口都生效,所以为方便演示可将全局配置文件:
mybatis-config.xml中延迟加载配置注释掉;
<!--开启延迟加载-->
<!--<setting name="lazyLoadingEnabled" value="true"/>-->
<!--关闭积极加载-->
<!--<setting name="aggressiveLazyLoading" value="false"/>-->
    
2.懒加载配置在@One@Many注解中都存在;
@Select("select * from tb_order where order_number=#{orderNumber}")
@Results(value = {
     
     @Result(column = "id",property = "id",id=true),
     @Result(column = "order_number",property = "orderNumber"),
    //1)column = "user_id":获取user_id字段对应的值
    //2)one = @One(select = "com.day08.mapper.UserMapper.findById"):表示获取的字段user_id的值传给这个方法
    //3)property = "orderUser":表示将第二步中方法执行返回的结果赋值给orderUser变量
    @Result(column = "user_id" ,
     one = @One(select = "com.day08.mapper.UserMapper.findById",fetchType = FetchType.LAZY),
     property = "orderUser")
})
Order findByOrderNumber(@Param("orderNumber") String orderNumber)
    
3.测试
@Test
public void test10(){
     
    OrderMapper mapper = MybatisUtil.getMapper(OrderMapper.class);
    Order order = mapper.findByOrderNumber("20140921003");
    System.out.println(order.getOrderNumber());
    System.out.println("开始使用用户信息");
    System.out.println(order.getOrderUser());
    MybatisUtil.close();
}

七、Mybatis缓存【了解】

缓存就是用来提高查询访问速度,就是将每次的访问记录缓存在一地方,在下次进行查询时首先访问的不是数据库,而是缓存,如果在缓存中查询到了该次查询条件的结果集就直接返回结果,不再访问数据库。这样就对数据库的操作次数上就减少了很多,从而提高访问速度。

在查询缓存的机制中有两种不同的作用域(生命周期),分别是一级缓存二级缓存

1、一级缓存

 MyBatis的一级查询缓存是由 org.apache.ibatis.cache.impl.PerpetualCache 类的 HashMap本地缓存实现的,它的作用域则是SqlSession,它的作用域也就是生命周期;
 假如同一个SqlSession中执行两次sql语句的查询,这两次的查询的位置是不同的,第一次查询时,由于没有缓存结果则是从数据库中进行查询结果,得到结果后写入缓存并将结果返回给查询语句,而在进行第二次查询时,这时缓存中已经有符合条件的结果集,这次的查询就会在缓存获得结果并返回,而不会向数据库进行查询。当SqlSession结束后相应的缓存也就销毁了。
 myBatis默认一级查询时开启状态;
1.概念:一级缓存属于本地缓存,SqlSession级别的;
2.原理:
 1)在同一个SqlSession,发生了一次查询,查询的结果会存入一级缓存;
 2)第二次再发生相同查询时,直接从缓存中获取数据,不再与数据库建立连接查询数据;
3.注意:一级缓存,默认是开启的,无法关闭。
1) 测试一级缓存
需求:完成根据id查询用户数据;
测试步骤:用同一个session根据id查询用户2,然后查看日志打印sql的情况进行判断判断;
1.在相同的sqlsession下调用mapper接口执行2次查询,第二次数据从一级缓存中获取;
/**
 * 测试一级缓存
*/
@Test
public void test14(){
     
    UserMapper userMapper = MybatisUtil.getMapper(UserMapper.class);
    //1.根据用户ID查询用户信息 一级缓存中没有数据,那么就会去数据库查询(发送sql)
    User user = userMapper.findById(1L);
    //2.相同的条件再次查询,就会被一级缓存名称,不发送sql到mysqlserver
    User user2 = userMapper.findById(1L);
    System.out.println(user);
    System.out.println(user2);
}


2.开启两个session,调用相同的方法,查看sql执行次数;
public class TestAll2 {
     
    private static SqlSession session1;
    private static SqlSession session2;
    static {
     
    InputStream in = null;
    try {
     
     in = Resources.getResourceAsStream("mybatis-config.xml");
     } catch (IOException e) {
     
     e.printStackTrace();
     }
    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
    session1=sessionFactory.openSession();
    session2=sessionFactory.openSession();
     }
    @Test
    public void test1(){
     
        UserMapper mapper1 = session1.getMapper(UserMapper.class);
        UserMapper mapper2 = session2.getMapper(UserMapper.class);
        User user1 = mapper1.findById(1l);
        User user2 = mapper2.findById(1l);
        System.out.println(user1);
        System.out.println(user2);
     }
}
说明:一级缓存是session级别,sessin与session之间不能共享缓存;


3.一级缓存失效的情况
①查询条件不一致:
说明:相同的session下可根据id=1和id=2去查询,发现需要查询2;
@Test
public void test3(){
     
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = userMapper.findById(1l);
    System.out.println(user);
    //说明:两次查询,条件不一样,不会被缓存名称,此时应该打印两次sql
    User user2 = userMapper.findById(2l);
    System.out.println(user2);
} 
②sqlSession不同;
说明:获取两个sesion,然后在两个sesion中获取相同类型的动态代理对象,进行测试;


③两次查询期间存在增删改操作;
说明:在执行update、insert、delete的时候,即使操作的不是和一级缓存中的是同一条记录,都会清空一级缓存。
/**
 * 测试一级缓存失效
*/
@Test
public void test15(){
     
    UserMapper userMapper = MybatisUtil.getMapper(UserMapper.class);
    //1.根据用户ID查询用户信息 一级缓存中没有数据,那么就会去数据库查询
    (发送sql)
    User user = userMapper.findById(1L);
    //2.当当前session发生增删改操作,就会清除一级缓存
    userMapper.deleteByUserId(13);
    //3.此时因为一级缓存中数据被清空了,所以需要从数据库再次查询
    User user2 = userMapper.findById(1L);
    System.out.println(user);
    System.out.println(user2);
}


④手动清除一级缓存;
使用:sqlSession.clearCache();可以强制清除缓存;
    @Test
    public void test6(){
     
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    //共打印2次sql
    User user = userMapper.findById(12l);
    System.out.println(user);
    //清空当前session下的一级缓存
    sqlSession.clearCache();
    //此时需要再次去数据库查询
    User user2 = userMapper.findById(12l);
    System.out.println(user2);
}

2、二级缓存

概念:全局缓存 ,namespace级别;
mybatis 的二级缓存的作用域:mapper范围的(即映射文件级别的,多个sqlSession可以共享二级缓存数据);
原理:
 在一个sqlSession,进行了一次查询,会把查询结果存入一级缓存;
 当sqlSession关闭之后,mybatis会把一级缓存中的数据存入二级缓存中;
 当我们再次发生相同的查询时,会从二级缓存中命中;
 场景:
在用户通过id查询一个商品信息,执行完查询方法之后会将sqlSession释放掉,当再次发送请求查询同一个商品信息时会再次获取一个sqlSession来执行查询,那么此时如果配置了二级缓存的话,就可以直接从二级缓存中获取信息,而不用再次去数据库查询了。
    
二级缓存条件:
1、手动开启:
    1.全局配置中: 默认已开启。
    映射文件中:
    2.注解方式:或者在接口上添加注解 @CacheNamespace
    
2、第一个session必须关闭;
    说明:由于缓存数据是在sqlSession调用close方法时,放入二级缓存的,
    因此在测试二级缓存时必须先将第一个sqlSession关闭;
    
3、二级缓存的对象必须序列化,例如:User对象必须实现Serializable接口。
说明:因为二级缓存的原理就是将对象进行序列化
测试二级缓存
开启二级缓存方式:  在映射文件(UserMapper.xml)中添加<cache />;
 或者在Mapper接口添加@CacheNamespace注解开启;
测试思路:session1获取mapper进行查询,然后关闭session1,session2获取mapper相同条件二次查询;
1)在核心配置文件下开启二级缓存
<!--开启驼峰映射-->
<settings>
     <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!--开启二级缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>
    
2)接口下标注开启namespace二级缓存
@CacheNamespace(blocking = true)
public interface UserDao {
     
 .....
}


3)测试 
/**
二级缓存测试
测试思路:session1获取mapper进行查询,然后关闭session1,session2获取mapper相同条件二次查询;
*/
@Test
public void test2(){
     
    UserMapper mapper1 = session1.getMapper(UserMapper.class);
    UserMapper mapper2 = session2.getMapper(UserMapper.class);
    //1.session1根据id=1查询数据,查询完毕数据存入一级缓存
    User user1 = mapper1.findById(1l);
    //2.session1调用close方法,会将session1的一级缓存数据存储到二级缓存下
    session1.close();
    //3.session2根据id=1查询用户信息,发现没有走数据库查询,走的是二级缓存
    User user2 = mapper2.findById(1l);
    System.out.println(user1);
    System.out.println(user2);
}


二级缓存失效的情况
/**
二级缓存测试失效
第二个sqlSession在执行update、insert、delete的时候,也同样会清空二级缓存中的内容。
*/
@Test
public void test3(){
     
    UserMapper mapper1 = session1.getMapper(UserMapper.class);
    UserMapper mapper2 = session2.getMapper(UserMapper.class);
    //1.session1根据id=1查询数据,查询完毕数据存入一级缓存
    User user1 = mapper1.findById(1l);
    //2.session1调用close方法,会将session1的一级缓存数据存储到二级缓存下
    session1.close();
    //3.session2进行增删改操作,会清空二级缓存
    mapper2.deleteByUserId(13);
    //4.session2根据id=1查询用户信息,发现二级缓存中没有数据,那么从数据库查询
    User user2 = mapper2.findById(1l);
    System.out.println(user1);
    System.out.println(user2);
}

你可能感兴趣的:(数据库学习,mybatis,mysql,数据库,java)