何为延迟加载
就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载。
好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关 联 查询多张表速度要快。
准备数据库表
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` datetime DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;
CREATE TABLE `account` (
`ID` int(11) NOT NULL COMMENT '编号',
`UID` int(11) DEFAULT NULL COMMENT '用户编号',
`MONEY` double DEFAULT NULL COMMENT '金额',
PRIMARY KEY (`ID`),
KEY `FK_Reference_8` (`UID`),
CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
使用 assocation 实现延迟加载
需求:查询账户信息同时查询用户信息,如果账户信息满足需求,就不需要查询用户信息。
实体类Account和User:
public class Account {
private String id;
private String uid;
private Double money;
private User user;
//省略了getXXX(),setXXX(),toString()方法
}
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
//省略了getXXX(),setXXX(),toString()方法
}
持久层账户Account接口:
public interface AccountMapper {
/***
* @Description 查询所有账户信息
* @Param: []
* @return: java.util.List<com.zy.domin.Account>
*/
List<Account> findAll();
}
持久层账户映射文件:
<?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="com.zy.dao.AccountMapper">
<resultMap id="accountMap" type="account">
<id property="id" column="id"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!--
select:填写我们要调用的 select 映射的全限定类名和方法
column :填写我们要传递给 select 映射的参数
-->
<association property="user"
javaType="user"
column="uid"
select="com.zy.dao.UserMapper.findByUserId">
</association>
</resultMap>
<select id="findAll" resultMap="accountMap">
select * from account;
</select>
</mapper>
用户持久层接口和映射文件:
public interface UserMapper {
/***
* @Description 根据id查询用户信息
* @Param: [uid]
* @return: com.zy.domin.User
*/
User findByUserId(Integer uid);
}
<?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="com.zy.dao.UserMapper">
<select id="findByUserId" parameterType="int" resultType="user">
select * from user where id=#{uid}
</select>
</mapper>
开启Mybatis延迟加载:
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
测试类:
public class AccountTest {
private InputStream in;
private SqlSessionFactoryBuilder builder;
private SqlSessionFactory factory;
private SqlSession session;
private AccountMapper accountMapper;
@Before//在test方法执行之前执行
public void befor() throws Exception {
//读取SqlMapConfig.xml配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建SqlSessionFactory工厂
builder = new SqlSessionFactoryBuilder();
factory = builder.build(in);
//使用工厂生产SqlSession
session = factory.openSession();
//使用SqlSession创建dao接口代理对象
accountMapper = session.getMapper(AccountMapper.class);
}
@After//在test方法执行之后执行
public void after() throws Exception {
session.commit();
session.close();
in.close();
}
@Test
public void testFindAll(){
List<Account> accounts = accountMapper.findAll();
for (Account account:accounts){
System.out.println(account);
System.out.println(account.getUser());
}
}
}
使用 collection 实现延迟加载
需求:加载用户信息,查询该用户下的账户信息
实体类User和Account:
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accounts;
//省略了getXXX(),setXXX(),toString()方法
}
public class Account {
private String id;
private String uid;
private Double money;
//省略了getXXX(),setXXX(),toString()方法
}
用户持久层和账户持久层接口方法:
public interface UserMapper {
/***
* @Description 查询所有用户
* @Param: []
* @return: java.util.List<com.zy.domin.User>
*/
List<User> findAll();
}
public interface AccountMapper {
/***
* @Description 根据id查询账户信息
* @Param: [accountId]
* @return: java.util.List<com.zy.domin.Account>
*/
List<Account> findByAccount(Integer accountId);
}
用户持久层映射:
<?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="com.zy.dao.UserMapper">
<resultMap id="userMap" type="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="birthday" property="birthday"></result>
<result column="sex" property="sex"></result>
<result column="address" property="address"></result>
<collection property="accounts"
ofType="account"
column="id"
select="com.zy.dao.AccountMapper.findByAccount">
</collection>
</resultMap>
<!--这里写具体的sql语句-->
<select id="findAll" resultMap="userMap">
select * from user;
</select>
</mapper>
账户持久层映射:
<?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="com.zy.dao.AccountMapper">
<!--查询账户-->
<select id="findByAccount" parameterType="int" resultType="account">
select * from account where uid=#{uid};
</select>
</mapper>
测试代码:
@Test
public void testFindAll(){
final List<User> users = userMapper.findAll();
for (User user:users){
System.out.println(user);
System.out.println(user.getAccounts());
}
}
加油吧