MyBatis高级映射(一对一、一对多、多对多、延迟加载)
MyBatis高级映射
一、入门准备:订单商品数据模型分析
1. 数据模型分析思路
a.每张表记录的数据内容
分模块对每张表记录的内容进行熟悉,相当 于你学习系统 需求(功能)的过程。
b.每张表重要的字段设置
非空字段、外键字段
c.数据库级别表与表之间的关系
外键关系
4、 d.表与表之间的业务关系
在分析表与表之间的业务关系时一定要建立 在某个业务意义基础上去分析。
2.数据模型分析
3. 数据库表之间有外键关系的业务关系
user和orders:
user---->orders:一个用户可以创建多个订单,一对多
orders--->user:一个订单只由一个用户创建,一对一
orders和orderdetail:
orders-àorderdetail:一个订单可以包括 多个订单明细,因为一个订单可以购买多个商品,每个商品的
购 买信息在orderdetail记录,一对多关系
orderdetail--> orders:一个订单明细只能包括在一个订单中,一对一
orderdetail和itesm:
orderdetail---》itesms:一个订单明细只对应一个商品信息,一对一
items--> orderdetail:一个商品可以包括在多个订单明细 ,一对多
4. 数据库表之间没有外键关系的业务关系
Orders和items:
这两张表没有直接的外键关系,通过业务及数据库的间接关系分析出它们是多对多的关系。
Ordersà orderdetail–>items:一个订单可以有多个订单明细,一个订单明细对应一个商品,所以一个订单对 应多个商品
Items-àorderdetailàorders:一个商品可以对应多个订单明细,一个订单明细对应一个订单,所以一个商品对应多个订单
User和items:
这两张表没有直接的外键关系,通过业务及数据库的间接关系分析出它们是多对多的关系。
Useràordersàorderdetailàitems:一个用户有多个订单,一个订单有多个订单明细、一个订单明细对应一个商品,所以一个用户对应多个商品
Itemsàorderdetailàordersàuser:一个商品对应多个订单明细,一个订单明细对应一个订单,一个订单对应一个用户,所以一个商品对应多个用户
二、一对一查询
准备工作:
创建java工程导入jar包
① SQL语句
SELECT
orders.*,
USER.username,
USER.sex,
USER.address
FROM
orders,
USER
WHERE orders.user_id = user.id
② 日志文件:log4j.properties
# Global logging configuration
#\u5728\u5f00\u53d1\u73af\u5883\u4e0b\u65e5\u5fd7\u7ea7\u522b\u8981\u8bbe\u7f6e\u6210DEBUG\uff0c\u751f\u4ea7\u73af\u5883\u8bbe\u7f6e\u6210info\u6216error
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
③ MyBatis配置文件: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>
<!-- 加载属性文件 -->
<properties resource="db.properties">
<!--properties中还可以配置一些属性名和属性值 -->
<!-- <property name="jdbc.driver" value=""/> -->
</properties>
<typeAliases>
<!-- 批量别名定义
指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写都可以)
-->
<package name="com.cjw.mybatis.po"/>
</typeAliases>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事务控制由mybatis-->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 加载 映射文件 -->
<mappers>
<!-- 批量加载mapper
指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载
遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
上边规范的前提是:使用的是mapper代理方法
-->
<package name="com.cjw.mybatis.mapper"/>
</mappers>
</configuration>
④ 数据库原型文件:db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
1. resultType实现一对一查询
1.1 创建PO类:Orders.java
public class Orders {
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
1.2 扩展PO类:OrdersCustomer.java
复杂查询时,单表对应的po类已不能满足输出结果集的映射。
所以要根据需求建立一个扩展类来作为resultType的类型。
/**
* 通过此类映射订单和用户查询的结果,让此类继承包括 字段较多的pojo类
* @author DreamWF
*
*/
public class OrdersCustomer extends Orders{
private String username;
private String sex;
1.3 建立Mapper代理接口:OrdersMapperCustomer.java
public interface OrdersMapperCustomer {
//查询订单关联查询用户
public List<OrdersCustomer> findOrdersUser() throws Exception;
}
1.4 编写映射文件:OrdersMapperCustomer.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">
<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离
注意:使用mapper代理方法开发,namespace有特殊重要的作用,namespace等于mapper接口地址
-->
<mapper namespace="com.cjw.mybatis.mapper.OrdersMapperCustomer">
<!-- 查询订单关联查询用户 -->
<select id="findOrdersUser" resultType="com.cjw.mybatis.po.OrdersCustomer">
SELECT
orders.*,
USER.username,
USER.sex,
USER.address
FROM
orders,
USER
WHERE orders.user_id = user.id
</select>
</mapper>
1.5 测试类:OrdersMapperCustomerTest.java
public class OrdersMapperCustomerTest {
private SqlSessionFactory sqlSessionFactory;
// 此方法是在执行testFindUserById之前执行
@Before
public void setUp() throws Exception {
// 创建sqlSessionFactory
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFinfOrdersUser() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建代理对象
OrdersMapperCustomer ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustomer.class);
// 调用maper的方法
List<OrdersCustomer> list = ordersMapperCustom.findOrdersUser();
System.out.println(list);
sqlSession.close();
}
}
2. resultMap实现一对一查询
思路:使用resultMap将查询结果中的订单信息映射到Orders对象中,在orders类中添加User属性,将关联查询出来的用户信息映射到orders对象中的user属性中。
2.1 创建PO类:Orders.java和User.java
public class Orders {
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
//用户信息
private User user;
public class User implements Serializable {
//属性名和数据库表的字段对应
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
//用户创建的订单列表
private List<Orders> ordersList;
2.2 扩展PO类:OrdersCustomer.java
/**
* 通过此类映射订单和用户查询的结果,让此类继承包括 字段较多的pojo类
* @author DreamWF
*
*/
public class OrdersCustomer extends Orders{
private String username;
private String sex;
2.3 建立Mapper代理接口:OrdersMapperCustomer.java
public interface OrdersMapperCustomer {
//查询订单关联查询用户信息,使用resultMap
public List<Orders> findOrdersUseResultMapper() throws Exception;
}
2.4 编写映射文件:OrdersMapperCustomer.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">
<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离
注意:使用mapper代理方法开发,namespace有特殊重要的作用,namespace等于mapper接口地址
-->
<mapper namespace="com.cjw.mybatis.mapper.OrdersMapperCustomer">
<!-- 订单查询关联用户的resultMap
将整个查询的结果映射到com.cjw.mybatis.po.Orders中
-->
<resultMap type="com.cjw.mybatis.po.Orders" id="OrdersUserResultMapper">
<!-- 配置映射的订单信息 -->
<!-- id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id
column:订单信息的唯 一标识 列
property:订单信息的唯 一标识 列所映射到Orders中哪个属性
-->
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 配置映射的关联的用户信息 -->
<!-- association:用于映射关联查询单个对象的信息
property:要将关联查询的用户信息映射到Orders中哪个属性
-->
<association property="user" javaType="com.cjw.mybatis.po.User">
<!-- id:关联查询用户的唯 一标识
column:指定唯 一标识用户信息的列
javaType:映射到user的哪个属性
-->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
<!-- 查询订单关联查询用户 使用resultMap -->
<select id="findOrdersUseResultMapper" resultMap="OrdersUserResultMapper">
SELECT
orders.*,
USER.username,
USER.sex,
USER.address
FROM
orders,
USER
WHERE orders.user_id = user.id
</select>
</mapper>
2.5 测试类:OrdersMapperCustomerTest.java
public class OrdersMapperCustomerTest {
private SqlSessionFactory sqlSessionFactory;
// 此方法是在执行testFindUserById之前执行
@Before
public void setUp() throws Exception {
// 创建sqlSessionFactory
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFinfOrdersUserResultMap() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建代理对象
OrdersMapperCustomer ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustomer.class);
// 调用maper的方法
List<Orders> list=ordersMapperCustom.findOrdersUseResultMapper();
System.out.println(list);
sqlSession.close();
}
}
3. 一对一查询:resultType和resultMap的比较总结
resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。
如果没有查询结果的特殊要求建议使用resultType。
resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的对象属性中。
resultMap可以实现延迟加载,resultType无法实现延迟加载。
三、一对多查询(resultMap)
需求:查询订单及订单明细的信息。
确定主查询表:订单表
确定关联查询表:订单明细表
在一对一查询基础上添加订单明细表关联即可。、
问题分析:
使用resultType将上边的查询结果映射到pojo中,订单信息将会重复。
要求:
对orders映射不能出现重复记录。
在orders.java类中添加List<Orderdetail> detailList属性。
最终会将订单信息映射到orders中,订单所对应的订单明细映射到orders中的detailList属性中。
映射成的orders记录数为两条(orders信息不重复)
每个orders中的detailList属性存储了该订单所对应的订单明细集合。
1. SQL语句
Select
Orders.id,
Orders.user_id,
orders.number,
orders.createtime,
orders.note,
user.username,
user.address,
orderdetail.id detail_id,
orderdetail.items_id,
orderdetail.items_num
from orders,user,orderdetail
where orders.user_id = user.id
and orders.id = orderdetail.orders_id
2. 创建PO类
public class Orders {
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
//用户信息
private User user;
//订单明细
private List<Orderdetail> orderDetails;
public class Items {
private Integer id;
private String name;
private Float price;
private String pic;
private Date createtime;
private String detail;
private Integer id;
private Integer ordersId;
private Integer itemsId;
private Integer itemsNum;
//明细对应的商品信息
private Items items;
public class User implements Serializable {
//属性名和数据库表的字段对应
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
/**
* 通过此类映射订单和用户查询的结果,让此类继承包括 字段较多的pojo类
* @author DreamWF
*
*/
public class OrdersCustomer extends Orders{
private String username;
private String sex;
3. 建立Mapper代理接口:OrdersMapperCustomer.java
public interface OrdersMapperCustomer {
//查询订单关联查询用户信息,订单明细
public List<Orders> findOrdersAndOrderDetailResultMap() throws Exception;
}
4. 映射文件:OrdersMapperCustomer.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.cjw.mybatis.mapper.OrdersMapperCustomer">
<!-- 查询订单及订单明细的resultMap -->
<resultMap type="com.cjw.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap">
<!-- 配置映射的关联的订单信息
id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id
column:订单信息的唯 一标识 列
property:订单信息的唯 一标识 列所映射到Orders中哪个属性
-->
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 配置映射的关联的用户信息
association:用于映射关联查询单个对象的信息
property:要将关联查询的用户信息映射到Orders中哪个属性
-->
<association property="user" javaType="com.cjw.mybatis.po.User">
<!-- id:关联查询用户的唯 一标识
column:指定唯 一标识用户信息的列
javaType:映射到user的哪个属性
-->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
<!-- 订单明细信息
一个订单关联查询出了多条明细,要使用collection进行映射
collection:对关联查询到多条记录映射到集合对象中
property:将关联查询到多条记录映射到com.cjw.mybatis.po.Orders哪个属性
ofType:指定映射到list集合属性中pojo的类型
-->
<collection property="orderdetails" ofType="com.cjw.mybatis.po.Orderdetail">
<!-- 订单明细唯一标识 -->
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
</collection>
</resultMap>
<!-- 查询订单关联查询用户 及 订单明细 使用ResultMap-->
<select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">
SELECT
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id
FROM
orders,
USER,
orderdetail
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id
</select>
</mapper>
5. 测试类
public class OrdersMapperCustomerTest {
private SqlSessionFactory sqlSessionFactory;
// 此方法是在执行testFindUserById之前执行
@Before
public void setUp() throws Exception {
// 创建sqlSessionFactory
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFinfOrdersUserResultMap() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建代理对象
OrdersMapperCustomer ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustomer.class);
// 调用maper的方法
List<Orders> list=ordersMapperCustom.findOrdersAndOrderDetailResultMap();
System.out.println(list);
sqlSession.close();
}
}
四、多对多查询
1.SQL语句
SELECT
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id,
items.name items_name,
items.detail items_detail,
items.price items_price
FROM
orders,
USER,
orderdetail,
items
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id
2. PO类
和上面一样
3. 建立Mapper代理接口:OrdersMapperCustomer.java
public interface OrdersMapperCustomer {
//查询用户购买商品信息
public List<User> findUserAndItemsResultMap() throws Exception;
}
4. 映射文件:OrdersMapperCustomer.xml
将用户信息映射到user中。
在user类中添加订单列表属性List<Orders> orderslist,将用户创建的订单映射到orderslist
在Orders中添加订单明细列表属性List<OrderDetail>orderdetials,将订单的明细映射到orderdetials
在OrderDetail中添加Items属性,将订单明细所对应的商品映射到Items
<?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.cjw.mybatis.mapper.OrdersMapperCustomer">
<!-- 查询用户和购买的商品 -->
<resultMap type="com.cjw.mybatis.po.User" id="UserAndItemsResultMap">
<!--用户信息 -->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<!-- 订单信息:一个用户对应多个订单,使用collection映射-->
<collection property="orderList" ofType="com.cjw.mybatis.po.Orders">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 订单明细: 一个订单包括 多个明细-->
<collection property="orderDetails" ofType="com.cjw.mybatis.po.Orderdetail">
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
<!-- 商品信息:一个订单明细对应一个商品 -->
<association property="items" javaType="com.cjw.mybatis.po.Items">
<id column="items_id" property="id"/>
<result column="items_name" property="name"/>
<result column="items_detail" property="detail"/>
<result column="items_price" property="price"/>
</association>
</collection>
</collection>
</resultMap>
<!-- 查询订单关联查询用户 及 购买的视频信息 使用ResultMap-->
<select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap">
SELECT
orders.*,
USER.username,
USER.sex,
USER.address,
orderdetail.id orderdetail_id,
orderdetail.items_id,
orderdetail.items_num,
orderdetail.orders_id,
items.name items_name,
items.detail items_detail,
items.price items_price
FROM
orders,
USER,
orderdetail,
items
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id
</select>
</mapper>
5. 测试类
public class OrdersMapperCustomerTest {
private SqlSessionFactory sqlSessionFactory;
// 此方法是在执行testFindUserById之前执行
@Before
public void setUp() throws Exception {
// 创建sqlSessionFactory
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFinfOrdersUserResultMap() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建代理对象
OrdersMapperCustomer ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustomer.class);
// 调用maper的方法
List<User> list=ordersMapperCustom.findUserAndItemsResultMap();
System.out.println(list);
sqlSession.close();
}
}
6. 多对多查询总结
将查询用户购买的商品信息明细清单,(用户名、用户地址、购买商品名称、购买商品时间、购买商品数量)
针对上边的需求就使用resultType将查询到的记录映射到一个扩展的pojo中,很简单实现明细清单的功能。
一对多是多对多的特例,如下需求:
查询用户购买的商品信息,用户和商品的关系是多对多关系。
需求1:
查询字段:用户账号、用户名称、用户性别、商品名称、商品价格(最常见)
企业开发中常见明细列表,用户购买商品明细列表,
使用resultType将上边查询列映射到pojo输出。
需求2:
查询字段:用户账号、用户名称、购买商品数量、商品明细(鼠标移上显示明细)
使用resultMap将用户购买的商品明细列表映射到user对象中。
总结:
使用resultMap是针对那些对查询结果映射有特殊要求的功能,,比如特殊要求映射成list中包括多个list。
8. ResultMap总结
resultType:
作用:
将查询结果按照sql列名pojo属性名一致性映射到pojo中。
场合:
常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。
resultMap:
使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。
association:
作用:
将关联查询信息映射到一个pojo对象中。
场合:
为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。
使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。
collection:
作用:
将关联查询信息映射到一个list集合中。
场合:
为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。
如果使用resultType无法将查询结果映射到list集合中。
五、延迟加载(association)
什么是延迟加载
resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。
需求:
如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。
延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。
Mybatis默认是不开启延迟加载功能的,我们需要手动开启。
需要在SqlMapConfig.xml文件中,在<settings>标签中开启延迟加载功能。
lazyLoadingEnabled、aggressiveLazyLoading
1. 在SqlMapConfig.xml文件开启延迟加载
<!-- 全局配置参数,需要时再设置 -->
<settings>
<!-- 打开延迟加载 的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载即按需要加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
2. 测试类
public class OrdersMapperCustomerTest {
private SqlSessionFactory sqlSessionFactory;
// 此方法是在执行testFindUserById之前执行
@Before
public void setUp() throws Exception {
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindOrdersUserLazyLoading() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建代理对象
OrdersMapperCustomer ordersMapperCustom = sqlSession
.getMapper(OrdersMapperCustomer.class);
// 调用maper的方法
List<Orders> list=ordersMapperCustom.findOrdersUserLazyLoading();
//遍历上边的订单列表
for(Orders orders:list) {
//执行getUser()去查询用户信息,这里实现按需加载
User user=orders.getUser();
System.out.println(user);
}
sqlSession.close();
}
}
3.延迟加载问题思考:
不使用mybatis提供的association及collection中的延迟加载功能,如何实现延迟加载??
实现方法如下:
定义两个mapper方法:
1、查询订单列表
2、根据用户id查询用户信息
实现思路:
先去查询第一个mapper方法,获取订单信息列表
在程序中(service),按需去调用第二个mapper方法去查询用户信息。
总之:
使用延迟加载方法,先去查询简单的sql(最好单表,也可以关联查询),再去按需要加载关联查询的其它信息。
推荐阅读
-
mybatis 一对一、一对多和多对多查询实例代码
-
MyBatis从入门到精通(十一):MyBatis高级结果映射之一对多映射
-
Mybatis使用注解实现一对一复杂关系映射及延迟加载
-
Mybatis使用注解实现一对一复杂关系映射及延迟加载
-
Mybatis04—注解开发实现CRUD以及实现一对一、一对多及多对多复杂关系映射
-
Mybatis常用的注解开发CRUD&&复杂关系映射(一对一,一对多)&&mybatis 基于注解的二级缓存
-
Mybatis—— 使用注解实现一对一复杂关系映射及延迟加载
-
Mybatis使用注解实现一对多复杂关系映射
-
MyBatis高级映射(一对一、一对多、多对多、延迟加载)
-
mybatis延迟加载一对一和一对多