Mybatis的延迟加载
一、什么是延迟加载
延迟加载: 就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.好处: 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。
二、实现需求
需求: 查询账户(Account)信息并且关联查询用户(User)信息。如果先查询账户(Account)信息即可满足要求,当我们需要查询用户(User)信息时再查询用户(User)信息。把对用户(User)信息的按需去查询就是延迟加载。 association、collection 具备延迟加载功能。
三、使用association实现延迟加载
需求:
查询账户信息同时查询用户信息。
3.1 账户的持久层dao接口
package com.llb.dao;import com.llb.domain.Account;import java.util.List;/** * Ceate By llb on 2019/8/7
*/publicinterface AccountMapper {
/** * 查询账户所对应的的用户
*/ List findAccountAndUser();
}
3.2 账户的持久层映射文件
3.3 用户的持久层接口
package com.llb.dao;import com.llb.domain.User;import java.util.List;/** * 用户的持久层接口
* Ceate By llb on 2019/8/5
*/publicinterface UserMapper {
/** * 根据id查询所有用户
* @return*/ User findById(Integer id);
/** * 查询出所有用户,包含账户信息
* @return*/ List findAccountAndUser();
}
3.4 用户的持久层映射文件
3.5 开启mybatis的延迟加载策略
进入 Mybaits 的官方文档,找到 settings 的说明信息:
我们需要在 Mybatis 的配置文件 SqlMapConfig.xml 文件中添加延迟加载的配置。
3.6 编写测试只查账户信息不查用户信息
*/publicclass AccountTest {
InputStream in =null;
AccountMapper mapper =null;
SqlSession sqlSession =null;
/** * 在测试方法执行前执行
* @throws IOException
*/ @Before
publicvoidinit()throws IOException {
//1.读取配置文件,生成字节流in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取sqlSessionFactory对象SqlSessionFactory factory =new SqlSessionFactoryBuilder().build(in);
//3.获取sqlSession对象sqlSession = factory.openSession();
//4.获取dao的代理对象mapper = sqlSession.getMapper(AccountMapper.class);
}
/** * 测试方法执行后执行
* @throws IOException
*/ @After
publicvoiddestory()throws IOException {
sqlSession.commit();
//6.释放资源 sqlSession.close();
in.close();
}
/** * 查询出账户所对应的user
*/ @Test
publicvoid testFindAccountAndUser(){
List accountUser = mapper.findAccountAndUser();// for (Account account: accountUser) {// System.out.println(account);// } }
}
3.7 测试结果
当不进行配置时,立即加载,查询account所对应的user,一起将user查询出来:
配置后,对account进行查询放入到list集合中,并没有涉及到user对象,所以就没有发出 SQL 语句查询账户所关联的 User 对象的查询。:
四、使用collection实现缓存策略
同样我们也可以在一对多关系配置的
结点中配置延迟加载策略。
结点中也有 select 属性,column 属性。 需求:
完成加载用户对象时,查询该用户所拥有的账户信息。
4.1 在User实体类中加入List属性
package com.llb.domain;import java.io.Serializable;
import java.util.Date;import java.util.List;/** * Ceate By llb on 2019/8/5
*/publicclassUserimplements Serializable{
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
//一对多关系。一的方包含多的一方所有对象privateList accounts;
@Override
public String toString() {
return"User{" + "id=" + id + ", username='" + username + '\'' + ", address='" + address + '\'' + ", sex='" + sex + '\'' + ", birthday=" + birthday + ", accounts=" + accounts + '}';
}
publicList getAccounts() {
return accounts;
}
publicvoidsetAccounts(List accounts) {
this.accounts = accounts;
}
public Integer getId() {
return id;
}
publicvoid setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
publicvoid setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
publicvoid setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
publicvoid setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
publicvoid setBirthday(Date birthday) {
this.birthday = birthday;
}
}
4.2 编写用户接口和配置文件
UserMapper.class:
package com.llb.dao;import com.llb.domain.User;import java.util.List;/** * 用户的持久层接口
* Ceate By llb on 2019/8/5
*/publicinterface UserMapper {
/** * 根据id查询所有用户
* @return*/ User findById(Integer id);
/** * 查询出所有用户,包含账户信息
* @return*/ List findAccountAndUser();
}
UserMapper.xml:
select * from user
select * from user where id = #{id}
4.3 使用测试方法进行测试
publicclass UserTest {
InputStream in =null;
UserMapper mapper =null;
SqlSession sqlSession =null;
/** * 在测试方法执行前执行
* @throws IOException
*/ @Before
publicvoidinit()throws IOException {
//1.读取配置文件,生成字节流in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取sqlSessionFactory对象SqlSessionFactory factory =new SqlSessionFactoryBuilder().build(in);
//3.获取sqlSession对象sqlSession = factory.openSession();
//4.获取dao的代理对象mapper = sqlSession.getMapper(UserMapper.class);
}
/** * 测试方法执行后执行
* @throws IOException
*/ @After
publicvoiddestory()throws IOException {
sqlSession.commit();
//6.释放资源 sqlSession.close();
in.close();
}
/** * 查询出所有用户所对应的账户
*/ @Test
publicvoid findUserAndAccount(){
List users = mapper.findAccountAndUser();
}
}
测试结果:
我们没有使用Accout,也只对User进行了查询。
Mybatis缓存
待更新。。。
源码:https://github.com/PopsiCola/SSM-mybatis/tree/association_lazy
欢迎star