目录
需求
关联查询
:查询购买某些商品的用户信息 ;
主表
:订单表 ;
关联表
:用户表 ;
一对一映射(使用 resultType)
sql
语句SELECT `order`.* ,`user`.`name` ,`user`.sex FROM `order`,`user` WHERE `user`.id = `order`.user_id ;
创建
pojo
对象将上面查询的结果列的所有信息,封装到该
pojo
中 ;这与复杂查询
创建pojo
对象不一样,复杂查询
创建pojo
对象是为了,封装查询条件 ;这里我们是为了 封装查询结果 ;从查询的列中,可以看出结果来自
user
、order
表 ,我们在设计 pojo 对象的时候,选择让其继承包含列字段段多的类,这样,我们可以在pojo
中少写一些属性;这里我选择继承字段多的
user
类 ;/** *User增强类,封装最后的查询结果 *@author An */ public class UserCustomerMapper extends User { // 将 order 类的字段添加进来 private int order_id ; private int user_id ; public int getOrder_id() { return order_id; } public void setOrder_id(int order_id) { this.order_id = order_id; } public int getUser_id() { return user_id; } public void setUser_id(int user_id) { this.user_id = user_id; } }
创建
映射关系
文件<?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="xin.ijava.dao.UserCustomerMapper"> <select id="findOrderUsers" resultType="xin.ijava.dao.UserCustomer"> SELECT `order`.* ,`user`.`name` ,`user`.sex FROM `order`,`user` WHERE `user`.id = `order`.user_id </select> </mapper>
创建同名的接口
@SuppressWarnings("unused") public interface UserCustomerMapper { public List<UserCustomer> findOrderUsers() throws Exception ; }
测试结果
可以看到,我们已经将结果中列的数据,都封装到 UserCustomer
类中了 ;
一对一映射(使用 resultMap)
我们发现前面我们在创建 pojo
对象,是选择继承包含结果集中列多的类,然后在 pojo
类添加新的属性 ;
我们发现,即使这样做,我们还是很反感,特别是不同表之间有重名的列,生成 get set
方法就会出问题, 为什么就不能直接添加一个包含那些属性的对象进去呢?
答案是可以的,使用 resultMap
;
创建 pojo 对象 ;
public class UserOrders extends User { // 直接传进来 order 对象 private Order order ; public Order getOrder() { return order; } public void setOrder(Order order) { this.order = order; } }
创建
resultMap
<!--type :最后将结果映射到的对象类--> <resultMap id="findOrders" type="xin.ijava.dao.UserOrders"> <!--主对象,也就是被继承对象--> <id column="id" property="id"></id> <result column="name" property="name"/> <result column="sex" property="sex"/> <!--关联对象,也就是传进来的对象--> <!-- property : 关联对象在主对象中的引用名--> <association property="order" javaType="xin.ijava.pojo.Order"> <id column="order_id" property="order_id"/> <result column="user_id" property="user_id"/> </association> </resultMap>
配置
sql
<sql id="query_Orders_users"> SELECT `order`.* ,`user`.`name` ,`user`.sex FROM `order`,`user` WHERE `user`.id = `order`.user_id </sql> <select id="findOrdersUserResultMap" resultMap="findOrders"> <include refid="query_Orders_users"/> </select>
创建接口方法
public List<UserOrders> findOrdersUserResultMap() throws Exception ;
测试结果
可以看出来,结果也被我们封装进去了 ;
小结
可以看出,resultType
适用于将结果集中列的结果映射到对象的一次映射到对应的属性上(一对一
) ;
而resultMap
则是用于,将结果中多列的内容,映射到一个对象中(一对多
) ;
resultType
无法实现延迟加载,resultMap
可以实现延迟加载 ;
需求
查询 订单
及 订单明细
一对多映射
sql
语句查询SELECT `order`.order_id, `user`.id , `user`.`name` , orderdetail.id orderDetailsId, orderdetail.number FROM `order`,`user`, orderdetail,items WHERE `user`.id = `order`.user_id AND orderdetail.item_id = items.id AND `order`.order_id = orderdetail.order_id ;
查询结果:
备注:再进行多表查询的时候,分清主表,关联表(主表没有直接关联,就通过一系列的中间表进行关联) where 后面写主键关系,按照逻辑写下去;
创建
pojo
对象首先讲下 覆盖现象:
mybatis
在往对象中,映射结果的时候,一条记录一条记录的映射 ;这里说下,我们在映射文件中规定主对象的
id
是user
的id
,那么,mybatis
就会根据user
的id
,来分辨是不是同一个对象 ,以便将信息映射到对象中;比如,第一条记录,创建出
pojo
对象了,然后订单对象
被赋值了,然后映射第二条记录,mybatis
会去检查该条记录中的user
的id
,看是不是新对象,如果是,则创建新的pojo
对象,如果是已经创建过的对象,则将结果映射到之前的pojo
对象中,这样,假如pojo
字段,设定的不正确,就会产生覆盖
;从结果中我们看到,
张三
拥有多个不同的订单号
,因此,在pojo
中,我们应该用集合存储订单对象
,来避免覆盖 ;订单明细
,也是一个对象,一个订单会产生多条订单明细记录,因为一个订单会购买多种不同的产品嘛 ,因此,也用集合存储;public class UserOrders extends User { private List<OrderDetails> orderDetails ; private List<Order> orders ; public List<OrderDetails> getOrderDetails() { return orderDetails; } public void setOrderDetails(List<OrderDetails> orderDetails) { this.orderDetails = orderDetails; } public List<Order> getOrders() { return orders; } public void setOrders(List<Order> orders) { this.orders = orders; } }
创建
resultMap
将结果信息封装到集合中,使用
collection
;<!--封装订单信息到 UsersOrder 中 --> <!--extends 继承其他 map --> <resultMap id="findOrdersAndOrderDetailsMap" type="xin.ijava.dao.UserOrders" extends="findOrders"> <!--封装信息到 集合--> <!--ofType 封装对象的类型--> <!--property 封装对象的引用名字--> <collection property="orderDetails" ofType="xin.ijava.pojo.OrderDetails"> <result column="orderDetailsId" property="order_id"/> <result column="number" property="number"/> </collection> </resultMap>
配置
sql
<select id="findOrdersAndOrderDetails" resultMap="findOrdersAndOrderDetailsMap"> SELECT `order`.order_id, `user`.id , `user`.`name` , orderdetail.id orderDetailsId, orderdetail.number FROM `order`,`user`, orderdetail,items WHERE `user`.id = `order`.user_id AND orderdetail.item_id = items.id AND `order`.order_id = orderdetail.order_id </select>
编写接口方法
public List<UserOrders> findOrdersAndOrderDetails() throws Exception ;
测试结果
我们可以发现,在数据库查询出来的 4
条记录,在这里被封装成 2
个对象了 ,完全符合我们的期望,因为,我们创建的 pojo
对象,是按照用户为主体的,上面的 4
条记录,是 2
个用户产生的,因此,最后也被封装到 2
个对象中 ;
小结
resultMap
主要是根据我们告诉它的 id
,也就是对象的唯一标识符号,来确定是不是同一个对象的 ;
需求
查询所有 用户
购买的具体商品
,将它们封装到一个集合中 ;
如果是:查询某一个具体 用户
购买的具体商品
,将它们封装到一个集合中,这样打印账单的活,则没有必要使用 resultMap
了 ;
主表: user
关联表 :items
多对多映射
sql
语句SELECT `user`.id user_id, `user`.`name` user_name, `user`.address user_address, `order`.order_id , `order`.createtime create_time, items.id item_id, items.`name` item_name, orderdetail.number item_number FROM `user`,`order`,orderdetail,items WHERE `user`.id = `order`.user_id AND `order`.order_id = orderdetail.order_id AND items.id = orderdetail.item_id ;
创建
resultMap
<resultMap id="findUserAndItemsMap" type="xin.ijava.pojo.UserItems"> <id column="user_id" property="id"/> <result column="user_name" property="name"/> <result column="user_address" property="address"/> <collection property="orders" ofType="xin.ijava.pojo.Order"> <id column="order_id" property="order_id"/> <result column="create_time" property="createTime"/> <!--嵌套 collection --> <collection property="orderDetails" ofType="xin.ijava.pojo.OrderDetails"> <id column="order_id" property="order_id"/> <result column="item_number" property="number"/> <result column="item_number" property="number"/> <!--关联对象--> <association property="item" javaType="xin.ijava.pojo.Items"> <id column="item_id" property="id"/> <result column="item_name" property="name"/> </association> </collection> </collection> </resultMap>
跟俄罗斯套娃一样,一层套一层,我们使用
collection
、association
完成数据的嵌套 ;配置
sql
<select id="findUserAndItems" resultMap="findUserAndItemsMap"> SELECT `user`.id user_id, `user`.`name` user_name, `user`.address user_address, `order`.order_id , `order`.createtime create_time, items.id item_id, items.`name` item_name, orderdetail.number item_number FROM `user`,`order`,orderdetail,items WHERE `user`.id = `order`.user_id AND `order`.order_id = orderdetail.order_id AND items.id = orderdetail.item_id </select>
编写接口方法
public List<UserItems> findUserAndItems() throws Exception ;
测试结果
总结
选择 resultType
还是选择 resultMap
看需求 ;
比如上面实现的商品明细,假如有特殊要求,将它们映射到一个集合中,那么则选用 resultMap
;如果只是想打印账单那样,那么使用 resultType
;主要是看最后对映射结果的要求 ;