缓存机制

正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持

  1. 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
  2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。
  3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。

Mybatis一级缓存测试

  1. package com.spiritmark.test;
  2. import menghan.domain.User;
  3. import spiritmark.util.MyBatisUtil;
  4. import org.apache.ibatis.session.SqlSession;
  5. import org.junit.Test;
  6. /**
  7. * @author gacl
  8. * 测试一级缓存
  9. */
  10. public class TestOneLevelCache {
  11. /*
  12. * 一级缓存: 也就Session级的缓存(默认开启)
  13. */
  14. @Test
  15. public void testCache1() {
  16. SqlSession session = MyBatisUtil.getSqlSession();
  17. String statement = "me.gacl.mapping.userMapper.getUser";
  18. User user = session.selectOne(statement, 1);
  19. System.out.println(user);
  20. /*
  21. * 一级缓存默认就会被使用
  22. */
  23. user = session.selectOne(statement, 1);
  24. System.out.println(user);
  25. session.close();
  26. /*
  27. 1. 必须是同一个Session,如果session对象已经close()过了就不可能用了
  28. */
  29. session = MyBatisUtil.getSqlSession();
  30. user = session.selectOne(statement, 1);
  31. System.out.println(user);
  32. /*
  33. 2. 查询条件是一样的
  34. */
  35. user = session.selectOne(statement, 2);
  36. System.out.println(user);
  37. /*
  38. 3. 没有执行过session.clearCache()清理缓存
  39. */
  40. //session.clearCache();
  41. user = session.selectOne(statement, 2);
  42. System.out.println(user);
  43. /*
  44. 4. 没有执行过增删改的操作(这些操作都会清理缓存)
  45. */
  46. session.update("me.gacl.mapping.userMapper.updateUser",
  47. new User(2, "user", 23));
  48. user = session.selectOne(statement, 2);
  49. System.out.println(user);
  50. }
  51. }

Mybatis二级缓存测试

1、开启二级缓存,在userMapper.xml文件中添加如下配置

  1. <mapper namespace="com.spiritmark.pojo.userMapper">
  2. <!-- 开启二级缓存 -->
  3. <cache/>

2、测试二级缓存

  1. package com.spiritmark.test;
  2. import spiritmark.gacl.domain.User;
  3. import spiritmark.util.MyBatisUtil;
  4. import org.apache.ibatis.session.SqlSession;
  5. import org.apache.ibatis.session.SqlSessionFactory;
  6. import org.junit.Test;
  7. /**
  8. 1. @author gacl
  9. 2. 测试二级缓存
  10. */
  11. public class TestTwoLevelCache {
  12. /*
  13. * 测试二级缓存
  14. * 使用两个不同的SqlSession对象去执行相同查询条件的查询,第二次查询时不会再发送SQL语句,而是直接从缓存中取出数据
  15. */
  16. @Test
  17. public void testCache2() {
  18. String statement = "me.gacl.mapping.userMapper.getUser";
  19. SqlSessionFactory factory = MyBatisUtil.getSqlSessionFactory();
  20. //开启两个不同的SqlSession
  21. SqlSession session1 = factory.openSession();
  22. SqlSession session2 = factory.openSession();
  23. //使用二级缓存时,User类必须实现一个Serializable接口===> User implements Serializable
  24. User user = session1.selectOne(statement, 1);
  25. session1.commit();//不懂为啥,这个地方一定要提交事务之后二级缓存才会起作用
  26. System.out.println("user="+user);
  27. //由于使用的是两个不同的SqlSession对象,所以即使查询条件相同,一级缓存也不会开启使用
  28. user = session2.selectOne(statement, 1);
  29. //session2.commit();
  30. System.out.println("user2="+user);
  31. }
  32. }

二级缓存补充说明

  1. 映射语句文件中的所有select语句将会被缓存。
  2. 映射语句文件中的所有insert,update和delete语句会刷新缓存。
  3. 缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回。
  4. 缓存会根据指定的时间间隔来刷新
  5. 缓存会存储1024个对象

cache标签常用属性:

  1. <cache
  2. eviction="FIFO" <!--回收策略为先进先出-->
  3. flushInterval="60000" <!--自动刷新时间60s-->
  4. size="512" <!--最多缓存512个引用对象-->
  5. readOnly="true"/> <!--只读-->

高级查询

