01_MyBatis的延迟加载

mybatis高级 - 图1何为延迟加载
通过前面的学习,我们已经掌握了 Mybatis中多表查询的配置及实现,可以实现对象的关联查询。实际开发过程中很多时候我们并不需要在加载用户信息时就一定要加载他的订单信息。此时就是我们所说的延迟加载。
mybatis高级 - 图2作用
就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.
mybatis高级 - 图3好处
先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
mybatis高级 - 图4应用
通常情况下,一对一查询不需要做延迟加载,一对多需要做延迟加载

02_一对一延迟加载实现

mybatis高级 - 图5使用前提
需要在sqlMapConfig.xml配置文件中开启延迟加载

  1. <settings>
  2. <setting name="lazyLoadingEnabled" value="true"/>
  3. </settings>

mybatis高级 - 图6需求:
通过订单延迟加载相应的用户信息
mybatis高级 - 图7POJO类

  1. public class Customer {
  2. private Long cid;
  3. private String cname;
  4. private int cage;
  5. //get/set方法
  6. }
  7. public class Order {
  8. private Long oid;
  9. private String oname;
  10. private Customer customer;
  11. private Integer cno;
  12. //get/set方法
  13. }


mybatis高级 - 图8映射文件

  1. <!‐‐
  2. 订单映射文件
  3. select属性:查询用户信息延迟加载的实现
  4. column属性:查询用户信息需要传递的参数,该参数从先加载的订单信息中获取.
  5. ‐‐>
  6. <mapper namespace="com.qzw.dao.IOrderDao">
  7. <resultMap type="com.qzw.bean.Order" id="orderCustomerMap">
  8. <id property="oid" column="oid"/>
  9. <result property="oname" column="oname"/>
  10. <association
  11. property="customer" javaType="com.qzw.bean.Customer" select="com.qzw.dao.ICustomerDao.selectCustomerById" column="cno"></association>
  12. </resultMap>
  13. <select id="selectOrderList" resultMap="orderCustomerMap"> select * from tb_order;
  14. </select>
  15. </mapper>
  16. <!‐‐ 用户映射文件 ‐‐>
  17. <select id="selectCustomerById" parameterType="int" resultType="com.qzw.bean.Customer">
  18. select * from tb_customer where cid = #{id};
  19. </select>


mybatis高级 - 图9测试

  1. @Test
  2. public void selectOrderList() {
  3. List < Order > list = orderDao.selectOrderList();
  4. //会触发查询用户信息list.get(0).getCustomer();
  5. }

03_一对多延迟加载实现

mybatis高级 - 图10需求:
通过用户信息延迟加载相应的订单信息
mybatis高级 - 图11POJO类

  1. public class Customer {
  2. private Long cid;
  3. private String cname;
  4. private int cage;
  5. private List < Order > list;
  6. //get/set方法
  7. }
  1. public class Order {
  2. private Long oid;
  3. private String oname;
  4. private Customer customer;
  5. private Integer cno;
  6. //get/set方法
  7. }


mybatis高级 - 图12映射文件

  1. <!‐‐
  2. 用户映射文件
  3. select属性:查询订单信息延迟加载实现 column属性:查询订单信息需要传递的参数,得先从已经加载的用户信息中获取
  4. ‐‐>
  5. <resultMap type="com.qzw.bean.Customer" id="customerOrderMap">
  6. <id property="cid" column="cid" />
  7. <result property="cname" column="cname" />
  8. <result property="cage" column="cage" />
  9. <collection
  10. property="list" ofType="com.qzw.bean.Order"
  11. select="com.qzw.dao.IOrderDao.selectOrderListByCustomerId" column="cid"></collection>
  12. </resultMap>
  13. <select id="selectCustomerById" parameterType="long" resultMap="customerOrderMap">
  14. select * from tb_customer where cid = #{id};
  15. </select>
  16. <!‐‐
  17. 订单映射文件
  18. ‐‐>
  19. <select id="selectOrderListByCustomerId" parameterType="long" resultMap="orderCustomerMap">
  20. select * from tb_order where cno = #{cno};
  21. </select>


