首先我们先思考一个问题,假设:在一对多中,我们有一个用户,他有100个账户。

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

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

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

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

  搞清楚这两个简单的问题后,我们就可以引出延迟加载和立即加载的特性。

  延迟加载:在真正使用数据的时候才发起查询,不用的时候不查询关联的数据,延迟加载又叫按需查询(懒加载)

  立即加载:不管用不用,只要一调用方法,马上发起查询。

  使用场景:在对应的四种表关系中,一对多、多对多通常情况下采用延迟加载,多对一、一对一通常情况下采用立即加载。

  理解了延迟加载的特性以后再看Mybatis中如何实现查询方法的延迟加载,在MyBatis 的配置文件中通过设置settings的lazyLoadingEnabled属性为true进行开启全局的延迟加载,通过aggressiveLazyLoading属性开启立即加载。看一下官网的介绍,然后通过一个实例来实现Mybatis的延迟加载,在例子中我们展现一对多表关系情况下,通过实现查询用户信息同时查询出该用户所拥有的账户信息的功能展示一下延迟加载的实现方式以及延迟加载和立即加载的结果的不同之处。

lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 true | false false
aggressiveLazyLoading 当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载(参考 lazyLoadTriggerMethods)。 true | false false (在 3.4.1 及之前的版本默认值为 true)

  

  1.用户类以及账户类

public class User implements Serializable{
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accountList; get和set方法省略.....
} public class Account implements Serializable{
private Integer id;
private Integer uid;
private Double money; get和set方法省略.....
}

注意因为我们是查找用户的同时查找出其所拥有的账户所以我们需要在用户类中增加账户的集合的属性,用来封装返回的结果。

  2.在UserDao接口中声明findAll方法

/**
* 查询所有的用户
*
* @return
*/
List<User> findAll();

  3.在UserDao.xml中配置findAll方法的映射

<resultMap id="userAccountMap" type="com.example.domain.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<collection property="accountList" ofType="com.example.domain.Account" column="id"
select="com.example.dao.AccountDao.findAllByUid"/>
</resultMap>
<select id="findAll" resultMap="userAccountMap">
SELECT * FROM USER;
</select>

  主要的功能实现位于 <collection property="accountList" ofType="com.example.domain.Account" column="id" select="com.example.dao.AccountDao.findAllByUid"/>中,对于账户列表的信息通过collection集合来映射,通过select指定集合中的每个元素如何查询,在本例中select的属性值为AccountDao.xml文件的namespace   com.example.dao.AccountDao路径以及指定该映射文件下的findAllByUid方法,通过这个唯一标识指定集合中元素的查找方式。因为在这里需要用到根据用户ID查找账户,所以需要同时配置一下findAllByUid方法的实现。

  4.配置collection中select属性所使用的方法 findAllByUid

AccountDao接口中添加
/**
* 根据用户ID查询账户信息
* @return
*/
List<Account> findAllByUid(Integer uid); AccountDao.xml文件中配置
<select id="findAllByUid" resultType="com.example.domain.Account">
SELECT * FROM account WHERE uid = #{uid};
</select>

  5.在Mybatis的配置文件中开启全局延迟加载

configuration>
<settings>
<!--开启全局的懒加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--关闭立即加载,其实不用配置,默认为false-->
<setting name="aggressiveLazyLoading" value="false"/>
<!--开启Mybatis的sql执行相关信息打印-->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<typeAliases>
<typeAlias type="com.example.domain.Account" alias="account"/>
<typeAlias type="com.example.domain.User" alias="user"/>
<package name="com.example.domain"/>
</typeAliases>
<environments default="test">
<environment id="test">
<!--配置事务-->
<transactionManager type="jdbc"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test1"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--配置映射文件的路径-->
<mappers>
<mapper resource="com/example/dao/UserDao.xml"/>
<mapper resource="com/example/dao/AccountDao.xml"/>
</mappers>
</configuration>

  6.测试方法

    private InputStream in;
private SqlSession session; private UserDao userDao;
private AccountDao accountDao;
private SqlSessionFactory factory;
@Before
public void init()throws Exception{
//获取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//获取工厂
factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); userDao = session.getMapper(UserDao.class);
accountDao = session.getMapper(AccountDao.class);
}
@After
public void destory()throws Exception{
session.commit();
session.close();
in.close();
}
@Test
public void findAllTest(){
List<User> userList = userDao.findAll();
// for (User user: userList){
// System.out.println("每个用户的信息");
// System.out.println(user);
// System.out.println(user.getAccountList());
// }
}

测试说明:当我们注释了findAllTest()方法中的for循环打印的时候,我们将不会需要用户的账户信息,按照延迟加载的特性程序只会查询用户的信息,而不会查询账户的信息。当我我们放开for循环打印的时候我们使用到了用户和账户的信息,程序会同时将用户以及对应的账户信息打印出来。

  7.测试结果

  (1)注释for循环,不使用数据,这时候不需要查询账户信息,我们能在控制台中看到sql执行结果是因为在Mybatis配置文件中添加了logImpl的配置,具体参考第5步中的配置信息

    (2)通过for循环打印查询的数据,使用数据,这时候因为使用了数据所以将查询账户信息,我们发现用户和账户查询都进行了执行