表关系说明

  • 创建表
  1. CREATE TABLE tb_order (
  2. id int(11) NOT NULL AUTO_INCREMENT,
  3. user_id int(11) DEFAULT NULL,
  4. order_number varchar(255) DEFAULT NULL,
  5. create datetime DEFAULT NULL,
  6. updated datetime DEFAULT NULL,
  7. PRIMARY KEY (id)
  8. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

对应的实体类

  1. public class Order {
  2. private Integer id;
  3. private Long userId;
  4. private String orderNumber;
  5. private Date created;
  6. private Date updated;
  7. }

需求说明:

一对一查询

方法一:核心思想扩展Order对象,来完成映射

新建OrderUser实体类继承Order:

  1. public class OrderUser extends Order {
  2. private String userName;
  3. private String password;
  4. private String name;
  5. private Integer age;
  6. private Integer sex;
  7. private Date birthday;
  8. private Date created;
  9. private Date updated;
  10. }

OrderMapper接口:

  1. public interface OrderMapper {
  2. OrderUser queryOrderUserByOrderNumber(@Param("number") String number);
  3. }

配置OrderMapper:

  1. <mapper namespace="com.lx.mybatis.dao.OrderMapper">
  2. <select id="queryOrderUserByOrderNumber" resultType="com.zpc.mybatis.pojo.OrderUser">
  3. select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number}
  4. </select>
  5. </mapper>

测试:

  1. @Test
  2. public void queryOrderUserByOrderNumber() throws Exception {
  3. OrderUser orderUser = orderMapper.queryOrderUserByOrderNumber("201807010001");
  4. System.out.println(orderUser);
  5. }

方法二:面向对象的思想,在Order对象中添加User对象

在Order对象中添加User属性:

  1. public class Order {
  2. private Integer id;
  3. private Long userId;
  4. private String orderNumber;
  5. private Date created;
  6. private Date updated;
  7. private User user;
  8. }

接口:

  1. /**
  2. * 根据订单号查询订单用户的信息
  3. * @param number
  4. * @return
  5. */
  6. public Order queryOrderWithUserByOrderNumber(@Param("number") String number);

使用resultType不能完成自动映射,需要手动完成结果集映射resultMap:

  1. <resultMap id="OrderUserResultMap" type="com.LX.mybatis.pojo.Order" autoMapping="true">
  2. <id column="id" property="id"/>
  3. <!--association:完成子对象的映射-->
  4. <!--property:子对象在父对象中的属性名-->
  5. <!--javaType:子对象的java类型-->
  6. <!--autoMapping:完成子对象的自动映射,若开启驼峰,则按驼峰匹配-->
  7. <association property="user" javaType="com.LX.mybatis.pojo.User" autoMapping="true">
  8. <id column="user_id" property="id"/>
  9. </association>
  10. </resultMap>
  11. <select id="queryOrderWithUserByOrderNumber" resultMap="OrderUserResultMap">
  12. select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number}
  13. </select>

测试:

  1. @Test
  2. public void queryOrderWithUserByOrderNumber() throws Exception {
  3. Order order = orderMapper.queryOrderWithUserByOrderNumber("201807010001");
  4. System.out.println(order.getUser());
  5. }

一对多查询

一对多查询:查询订单,查询出下单人信息并且查询出订单详情。

Order类:

  1. public class Order {
  2. private Integer id;
  3. private Long userId;
  4. private String orderNumber;
  5. private Date created;
  6. private Date updated;
  7. private User user;
  8. private List<OrderDetail> detailList;
  9. }
  1. public class OrderDetail {
  2. private Integer id;
  3. private Integer orderId;
  4. private Double totalPrice;
  5. private Integer status;
  6. }

接口:

  1. /**
  2. * 根据订单号查询订单用户的信息及订单详情
  3. * @param number
  4. * @return
  5. */
  6. Order queryOrderWithUserAndDetailByOrderNumber(@Param("number") String number);

Mapper映射:

  1. <resultMap id="OrderUserDetailResultMap" type="com.LX.mybatis.pojo.Order" autoMapping="true">
  2. <id column="id" property="id"/>
  3. <!--collection:定义子对象集合映射-->
  4. <!--association:完成子对象的映射-->
  5. <!--property:子对象在父对象中的属性名-->
  6. <!--javaType:子对象的java类型-->
  7. <!--autoMapping:完成子对象的自动映射,若开启驼峰,则按驼峰匹配-->
  8. <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true">
  9. <id column="user_id" property="id"/>
  10. </association>
  11. <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true">
  12. <id column="id" property="id"/>
  13. </collection>
  14. </resultMap>
  15. <select id="queryOrderWithUserAndDetailByOrderNumber" resultMap="OrderUserDetailResultMap">
  16. select * from tb_order o
  17. left join tb_user u on o.user_id=u.id
  18. left join tb_orderdetail od on o.id=od.order_id
  19. where o.order_number = #{number}
  20. </select>

