欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyBatis高级映射(一对一、一对多、多对多、延迟加载)

程序员文章站 2022-07-12 22:33:04
...

MyBatis高级映射

一、入门准备:订单商品数据模型分析

MyBatis高级映射(一对一、一对多、多对多、延迟加载)

1. 数据模型分析思路

    a.每张表记录的数据内容

         分模块对每张表记录的内容进行熟悉,相当 于你学习系统 需求(功能)的过程。

    b.每张表重要的字段设置

         非空字段、外键字段

    c.数据库级别表与表之间的关系

         外键关系

4、    d.表与表之间的业务关系

         在分析表与表之间的业务关系时一定要建立 在某个业务意义基础上去分析

2.数据模型分析

    MyBatis高级映射(一对一、一对多、多对多、延迟加载)

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包

MyBatis高级映射(一对一、一对多、多对多、延迟加载)

① 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();
}		
}

MyBatis高级映射(一对一、一对多、多对多、延迟加载)

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();
}						
}
MyBatis高级映射(一对一、一对多、多对多、延迟加载)

3. 一对一查询:resultType和resultMap的比较总结

resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。

如果没有查询结果的特殊要求建议使用resultType。

resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的对象属性中。

                                    resultMap可以实现延迟加载,resultType无法实现延迟加载。

三、一对多查询(resultMap)

需求:查询订单及订单明细的信息。

确定主查询表:订单表

确定关联查询表:订单明细表

在一对一查询基础上添加订单明细表关联即可。、

问题分析:

使用resultType将上边的查询结果映射到pojo中,订单信息将会重复。

MyBatis高级映射(一对一、一对多、多对多、延迟加载)

要求:

orders映射不能出现重复记录。

在orders.java类中添加List<Orderdetail> detailList属性。

最终会将订单信息映射到orders中,订单所对应的订单明细映射到orders中的detailList属性中。

MyBatis高级映射(一对一、一对多、多对多、延迟加载)

映射成的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

MyBatis高级映射(一对一、一对多、多对多、延迟加载)

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(最好单表,也可以关联查询),再去按需要加载关联查询的其它信息。