Mybatis延迟加载的实现以及使用场景的更多相关文章

  1. mybatis源代码分析:mybatis延迟加载机制改进

    在上一篇博客<mybatis源代码分析:深入了解mybatis延迟加载机制>讲诉了mybatis延迟加载的具体机制及实现原理. 可以看出,如果查询结果对象中有一个属性是需要延迟加载的,那整 ...

  2. mybatis源代码分析:深入了解mybatis延迟加载机制

    下文从mybatis(3.2.7)延迟加载样例讲起,逐步深入其实现机制. 下面的例子是Student类关联一个Teacher对象,在访问Student对象时,不立即加载其关联的Teacher对象,而是 ...

  3. 【MyBatis】MyBatis 延迟加载策略

    MyBatis 延迟加载策略 文章源码 什么是延迟加载 延迟加载,就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据,也被成为懒加载. 好处:先从单表查询,需要时再从关联表去关联查询,大大提 ...

  4. Mybatis延迟加载和查询缓存

    摘录自:http://www.linuxidc.com/Linux/2016-07/133593.htm 阅读目录 一.延迟加载 二.查询缓存 一.延迟加载 resultMap可以实现高级映射(使用a ...

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

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

  6. mybatis——延迟加载

    ------------------------------------------------SqlMapConfig.xml------------------------------------ ...

  7. mybatis延迟加载

    配置完成后可能会报错Cannot enable lazy loading because CGLIB is not available. Add CGLIB to your classpath 是由于 ...

  8. Mybatis学习记录(七)----Mybatis延迟加载

    1.什么是延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载功能. 需求: ...

  9. mybatis和hibernate区别和应用场景

    hibernate:是一个标准ORM框架(对象关系映射).入门门槛较高的,不需要程序写sql,sql语句自动生成了. 对sql语句进行优化.修改比较困难的. 应用场景: 适用与需求变化不多的中小型项目 ...

随机推荐

  1. koa2服务端使用jwt进行鉴权及路由权限分发

    大体思路 后端书写REST api时,有一些api是非常敏感的,比如获取用户个人信息,查看所有用户列表,修改密码等.如果不对这些api进行保护,那么别人就可以很容易地获取并调用这些 api 进行操作. ...

  2. Excel催化剂开源第16波-VSTO开发之脱离传统COM交互以提升性能

    在VSTO开发或其他COM技术开发过程中,甚至VBA也是,在和Excel交互中,难免会遇到性能瓶颈问题,COM技术的交互实在太慢,对大量数据读写等操作,耗时太长,容易卡用户界面以为是程序死机等等. 在 ...

  3. Polya定理与Burnside引理

    也许更好的阅读体验 \(Burnside引理\) 公式 \(\begin{aligned}L=\frac{1}{|G|}\sum_{i=1}^{|G|}D_{G_i}\end{aligned}\) 一 ...

  4. springboot集成activiti6.0多数据源的配置

    最近公司开始开发springboot的项目,需要对工作流进行集成.目前activiti已经发布了7.0的版本,但是考虑到6.0版本还是比较新而且稳定的,决定还是选择activiti6.0的版本进行集成 ...

  5. Java多线程笔记总结

    1.线程的三种创建方式 对比三种方式: 通过继承Thread类实现 通过实现Runnable接口 实现Callable接口 第1种方式无法继承其他类,第2,3种可以继承其他类: 第2,3种方式多线程可 ...

  6. 【iOS】XIB 调整视图大小

    使用 XIB 创建视图的时候,拖拽 UIView 到画布时,大小是不可调整的,如何自由调整大小呢? 选中 UIView 并打开属性面板,将 Simulated Metrics 中的 Size 设为 F ...

  7. poj 3714 寻找最近点对

    参考自<编程之美>169页,大概原理就是把区间分成两部分,然后递归找每一部分中最近的点对,还有一种情况就是这个点对分属于这两部分,然后选两部分中的部分点枚举即可,取其最小值. //2013 ...

  8. python log 设置

    # -*- coding: utf-8 -*- import loggingfrom logging.handlers import TimedRotatingFileHandler  # 按时间处理 ...

  9. LDAP 服务搭建和后期管理

    LDAP 服务 本文主要在debian配置,如果需要在CentOS上部署,需要修改大部分的路劲,这里需要自行修改. LDAP 服务按照个人理解,也可使理解为一个数据库,但是这个数据库的读写性能不像 M ...

  10. 初试kafka消息队列中间件一 (只适合初学者哈)

    初试kafka消息队列中间件一 今天闲来有点无聊,然后就看了一下关于消息中间件的资料, 简单一点的理解哈,网上都说的太高大上档次了,字面意思都想半天: 也就是用作消息通知,比如你想告诉某某你喜欢他,或 ...