一、mybatis的延迟加载

问题:在一对多中,当一个用户有100个账户.

1、在查询用户的时候,要不要把关联的账户查出来?

答:在查询用户时,用户下的账户信息应该是:什么时候使用,什么时候查询

2、在查询账户的时候,要不要把关联的用户查出来?

答:在查询账户时,账户的所属用户信息应该随着账户查询时一起查询出来

什么是延迟加载

在真正使用数据时才发起查询,不用的时候不查询。按需加载(懒加载)

什么是立即加载

不管用不用,只要一调用方法,马上发起查询

在对应的四种表关系中:一对多,多对一,一对一,多对多

一对多,多对多:通常情况下我们都是采用延迟加载

多对一(mybatis无此概念),一对一:采用立即加载

需求:查询账户(Account)信息并且关联查询用户(User)信息。如果先查询账户(Account)信息即可满足要求,当我们需要查询用户(User)信息时再查询用户(User)信息。把对用户(User)信息的按需去查询就是延迟加载。

我们使用了resultMap来实现一对一,一对多,多对多关系的操作。主要是通过 association、collection 实现一对一及一对多映射。association、collection 具备延迟加载功能。

一对一实现延迟加载

需求:

查询账户信息同时查询用户信息。

1、先通过 AccountDao.xml 配置文件中association配置延迟加载

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.itheima.dao.AccountDao"><!--将结果封装为一个resultMap--><!--定义封装account和user的resultMap--><resultMap id="accountUserMap" type="account"><!--colum是数据库中的列名,property是java程序中的--><id property="ID" column="id"></id><result property="UID" column="UID"></result><result property="MONEY" column="MONEY"></result><!--一对一的关系映射:封装user的内容--><!--select属性指定的内容:查询用户的唯一标识:column属性指定的内容:用户根据id查询时,所需要的参数的值--><association property="user"  javaType="user" select="com.itheima.dao.UserDao.findById" column="uid"></association></resultMap><!--查询所有account--><select id="findAllAccount" resultMap="accountUserMap">select * from account ;</select><!--根据用户id查找Account--><select id="findAccountByUid" resultType="account">select * from account where uid=#{uid};</select></mapper>

知识点:

1、select: 填写我们要调用的 select 映射的 id

2、column : 填写我们要传递给 select 映射的参数

(column属性指定的内容:用户根据id查询时,所需要的参数的值)

看UserDao.xml文件中相对应的方法

 <!--根据id查询--><select id="findById" parameterType="Integer" resultType="user">select * from user where id=#{id};</select>

2、在主配置SqlMapConfig.xml文件中开启mybatis的延迟加载策略

<!--配置延迟加载--><settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/></settings>

3、测试类代码

