概述
延迟加载:在真正使用数据的时候才发起查询,不用的时候不查询关联的数据,延迟加载又叫按需查询(懒加载)
立即加载(积极加载):不管用不用,只要一调用方法,马上发起查询
使用及案例
案例简介:
一个用户下有多个账户
表关系:一对多
需求:查询所有用户的信息;需要时,查询该用户下的账户信息
案例分析:
需要两张表:user用户表,account账户表
需要两个实体类(pojo)
需要两个mapper接口(sql映射)
需要两个mapper映射的xml
实体类如下:
User.java 此处省略构造及get和set
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
List<Account> accounts;
}
Account.java 此处省略构造及get和set
public class Account {
private Integer id;
private Integer uId;
private double money;
private User user;
}
mapper接口如下:
UserMapper.java
public interface UserMapper {
/**
* 查询所有用户信息
* @return
*/
List<User> findAll();
}
AccountMapper.java
public interface AccountMapper {
/**
* 根据id查询账户信息
* @param id
* @return
*/
Account findById(int id);
}
配置SqlMapConfig.xml核心文件
<?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>
<!--开启懒加载(延迟加载)-->
<!-- 将lazyLoadingEnable设置为 teue 启用延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将aggressiveLazyLoading设置为 false 将积极加载修改为消极加载-->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 指定对象的哪些方法触发一次延迟加载;默认值:equals,clone,hashCode,toString -->
<!-- 注意:由于默认值toString方法会触发延迟加载,而打印对象信息会触发toString();所以这里将toString 方法排除,才可看到延迟加载的效果 -->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode"/>
</settings>
</configuration>
mapper映射文件
映射文件中resultMap标签的association和collection 具备延迟加载功能
UserMapper.xml文件
<!--属性`namespace`指向接口全限定名-->
<mapper namespace="cn.dy.mapper.UserMapper">
<resultMap id="userAccount" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<!-- collection 可以使用延迟加载,property为当前实体类的属性名,column为传递给延迟方法的参数,select为延迟方法的全名称(包名.类名.方法名),ofType为当前集合属性的类型(collection标签支持该属性) -->
<!-- association ofType替换为javaType,javaType为当前属性的类型;其余用法相同, javaType(association标签支持该属性) -->
<collection property="accounts" column="id" select="cn.dy.mapper.AccountMapper.findById" ofType="account">
</collection>
</resultMap>
<select id="findAll" resultMap="userAccount">
SELECT id, username, birthday, sex, address
FROM user
</select>
</mapper>
AccountMapper.xml文件
<!--属性`namespace`指向接口全限定名-->
<mapper namespace="cn.dy.mapper.AccountMapper">
<!-- 上方sql查询语句触发延迟加载时将调用下方sql并返回数据信息 -->
<select id="findById" resultType="account" parameterType="java.lang.Integer">
SELECT id, money, UID FROM account
<where>UID = #{id}</where>
</select>
</mapper>
测试
TestUser.java
public class TestUser {
private InputStream inputStream;
private SqlSession sqlSession;
private UserMapper userMapper;
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() {
try {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
// 这里的事务默认不开启
sqlSession = sqlSessionFactory.openSession();
userMapper = sqlSession.getMapper(UserMapper.class);
}
@After
public void destory() {
// 这里提交事务
sqlSession.commit();
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
sqlSession.close();
}
// 查询所有的用户信息
@Test
public void testFindAll(){
List<User> users = userMapper.findAll();
for (User user : users) {
System.out.println(user);
// 这里调用getAccounts时会触发延迟加载,不调用时则不会触发延迟加载
System.out.println(user.getAccounts());
System.out.println("-----------------------------------------------");
}
}
}
使用场景
在对应的四种表关系中,一对多、多对多通常情况下采用延迟加载,多对一、一对一通常情况下采用立即加载