文章目录
MyBatis中延迟加载,全局和局部的开启使用与关闭
1、问题提出
在之前的文章一对多中,当我们有一个用户,他又一百个账户。
(1)在查询用户时,要不要把关联的账户信息查询出来?
(2)在查询账户时,要不要把关联的用户信息查询出来?
对于第一个问题,我们应该是什么时候需要查询账户信息,才查询。没必要每次查询用户信息都把账户信息也查询出来。因为如果每次都查询出账户信息,对我们的内存开销是很大的,而且每次查询也都不一定用到账户信息。
对于第二个问题,我们就可以在查询账户信息的时候查询出关联的用户信息,因为我们如果只是单纯的账户信息没有说明用户是谁,这对于我们来说是不友好的。也没什么意义,所以在每次查询账户信息的时候都要显示出关联的用户信息。
2、延迟加载和立即加载
第一个问题其实就是延迟加载。
第二个问题就是立即加载。
延迟加载
在真正的使用数据时才发起查询,不用的时候不查。按需加载(懒加载)。
立即加载
不管用不用,只要一调用方法,马上发起查询。
3、三种对应的表关系中的加载
四种表 关系:一对一,一对多,多对多。
一对多、多对多:通常情况下,我们都是采用延迟加载。
多对一、一对一:通常情况下,我们都是采用立即加载。
4、打开全局延迟加载(实现一对一的延迟加载)
这里的项目结构和mybatis关联查询里面的大部分内容是一样的,我们只需要更改一些配置信息。
更改mybatis-config.xml 中的信息
在这里添加两条setting标签配置信息。根据mybatis的文档
需要设置这两个属性。才能开启延迟加载。
<settings> <!-- 打开全局延迟加载的开关 --> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>
java
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置延迟加载策略 -->
<settings>
<!-- 打开全局延迟加载的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<typeAliases>
<package name="cn.fpl1116.pojo"/>
</typeAliases>
<!--使用dev环境-->
<environments default="dev">
<environment id="dev">
<!--事务-->
<transactionManager type="JDBC"></transactionManager>
<!--
type="POOLED":连接池
-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<!--加载mapper映射文件-->
<mappers>
<package name="cn.fpl1116.mapper"/>
</mappers>
</configuration>
5、实现一对多的延迟加载(将上面设置的全局延迟加载给注释掉)
编写UserMapper.xml
java
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.fpl1116.mapper.UserMapper">
<resultMap id="getUserById2Result" type="cn.fpl1116.pojo.User">
<id column="id" property="id"></id>
<result column="username" property="username"/>
<result column="address" property="address"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<!--延迟加载的一对多-->
<!--
property="accountList":属性名
ofType="com.by.pojo.Account":集合的泛型,等价于resultType
select="com.by.mapper.AccountMapper.selectAccountByUid":要调用的select标签的id
column="id":传递给select查询的参数
fetchType="lazy":局部开启懒加载
-->
<collection property="accountList"
ofType="cn.fpl1116.pojo.Account"
select="cn.fpl1116.mapper.AccountMapper.selectAccountByUid"
column="id"
fetchType="lazy">
</collection>
</resultMap>
<select id="getUserById2" parameterType="int" resultMap="getUserById2Result">
<!-- SELECT u.*, a.id aid, a.uid uid, a.money money FROM user u LEFT JOIN account a ON u.id=a.uid WHERE u.id=#{id}-->
select * from user where id=#{id}
</select>
</mapper>
在UserMapper.xml中添加select查询语句
java
<select id="selectAccountByUid" parameterType="int" resultType="cn.fpl1116.pojo.Account">
SELECT * FROM account WHERE uid=#{uid}
</select>
在UserMapper.java中添加属性
java
User getUserById2(Integer id);
编写测试类
java
@Test
public void testGetUserById2(){
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById2(41);
System.out.println(user.getUsername());
List<Account> accountList = user.getAccountList();
for (Account account : accountList) {
System.out.println(account);
}
}
延迟加载运行结果如下:
6、测试一对多的延迟加载,对比观察输出结果
将测试类中的另一个想要获得的信息给注释掉,如下:
java
@Test
public void testGetUserById2(){
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById2(41);
System.out.println(user.getUsername());
//List<Account> accountList = user.getAccountList();
//for (Account account : accountList) {
// System.out.println(account);
//}
}