延迟加载:也称懒加载,就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。可以提高数据库性能。Mybatis在进行多表操作时,使用resultMap来实现,其中通过association实现一对一和多对一映射、通过collection实现一对多和多对多映射。association、collection都具备延迟加载功能,本文演示collection的延迟加载。
1.准备工作
创建maven、添加jar包坐标、MyBatis主配置文件、log4j的配置文件等准备工作可以参考:IDEA中Maven工程的MyBatis快速入门
在MyBatis主配置文件中开启延时加载,需要在<configuration>标签中增加:
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
2.编写实体类
假如数据库有user表和account表,sql语句为:
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL auto_increment, `username` varchar(32) NOT NULL COMMENT '用户名称', `sex` char(1) default NULL COMMENT '性别', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `user`(`id`,`username`,`sex`) values (41,'老王','男'),(42,'小二王','女'),(43,'小三王','女'); DROP TABLE IF EXISTS `account`; CREATE TABLE `account` ( `id` int(11) NOT NULL COMMENT '编号', `uid` int(11) default NULL COMMENT '用户编号', `money` double default NULL COMMENT '金额', PRIMARY KEY (`id`), CONSTRAINT `FK_Reference_1` FOREIGN KEY (`uid`) REFERENCES `user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `account`(`id`,`uid`,`money`) values (1,41,1000),(2,42,1000),(3,42,2000);
在src/main/java下创建User类和Account类,实现Serializable接口,且要求与数据表有对应的属性名,代码可参考:IDEA中Maven工程的MyBatis快速入门。
通过面向对象的(has a)关系得知,可以在User类中加入一个Account类的属性来代表这个用户有哪些账户。即需要在User.class中添加如下代码:
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
3.编写实体类的持久层映射接口
这里对应的User类持久层映射接口取名UserMapper,放在src/main/java下,代码如下:
package com.gqzzw.mapper;
import com.gqzzw.domain.QueryVo;
import com.gqzzw.domain.User;
import java.util.List;
public interface UserMapper {
//一对多查询
List<User> findAll();
}
Account类持久层映射接口取名AccountMapper,放在src/main/java下,代码如下:
package com.gqzzw.mapper;
import com.gqzzw.domain.Account;
import java.util.List;
public interface AccountMapper {
//根据uid查询账户
List<Account> findByUid(int uid);
}
4.编写映射接口的配置文件
放在src/main/resources下,必须与久层接口包路径和文件名相同,即:com.gqzzw.mapper.UserMapper.xml
<?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.gqzzw.mapper.UserMapper">
<!-- 一对多查询 -->
<resultMap id="user_account" type="com.gqzzw.domain.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<!-- select:映射接口对应的方法 column:传递的参数 -->
<collection property="accounts" ofType="com.gqzzw.domain.Account"
select="com.gqzzw.mapper.AccountMapper.findByUid" column="id">
</collection>
</resultMap>
<select id="findAll" resultMap="user_account">
SELECT * from user;
</select>
</mapper>
放在src/main/resources下,必须与久层接口包路径和文件名相同,即:com.gqzzw.mapper.AccountMapper.xml
<?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.gqzzw.mapper.AccountMapper">
<!-- 根据Uid查询账户 -->
<select id="findByUid" resultType="com.gqzzw.domain.Account" parameterType="int">
select * from account where uid=#{uid}
</select>
</mapper>
5.编写测试类
放在src/test/java下,编写测试类,内容如下:
package com.gqzzw.mapper;
import com.gqzzw.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UserMapperTset {
private InputStream in;
private SqlSession sqlSession;
private UserMapper userMapper;
@Before
public void init() throws IOException {
//读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建SqlSessionFactory的构建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//使用构建者创建工厂对象SqlSessionFactory
SqlSessionFactory factory = builder.build(in);
//使用SqlSessionFactory产SqlSession对象生
sqlSession = factory.openSession();
//产SqlSession对象时可以传true代表自动提交事务
//sqlSession = factory.openSession(true);
//使用SqlSession创建映射接口的代理对象
userMapper = sqlSession.getMapper(UserMapper.class);
}
@After
public void destroy() throws IOException {
//提交事务,释放资源
sqlSession.commit();
sqlSession.close();
in.close();
}
@Test
//一对多查询
public void findAll(){
List<User> users = userMapper.findAll();
}
}
转载请注明:运维博客 » Mybatis延迟加载之:一对多(使用Collection实现)