mybatis高级 - 图13测试

  1. Customer customer = customerDao.selectCustomerById(1L);
  2. System.out.println(customer.getCname());
  3. System.out.println(customer.getList());

04_MyBatis的缓存

mybatis高级 - 图14什么是缓存?
存储在内存中的临时数据

mybatis高级 - 图15为什么使用缓存?
减少和数据库的交互次数,提高执行效率
mybatis高级 - 图16应用场景
mybatis高级 - 图17适用于缓存
经常查询并且不经常改变的
数据的正确与否对最终结果影响不大
mybatis高级 - 图18不适用于缓存 数据经常改变的
数据的正确与否对最终结果影响不大
mybatis高级 - 图19比如:
商品库存,银行汇率…

05_一级缓存的验证

mybatis高级 - 图20概念
一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除, commit(),
close()等方法时,就会清空一级缓存。
mybatis高级 - 图21验证

  1. public interface IUserDao {
  2. public User selectUserById(Long id);
  3. }
  4. < mapper namespace = "com.qzw.dao.IUserDao" >
  5. < select id = "selectUserById"
  6. parameterType = "long"
  7. resultType = "com.qzw.bean.User" > select * from user where id = # {
  8. id
  9. }; < /select>
  10. </mapper >
  11. @Test
  12. public void selectUserById() throws IOException {
  13. InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
  14. SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  15. SqlSession session = sessionFactory.openSession();
  16. IUserDao userDao = session.getMapper(IUserDao.class);
  17. User user1 = userDao.selectUserById(2l);
  18. session.clearCache();
  19. User user2 = userDao.selectUserById(2l);
  20. System.out.println(user1 == user2);
  21. }

05_增删改清空一级缓存

mybatis高级 - 图22概念
如果 sqlSession去执行commit操作(执行插入、更新、删除),清空 SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息
mybatis高级 - 图23以修改操作为例:

  1. InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
  2. SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  3. SqlSession session = sessionFactory.openSession();
  4. IUserDao userDao = session.getMapper(IUserDao.class);
  5. User user1 = userDao.selectUserById(2l);
  6. userDao.updateUser(new User(3l, "aaaa", "aa"));
  7. User user2 = userDao.selectUserById(2l);
  8. System.out.println(user1 == user2);
  9. session.commit();
  10. session.close();

06_MyBatis的二级缓存

mybatis高级 - 图24概念
二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

mybatis高级 - 图25使用步骤

mybatis高级 - 图26开启二级缓存

  1. <settings>
  2. <!‐‐ 开启缓存的支持 ‐‐>
  3. <setting name="cacheEnabled" value="true"/>
  4. </settings>

mybatis高级 - 图27在mapper映射文件配置标签

  1. <mapper namespace="com.qzw.dao.IUserDao">
  2. <!‐‐ 开启二级缓存的支持 ‐‐>
  3. <cache></cache>
  4. </mapper>

mybatis高级 - 图28配置statement上面的useCache属性

  1. <!‐‐设置 useCache=”true”代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置
  2. 为 false。‐‐>
  3. <select id="findById" resultType="user" parameterType="int" useCache="true">
  4. select * from user where id = #{uid}
  5. </select>







mybatis高级 - 图29注意事项
mybatis高级 - 图30二级缓存存储的并不是java对象,存储的是对象所对应的字符串信息,当从二级缓存取出 时,根据对应字符串生成新的对象,所以,使用二级缓存,会发现取出对象是不同的对象。但是,sql语句只执行了一次。

mybatis高级 - 图31测试代码

  1. @Test
  2. public void selectUserById() throws IOException {
  3. InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
  4. SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  5. SqlSession session = sessionFactory.openSession();
  6. IUserDao userDao = session.getMapper(IUserDao.class);
  7. User user1 = userDao.selectUserById(2l);
  8. //销毁第一次查询的一级缓存session.close();
  9. session = sessionFactory.openSession();
  10. userDao = session.getMapper(IUserDao.class);
  11. User user2 = userDao.selectUserById(2l);
  12. //销毁第二次查询的一级缓存session.close(); System.out.println(user1 == user2);
  13. }