测试:

  1. @Test
  2. public void queryOrderWithUserAndDetailByOrderNumber() throws Exception {
  3. Order order = orderMapper.queryOrderWithUserAndDetailByOrderNumber("201807010001");
  4. System.out.println(order.getUser());
  5. System.out.println(order.getDetailList());
  6. }

多对多查询

多对多查询:查询订单,查询出下单人信息并且查询出订单详情中的商品数据。

OrderDetail类

  1. public class OrderDetail {
  2. private Integer id;
  3. private Integer orderId;
  4. private Double totalPrice;
  5. private Integer status;
  6. private Item item;
  7. }
  8. public class Item {
  9. private Integer id;
  10. private String itemName;
  11. private Float itemPrice;
  12. private String itemDetail;
  13. }

接口:

  1. /**
  2. * 根据订单号查询订单用户的信息及订单详情及订单详情对应的商品信息
  3. * @param number
  4. * @return
  5. */
  6. Order queryOrderWithUserAndDetailItemByOrderNumber(@Param("number") String number);

Mapper配置:

  1. <resultMap id="OrderUserDetailItemResultMap" type="com.LX.mybatis.pojo.Order" autoMapping="true">
  2. <id column="id" property="id"/>
  3. <association property="user" javaType="com.LX.mybatis.pojo.User" autoMapping="true">
  4. <id column="user_id" property="id"/>
  5. </association>
  6. <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true">
  7. <id column="detail_id" property="id"/>
  8. <association property="item" javaType="com.zpc.mybatis.pojo.Item" autoMapping="true">
  9. <id column="item_id" property="id"/>
  10. </association>
  11. </collection>
  12. </resultMap>
  13. <select id="queryOrderWithUserAndDetailItemByOrderNumber" resultMap="OrderUserDetailItemResultMap">
  14. select * ,od.id as detail_id from tb_order o
  15. left join tb_user u on o.user_id=u.id
  16. left join tb_orderdetail od on o.id=od.order_id
  17. left join tb_item i on od.item_id=i.id
  18. where o.order_number = #{number}
  19. </select>

测试:

  1. @Test
  2. public void queryOrderWithUserAndDetailItemByOrderNumber() throws Exception {
  3. Order order = orderMapper.queryOrderWithUserAndDetailItemByOrderNumber("201807010001");
  4. System.out.println(order);
  5. System.out.println(order.getUser());
  6. System.out.println(order.getDetailList());
  7. }

