多表之间的数据交互
其实一对一和一对多映射,在前面的配置中已经接触到,我没在日志里直接说明,是因为想要在之后写一篇总结日志(就是本篇),总结这些高级映射的配置。例如一对一查询在关联的嵌套结果集查询中就涉及到,一对多查询则在这个基础上再加上一个或多个嵌套结果集,它们可以是一个实体类,或者是一个集合。多对多查询稍微有点复杂,举个例子来说,一个商城管理系统中,一名顾客在一个购物清单中可以有多件商品,而一件商品可以被多名顾客选购,它们之间的关系是多对对。假设现在有这么一个需求,查询数据表库中,所有的顾客信息,包括它们的购物清单,以及清单里面的商品信息,怎么做?下面会说。
无论是一对一、一对多还是多对多查询,都涉及到不同表之间的数据交互,因为它们之间需要主外键关系来关联,例如顾客表和购物清单表都有顾客id属性,根据这个属性来查询不同顾客对应的购物清单,有了主外键关系后,就可以进行高级映射了。
事例模型
为了展示三种映射示例,首先建立一个商场管理系统模型,里面有三张数据表,分别是顾客表user,购物车(商品清单)表shoppingcart和商品表products。顾客和商品清单之间是一对多的关系,因为一名顾客可以多次进商场购物,每一次购物生成一个购物清单(购物车),而每一张购物清单只属于一名顾客,所以顾客表和购物车表之间是一对多的关系。 还有商品表product,因为一张购物清单中可以有多件商品,所以商品表和购物车表为一对多的关系。因为一名顾客可以购买多件商品,一件商品也可以属于多名顾客,所以顾客和商品又构成多对多关系。我们在测试时,可以建立基本的三张表,:顾客表、购物车表和商品表(当然最好多加几张表,例如商品评价表),它们之间的查询可以组合出一对一、一对多以及多对多的关系,理清各张表的关系后,就可以进行测试了。
一对一嵌套结果集查询
从上面的事例模型中可以看到,含一对一关系的两张表有,购物车表和用户表,要注意其中的顺序不要弄乱,购物车和顾客是一对一关系,但反过来不是,顾客和购物车是一对多的关系。在查询需求中,这种多表之间一对一查询的场景,典型的有:一对一嵌套结果集查询。举个例子,假如我们要查询购物车表中,某一张购物清单信息,以及对应的该名顾客的个人信息。有两种配置方式,或是说两种方法实现:
resultType结合查询包装类
实现上面的一对一嵌套结果集查询,如果使用resultType来配置SQL映射的话,因为涉及到两张表的交互,且最后只能映射到一个实体类中,所以需要新建一个查询包装类,来包括其中含有的两张表的结果集字段对应的属性(这句话表述的不好- -、)。也就是说,新创建一个查询包装类,里面既含有购物车表中的字段对应的属性,也含有用户表中字段对应的属性,这样才能接收结果集中包含的两个表里的数据。来看看这个查询包装类:
// 购物车表一对多查询包装类
public class ShoppingCartInstance extends ShoppingCart implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String username; //顾客姓名
private String gender; //性别
private String province; //省会
private String city; //城市
public ShoppingCartInstance() {
}
public ShoppingCartInstance(int cartId, int userId, int productId,
String productName, int number,
double price, User user, String username, String gender, String province,
String city) {
super(cartId, userId, productId, productName, number, price);
this.username = username;
this.gender = gender;
this.province = province;
this.city = city;
}
// 省略get()和set()方法
}
我们的查询包装类采用继承的方式得到购物车实体类的所有属性,当然你也可以重新一个一个自己定义,这样来舍去一些不需要的属性。接着在查询包装类中追加顾客表中的属性,对应返回结果集中顾客数据表的字段。
数据包装类准备好后,接下来可以写我们的SQL语句和映射配置了:
<!-- 一对一查询:resultType实现 -->
<select id="queryShoppingCartInstance1" parameterType="int" resultType="ShoppingCartInstance">
SELECT
S.cartId, S.productName, S.userId, S.price, S.number,
U.id, U.username, U.gender, U.province, U.city
FROM ShoppingCart S left outer join user U on S.userId = U.id
WHERE S.cartId = #{id}
</select>
SQL语句根据id查询出购物清单,并根据外键,顾客id关联另一张数据表user顾客表。
public void TestAssociationQuery() throws IOException {
SqlSession sqlSession = dataConn.getSqlSession();
List<ShoppingCartInstance> resultList = sqlSession.selectList("queryShoppingCartInstance1", 2);
StringBuffer result = new StringBuffer();
double totalAmount;
System.out.println("顾客姓名: " + resultList.get(0).getUsername());
System.out.println("性别: " + resultList.get(0).getGender());
System.out.pr