Mybatis高级应用 多表关联查询

>以订单商品数据模型为例子:

存在以下四张表,用户表user,用户订单表orders,订单明细表orderdetail,商品表items。四张表之间的关系如下图所示:

Mybatis高级应用 多表关联查询_第1张图片

下面给出四张表结构的详细定义,出于演示,每张表仅定义少量字段:

用户表: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映射实现。

你可能感兴趣的:(SSM)