SQL语句如下 :

  1. CREATE TABLE tb_order (
  2. id int(11) NOT NULL AUTO_INCREMENT,
  3. user_id int(11) DEFAULT NULL,
  4. order_number varchar(255) DEFAULT NULL,
  5. create datetime DEFAULT NULL,
  6. updated datetime DEFAULT NULL,
  7. PRIMARY KEY (id)
  8. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
  9. INSERT INTO tb_order VALUES (‘1’, 2’, 201807010001’, 2018-07-01 19:38:35’, 2018-07-01 19:38:40’);
  10. CREATE TABLE tb_item (
  11. id int(11) NOT NULL,
  12. itemName varchar(255) DEFAULT NULL,
  13. itemPrice decimal(10,2) DEFAULT NULL,
  14. itemDetail varchar(255) DEFAULT NULL,
  15. PRIMARY KEY (id)
  16. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  17. INSERT INTO tb_item VALUES (‘1’, ‘袜子’, 29.90’, ‘香香的袜子’);
  18. INSERT INTO tb_item VALUES (‘2’, ‘套子’, 99.99’, ‘冈本001’);
  19. CREATE TABLE tb_orderdetail (
  20. id int(11) NOT NULL AUTO_INCREMENT,
  21. order_id int(11) DEFAULT NULL,
  22. total_price decimal(10,0) DEFAULT NULL,
  23. item_id int(11) DEFAULT NULL,
  24. status int(10) unsigned zerofill DEFAULT NULL COMMENT 0成功非0失败’,
  25. PRIMARY KEY (id)
  26. ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
  27. INSERT INTO tb_orderdetail VALUES (‘1’, 1’, 10000’, 1’, 0000000001’);
  28. INSERT INTO tb_orderdetail VALUES (‘2’, 1’, 2000’, 2’, 0000000000’);

时间过的很快 ! 快S2结业了 没时间 给大家更新了 希望大家记住

路在自己脚下,没有人可以决定你前进的方向。 加油!

持久层之 MyBatis: 第三篇 :缓存 And 高级查询的更多相关文章

  1. 从零搭建springboot服务02-内嵌持久层框架Mybatis

    愿历尽千帆,归来仍是少年 内嵌持久层框架Mybatis 1.所需依赖 <!-- Mysql驱动包 --> <dependency> <groupId>mysql&l ...

  2. 持久层之 MyBatis: 第一篇:快速入门

    MyBatis入门到精通 JDBC回顾 1.1.认识MyBatis 1.1.使用IDEA创建maven工程 1.2.引入mysql依赖包 1.3.准备数据 1.4 使用JDBC手写MyBatis框架 ...

  3. Java数据持久层框架 MyBatis之背景知识三

    摘录自:http://www.cnblogs.com/lcngu/p/5437281.html 对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.or ...

  4. 持久层之 MyBatis: 第二篇 :动态SQL And多表查询

    MyBatis入门到精通 完整CRUD UserDaoImpl 编写UserDao对应的UserDaoMapper.xml 添加UserDao的测试用例 编写UserDao的测试用例 解决数据库字段名 ...

  5. Java数据持久层框架 MyBatis之背景知识二

    对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...

  6. java持久层框架mybatis如何防止sql注入

    看到一篇很好的文章:http://www.jfox.info/ava-persistence-framework-mybatis-how-to-prevent-sql-injection sql注入大 ...

  7. Java数据持久层框架 MyBatis之背景知识一

    对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...

  8. 开源顶级持久层框架——mybatis(ibatis)——day02

    mybatis第二天    高级映射 查询缓存 和spring整合          课程复习:         mybatis是什么?         mybatis是一个持久层框架,mybatis ...

  9. 开源顶级持久层框架——mybatis(ibatis)——day01

    mybatis-day01     1.对原生态jdbc程序中的问题总结         1.1环境             java环境:jdk             eclipse:indigo ...

随机推荐

  1. synchronized关键字的内存语义

    以下内容摘自:Java并发编程之美 加锁和释放锁的语义:当获取锁以后会清空锁块内本地内存中将会被用到的共享变量,在使用这些共享变量的时从主内存进行加载,在释放锁时将本地内存中修改的 共享变量刷新到主内 ...

  2. transient关键字的作用以及几个疑问的解决

    目录 1.从Serilizable说到transient 2.序列化属性对象的类需要实现Serilizable接口? 3.不想被序列化的字段怎么办? 4.ArrayList里面的elementData ...

  3. PowerManagerService流程分析

    一.PowerManagerService简介 PowerManagerService主要服务Android系统电源管理工作,这样讲比较笼统,就具体细节上大致可以认为PowerManagerServi ...

  4. Kubernetes-20:日志聚合分析系统—Loki的搭建与使用

    日志聚合分析系统--Loki 什么是Loki? Loki 是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统.它的设计非常经济高效且易于操作,因为它不会 ...

  5. pyhon的6大基本数据类型

    1.数字型(Number) 1.1 整型(int) 整型包括所有的正整数,负整数还有0. 在python中所有的整型数据全部默认采用十进制进行表示,但我们还可以手动表示其他进制的整型,具体表示如下: ...

  6. 关于 spring security 对用户名和密码的校验过程

    1.执行 AuthenticationManager 认证方法 authenticate(UsernamePasswordAuthenticationToken) 2.ProviderManager ...

  7. LeetCode 049 Anagrams

    题目要求:Anagrams Given an array of strings, return all groups of strings that are anagrams. Note: All i ...

  8. 20200523_mysql中文乱码

    查看字符集: 方法一:show variables like '%character%'; 方法二:show variables like 'collation%';设置字符集: /*建立连接使用的编 ...

  9. 不是程序员,代码也不能太丑!python官方书写规范:任何人都该了解的 pep8

    不是程序员,代码也不能太丑!python官方书写规范:任何人都该了解的 pep8 简介:为什么要强调 书写规范 ?这其实并不关乎"美丑",而是为了 更高的效率(代码阅读.开发.维护 ...

  10. Java之选择排序(正序、逆序)

    public class SelectSort { public static void main(String[] args) { /** * @author JadeXu * @// TODO: ...