>以订单商品数据模型为例子:
存在以下四张表,用户表user,用户订单表orders,订单明细表orderdetail,商品表items。四张表之间的关系如下图所示:
下面给出四张表结构的详细定义,出于演示,每张表仅定义少量字段:
用户表:user
列名 |
数据类型 |
是否为空 |
主键 |
外键 |
注释 |
user_id |
varchar2(40) |
否 |
是 |
|
用户主键 |
user_name |
varchar2(40) |
否 |
|
|
用户名 |
user_pass |
varchar2(20) |
否 |
|
|
用户密码 |
cname |
varchar2(20) |
否 |
|
|
昵称 |
user_img |
varchar2(100) |
是 |
|
|
用户头像 |
订单表:orders
列名 |
数据类型 |
是否为空 |
主键 |
外键 |
注释 |
order_id |
varchar2(40) |
否 |
是 |
|
订单主键 |
user_id |
varchar2(40) |
否 |
|
是 |
用户外键 |
numer |
varchar2(20) |
否 |
|
|
订单号 |
order_date |
date |
否 |
|
|
订单日期 |
payment |
char(1) |
否 |
|
|
是否付款 |
订单明细表:orderdetail
列名 |
数据类型 |
是否为空 |
主键 |
外键 |
注释 |
detail_id |
varchar2(40) |
否 |
是 |
|
订单明细主键 |
order_num |
varchar2(40) |
否 |
|
是 |
订单号 |
item_id |
varchar2(20) |
否 |
|
是 |
商品外键 |
buy_num |
int |
否 |
|
|
购买数量 |
商品表:items
列名 |
数据类型 |
是否为空 |
主键 |
外键 |
注释 |
item_id |
varchar2(40) |
否 |
是 |
|
商品主键 |
item_name |
varchar2(40) |
否 |
|
|
商品名称 |
price |
double |
否 |
|
|
商品价格 |
description |
varchar2(50) |
否 |
|
|
商品描述 |
item_img |
varchar2(100) |
是 |
|
|
用户图片 |
> 一对一关联查询
使用mybatis实现一对一关联查询,操作内容为:订单信息查询,并关联查询创建订单的用户的信息。对于返回查询结果信息可以由resultType或resultMap实现。
resultType实现:
去写一个拓展bean作为输出映射:写一个UserBean,继承User表,将Order表中的字段再写一遍;
缺陷:Order表中的字段写了两遍,做了重复性的工作;
resultMap实现:
上例中使用resultType的实现,再进行关联查询时,对于关联表中的字段只取出几列而已,那么在开发时可以选择一个较多的列POJO对象为基础进行扩展,例如A表与B表进行关联查询,A表查询所有列,B表查询几列,那就需要以A表对应的POJO对象为基础进行扩展。即:class QueryABean extends A 。
但是如果在进行关联查询时,几乎两个表中所有的列都被当做查询结果,那么在扩展类中再定义另外一个表中所有的列,显然不是很合适了,这种情况下最常见的方式,就是把另外一个表所对应的POJO对象组合进来,这时使用mybatis进行输出映射就只能使用resultMap元素了,这就是resultMap的高级使用。
(1)定义Order类、组合类:
package com.langsin.pojo;
public class Orders {
private Integer orderId;
private Integer userId;
private String orderNum;
private String orderDate;
private String payment;
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getOrderNum() {
return orderNum;
}
public void setOrderNum(String orderNum) {
this.orderNum = orderNum;
}
public String getOrderDate() {
return orderDate;
}
public void setOrderDate(String orderDate) {
this.orderDate = orderDate;
}
public String getPayment() {
return payment;
}
public void setPayment(String payment) {
this.payment = payment;
}
}
这里不采用User中所有的字段再写一遍,而是采用组合的方式将User对象加进来;
package com.langsin.pojo;
public class OrderBean extends Orders {
private User user=null;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
(2)Mapper配置文件:
注:在之前将User中所有的字段再写一遍的情况下,我们使用resultMap时,只需要将表中的列名与pojo中不对应的部分关联起来即可,名字相同的会自动映射。
但在组合的方式将User对象加进来的情况,所有的列都要与pojo进行关联,即使名称一致。
(3)Mapper接口
public interface UserMapper {
public OrderBean queryOrderUser(Integer orderId) throws Exception;
}
(4)测试类
@Test
public void queryOrderUser() throws Exception{
Integer orderId=1111;
UserMapper mapper=session.getMapper(UserMapper.class);
OrderBean orderuser = mapper.queryOrderUser(orderId);
System.out.println(orderuser);
session.close();
}
>一对多关联查询
使用mybatis实现一对多关联查询,操作内容为:查询订单表并关联查询订单明细表。在没有使用框架时,针对于这种情况,一般我们都是service层进行业务处理,首先组装一个订单扩展类,在订单扩展类中定义一个List集合来存放此订单所对应的订单明细。即:先调用dao层查询订单表,然后再根据订单表与订单明细表的主外键关联字段,再调用订单明细的dao再查询订单明细,最终完成数据组装。
通过mybatis框架collection集合,可以很轻松的完成此项工作。
(1)定义订单明细、订单明细组合类
package com.langsin.pojo;
public class OrderDetail {
private Integer detailId;
private String orderNum;
private String itemId;
private String buyNum;
private Integer orderId;
public Integer getDetailId() {
return detailId;
}
public void setDetailId(Integer detailId) {
this.detailId = detailId;
}
public String getOrderNum() {
return orderNum;
}
public void setOrderNum(String orderNum) {
this.orderNum = orderNum;
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getBuyNum() {
return buyNum;
}
public void setBuyNum(String buyNum) {
this.buyNum = buyNum;
}
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("OrderDetail [detailId=").append(detailId).append(", orderNum=").append(orderNum)
.append(", itemId=").append(itemId).append(", buyNum=").append(buyNum).append(", orderId=")
.append(orderId).append("]");
return builder.toString();
}
}
订单明细与商品是一对一的关系,组合单个对象:
package com.langsin.pojo;
public class DetailBean extends OrderDetail {
Items item = null;
public Items getItem() {
return item;
}
public void setItem(Items item) {
this.item = item;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("DetailBean [item=").append(item).append(", toString()=").append(super.toString()).append("]");
return builder.toString();
}
}
订单与订单明细组合类中由于是存放一对多的查询结果,使用集合:
package com.langsin.pojo;
import java.util.List;
public class OrderList extends Orders {
private List detailList=null;
public List getDetailList() {
return detailList;
}
public void setDetailList(List detailList) {
this.detailList = detailList;
}
}
(2)Mapper配置文件(collection与association可以嵌套)
(3)Mapper接口
public interface UserMapper {
public OrderList queryOrderList(Integer orderId)throws Exception;
}
(4)测试类
@Test
public void queryOrderList() throws Exception{
Integer orderId=1111;
UserMapper mapper=session.getMapper(UserMapper.class);
OrderList orderList = mapper.queryOrderList(orderId);
System.out.println(orderList);
List detailList = orderList.getDetailList();
for (DetailBean detailBean : detailList) {
System.out.println(detailBean);
}
session.close();
}
>多对多关联查询(实质上还是association和collocation的相互嵌套)
(1)定义pojo,pojo组合类
package com.langsin.pojo;
import java.util.List;
public class UserOrderList extends User {
/**
* 已经继承User,包含所有用户信息
* 还需要订单的集合,这个订单元素本身(也就是泛型类型)又应该是包含订单本身和对应明细和商品的集合
*/
List orderlist = null;
public List getOrderlist() {
return orderlist;
}
public void setOrderlist(List orderlist) {
this.orderlist = orderlist;
}
}
(2)Mapper配置
(3)Mapper接口
public interface UserMapper {
public UserOrderList queryUserOrderDetailItem(Integer orderId)throws Exception;
}
(4)测试类
@Test
public void queryUserOrderDetailItem() throws Exception{
Integer userId=2;
UserMapper mapper=session.getMapper(UserMapper.class);
UserOrderList userOrderList = mapper.queryUserOrderDetailItem(userId);
System.out.println("---用户信息---");
System.out.println(userOrderList);
System.out.println("-----------------------------------");
List orderList = userOrderList.getOrderlist();
for (OrderList orderlist : orderList) {
System.out.println("订单信息:");
System.out.println(orderlist);
List detailList = orderlist.getDetailList();
for (DetailBean detailBean : detailList) {
System.out.println("明细和商品:");
System.out.println(detailBean);
}
System.out.println("-----------------------------------");
}
session.close();
}
测试debug结果:
---用户信息---
User [userId=2, userName=lisi, password=123789, roleCode=admin, cname=weiwei, telphone=17864195335, address=山东济南, isLogin=0]
-----------------------------------
订单信息:
Orders [orderId=1111, userId=2, orderNum=21111, orderDate=1996-12-12, payment=y]
明细和商品:
DetailBean [item=Items [itemId=good001, itemName=iPad, price=10000.0], toString()=OrderDetail [detailId=1, orderNum=21111, itemId=good001, buyNum=1, orderId=1111]]
明细和商品:
DetailBean [item=Items [itemId=good002, itemName=iPhone, price=12000.0], toString()=OrderDetail [detailId=2, orderNum=21111, itemId=good002, buyNum=2, orderId=1111]]
-----------------------------------
订单信息:
Orders [orderId=2222, userId=2, orderNum=22222, orderDate=1996-12-13, payment=y]
明细和商品:
DetailBean [item=Items [itemId=good003, itemName=Huawei, price=5000.0], toString()=OrderDetail [detailId=3, orderNum=22222, itemId=good003, buyNum=3, orderId=2222]]
-----------------------------------
>resultType与resultMap总结
1、对于单表的查询基本上都用resultType实现即可。
2、对于一对一的联合查询,如果作为查询结果的第二张的表字段不多,定义一个扩展类,然后使用resultType实现即可。
3、如果一对一的联合查询,两个表的字段都大量的使用作为查询结果,那么在一个类中,组合另外一个类,使用resultMap进行映射实现。使用association将关联信息映射到一个对象中。
4、对于一对多,多对多的联合查询,如果查询结果数据特殊使用resultMap,使用collection将关联信息映射到一个集合中去,如果只是针对明细的数据,建议定义扩展类,使用resultType映射实现。