@Testpublic void testFindAllAccount(){//执行方法List<Account> accounts = accountDao.findAllAccount();/*  for (Account account : accounts) {System.out.println(account);System.out.println(account.getUser());}*/}

只查账户信息:

当把测试类的注释内容恢复,即查账户和账户下的用户信息

未开启延时加载配置

配置之后

即加了延时配置之后,可以需要信息的时候再输出,不需要就不输出

一对多实现延迟加载

需求:完成加载用户对象时,查询用户所拥有的账户信息

同样我们也可以在一对多关系配置的< collection>结点中配置延迟加载策略。

< collection>结点中也有 select 属性,column 属性。

1、在UserDAo中编写根据用户id查找账户的方法

 /*根据id查询*/List<Account> findById(Integer id);

2、在UserDao.xml中的< collection>配置延迟加载

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.itheima.dao.UserDao"><!--对用户和account一对多关系的查询结果进行封装--><resultMap id="userAccountMap" type="user"><!--对用户封装--><id property="id" column="id"></id><result property="username" column="username"></result><result property="address" column="address" ></result><result property="sex" column="sex" ></result><result property="birthday" column="birthday" ></result><!--配置user对象中accounts集合的映射--><!--property集合名,ofType 集合中的类型--><!--因为是用用户的id去查的,colimn写id--><collection property="accounts" ofType="account" select="com.itheima.dao.AccountDao.findAccountByUid" column="id"></collection></resultMap><!--查找所有用户下的所有account--><select id="findAll" resultMap="userAccountMap">SELECT * FROM USER ;</select><!--根据id查询--><select id="findById" parameterType="Integer" resultType="account">select * from user where id=#{id};</select></mapper>

注意:因为是用用户的id去查的,所以column写idu

看AccountDao.xml里面对应的方法

 <!--根据用户id查找Account--><select id="findAccountByUid" resultType="account">select * from account where uid=#{uid};</select>

3、主配置文件在上面已经配置过,所以直接看测试类

  @Testpublic void testFindAll(){//执行方法List<User> users = userDao.findAll();/*      for (User user : users) {System.out.println("-------------------");System.out.println(user);System.out.println(user.getAccounts());}*/}

只查看用户信息时:

当把测试类的注释内容恢复,即再查看用户的时候也查看账户信息

延迟的总思想:

在你需要打印查询某个信息A下关联的另一个B信息,你在A的相关配置文件中的 association、collection 标签中配置 select (B相关方法的id)和 column(需要传过去的参数), 来实现延迟加载。即想看关联信息就看,不想看就不看。(用的时候去调用对方文件的一个配置)

二、缓存

1、什么是缓存:

存在于内存中的临时数据。

2、为什么使用缓存?

减少和数据库的交互次数,提高执行效率

3、什么样的数据能使用缓存?生养的不能使用?

适用于缓存:经常查询并且不经常改变的。数据的正确与否对最终结果影响不大的。(缓存中的数据和数据库中的数据不一样)

不适用于缓存:经常改变的数据,数据的正确与否对最终结果影响很大的。例如:商品的库存,银行的汇率,股市的牌价

mybatis的一级缓存

指的是mybatis中SqlSession对象的缓存。

当我们执行查询之后,查询的结果同时会存入到SqlSession为我们提供的一块区域中,该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用。

当SqlSession对象消失时,maybatis的一级缓存也就消失了

一级缓存测试代码:

  /*测试一级缓存*/@Testpublic void testFirstLevelCache(){//执行方法User u1 = userDao.findById(50);User u2 = userDao.findById(50);System.out.println(u1==u2);//trueUser u3 = userDao.findById(51);
//        sqlSession.close();//再次获取sqlsession对象//        sqlSession = factory.openSession();sqlSession.clearCache(); //此方法也可以清空缓存userDao = sqlSession.getMapper(UserDao.class);User u4 = userDao.findById(51);System.out.println(u3==u4);//false}

知识点: sqlSession.clearCache(); //此方法也可以清空缓存

运行结果:

一级缓存的分析:

一级缓存是SqlSession范围的缓存,当调用SqlSession的 修改,添加,删除,commit(), close() 等方法时,就会清空一级缓存

测试类代码

 /*测试清空缓存*/@Testpublic void testCleanCache(){User u1 = userDao.findById(50);System.out.println(u1);User user=new User();user.setUsername("yyyy");user.setAddress("qqqqqqq");userDao.updateUser(user);User u2 = userDao.findById(50);System.out.println(u2);System.out.println(u1==u2);}

中间未加更新操作时,返回的对象是同一个,结果为true。加过之后,返回的对象是两个,结果为false

注意:update不能有返回值

mybatis的二级缓存

它指的是mybatis中SqlSessionFactory对象的缓存。

由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。

二级缓存的使用步骤:

1、让mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
不配也行,因为默认就是true
2、让当前的映射文件支持二级缓存(在UserDao.xml中配置)
3、让当前的操作支持二级缓存(在select标签中配置)

1、

 <!--配置二级缓存--><settings><setting name="cacheEnabled" value="true"/></settings>

2和3

测试类代码:

 /*测试二级缓存*/@Testpublic void testFirstLevelCache(){//执行方法SqlSession sqlSession1 = factory.openSession();UserDao userDao1 = sqlSession1.getMapper(UserDao.class);User u1 = userDao1.findById(50);System.out.println(u1);sqlSession1.close();//一级缓存消失SqlSession sqlSession2 = factory.openSession();UserDao userDao2 = sqlSession2.getMapper(UserDao.class);User u2 = userDao2.findById(50);System.out.println(u2);System.out.println(u1==u2);}

运行结果:

通过截图可以看到,经过上面的测试,
我们发现执行了两次查询,并且在执行第一次查询后,
我们关闭了一级缓存,再去执行第二次查询时,
我们发现并没有对数据库发出 sql 语句,
所以此时的数据就只能是来自于我们所说的二级缓存。

但为什么结果是false呢?

因为SqlSessionFactory的二级缓存,存放的是数据,而不是对象

二级缓存注意事项:

当我们使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化方式保存对象

mybatis延迟加载、缓存(一级、二级)相关推荐

  1. MyBatis 延迟加载,一级缓存(sqlsession级别)、二级缓存(mapper级别)设置

    什么是延迟加载 resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信息 ...

  2. MyBatis 延迟加载,一级缓存,二级缓存设置

    什么是延迟加载 resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信息 ...

  3. Mybatis(15)Mybatis延迟加载/缓存

    复制项目day03_eesy_03one2many到新建的项目day04_eesy_01lazy 1.删除项目中AccountUser类 2.IAccountDao接口中只保留findAll() 3. ...

  4. (十二)Mybatis的缓存机制

    文章目录 环境 Mybatis的缓存 一级缓存 一级缓存失效 方式一 方式二 二级缓存 MyBatis集成EhCache缓存 Mybatis学习目录 上一篇:(十一)MyBatis的高级映射及延迟加载 ...

  5. Mybatis(五) 延迟加载和缓存机制(一级二级缓存)

    踏踏实实踏踏实实,开开心心,开心是一天不开心也是一天,路漫漫其修远兮. --WZY 一.延迟加载 延迟加载就是懒加载,先去查询主表信息,如果用到从表的数据的话,再去查询从表的信息,也就是如果没用到从表 ...

  6. mybatis高级(3)_延迟加载_深度延迟_一级缓存_二级缓存

    设置延迟加载需要在mybatis.xml中设置 注: 侵入式延迟加载为真时是延迟加载 侵入式延迟加载为假时是深度延迟加载 <!-- 延迟加载和深度延迟加载 --><settings& ...

  7. MyBatis框架:延迟加载策策略、一级缓存、二级缓存

    MyBatis框架:延迟加载策略和缓存 Mybatis 延迟加载策略 1.1 何为延迟加载? 1.2 实现需求 1.3 使用association实现延迟加载 1.3.1 账户的持久层DAO接口 1. ...

  8. MyBatis→优缺点、select延迟加载、接口式MyBatis编程、一级缓存、二级缓存、集成Redis自定义缓存、Log4j

    MyBatis优缺点 select延迟加载 接口式MyBatis编程 一级缓存 一级缓存原理 一级缓存命中原则 一级缓存销毁 一级缓存避免脏读不可重复读 一级缓存与spring@事务 二级缓存 与一级 ...

  9. Mybatis学习第四天:Mybatis延迟加载懒加载,一级缓存,二级缓存,注解开发

    文章目录 Mybatis中的延迟加载 一对一进行延迟加载 一对多的延迟加载 缓存机制: 一级缓存 二级缓存 注解开发 注解开发--单表的增删改查 注解开发--建立表与实体类的对应关系 注解开发--多表 ...

最新文章

  1. html邮件模板编辑器_免费电子邮件群发工具推荐「aweber」
  2. mysql+实例夯住的监控_Nagios 里面监控MySQL 监控事务夯住(RUNNING)报警通知
  3. 一场低调的逆袭:清华文化如何改变了王兴和美团?
  4. 清北·NOIP2017济南考前冲刺班 DAY1 morning
  5. Java——面向对象进阶(final关键字,static关键字,匿名对象,内部类,四种访问修饰符,代码块)...
  6. matlab的cylinder函数,matlab cylinder怎么用,Matlab cylinder 函数
  7. 跑山么、后浪们?2.0T+237匹大马力后驱CT4山路试驾体验
  8. access insert语句怎么写_擦亮自己的眼睛去看SQLServer之简单Insert
  9. 为什么我的IP地址经常变化
  10. android桌面部件开发教程,Android桌面小部件AppWidget开发
  11. 非线性控制2.0——鲁棒控制之H无穷控制器设计
  12. 关于.net dll文件反编译
  13. 学习Java过程中创建动态数组的两种方法比较
  14. cesium 旋转图片
  15. vmware虚拟机ping不通主机
  16. 体系结构复习2——指令级并行(分支预测和VLIW)
  17. elementui级联选择器空children导致选择无法显示的问题
  18. 一位医疗 AI 创业者的自述:这个行业到底需要什么样的产品?
  19. 本科进了大厂拿高薪,为什么硕士和博士却要挤破头进高校?
  20. 玩转汉诺塔(hanoi)游戏

热门文章

  1. ISO常见的17大体系介绍,又涨知识了
  2. 下载protobuf-cpp-3.3.0.zip
  3. MapReduce:Map端Join算法实现
  4. UCC28951QPWRQ1 IC REG CTRLR 24TSSOP 稳压器
  5. 【调剂】2.25算机考研其余调剂信息
  6. 爬虫的自创建请求对象:报错AttributeError: 'str' object has no attribute 'items'
  7. 最常用web server---Nginx
  8. TCP三次握手的原因
  9. 智能合约 web3j Java_Java使用web3j调用智能合约
  10. 【C51单片机】数字电压表设计