MyBatis知识点复习-09多表操作讲解
在阅读本文前,如果你对多表关系不太了解可以看看这篇Mysql语法教程里的多表操作。前面章节我们一直都是使用的单表查询(在POJO包装的时候用过多表),今天我们将系统的学习一遍。
一.一对一
一对一我们选择user表和orders表来演示
1.简单一对一
这里我说的简单一对一就是虽然是关联查询两个表但最后只返回一个表的数据(这里我返回的是ordes表数据)
先在mapper包下面新建OrdersMapper接口与OrdersMapper.xml;
OrdersMapper.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="mapper.OrdersMapper">
</mapper>
后面的配置会在<mapper>标签下面添加。现在我们的全局配置文件是不用改来添加映射配置的,因为已经有了
<package name="mapper"/>
这个配置。
然后我们在OrdersMapper接口里面添加下面这个方法
public List<Orders> findOrdersBySex(String sex);
在OrdersMapper里面添加下面这一段:
#查询出Orders表里面的性别为1的数据
<select id="findOrdersBySex" parameterType="String" resultType="orders">
select o.* from orders o,user u where o.user_id = u.id and u.sex = #{sex}
</select>
Test方法内容:
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
List<Orders> ordersBySex = mapper.findOrdersBySex("1");
System.out.println(ordersBySex);
sqlSession.commit();//提交事务,否则会事务回滚
结果如下:
2.复杂一对一
这里我说的复杂一对一指的是不单单只返回一个表的数据,而是要返回两个表的数据,这里我还是用orders表和user表为例,这个时候我们一般两种做法
①扩展类方案:创建一个扩展对象,将user与orders的属性都放进去
②添加属性方案:在orders里面添加一个User这个POJO类的成员属性(当然可以选择创建一个扩展类或者在User里面加Orders,大同小异)()
关于第一个方法我就不演示了,比较简单,交给读者自己尝试,我来实现第二个:在orders里面添加一个User这个POJO类的成员属性,同时添加getter与setter方法这个操作我不演示了(我的教程其实讲的特别详细,基本上是每一步都讲了)
然后我们在OrdersMapper接口里面添加下面这个方法
public Orders findOrdersByName(String name);
在这里我们不可以使用resultType,而是resultMap
<resultMap id="ordersMap" type="orders">
<!--映射属性与列名-->
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="createtime" column="createtime"></result>
<result property="note" column="note"></result>
<!--利用association来为Orders的user属性赋值-->
<association property="user" javaType="user">
<result property="username" column="name"></result>
<result property="id" column="uid"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<result property="address" column="address"></result>
</association>
</resultMap>
<select id="findOrdersByName" parameterType="String" resultMap="ordersMap">
SELECT o.*,u.`address`,u.`birthday`,u.`id` uid,u.`name`,u.`sex` FROM orders o,USER u WHERE o.user_id = u.id AND u.name = #{name}
</select>
<association>标签的property属性的值user指的是orders类的属性user,而javaType的user是指的类型,因为我们在全局配置文件里面为domain.User起了别名user。
Test方法内容如下:
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
Orders ordersByName = mapper.findOrdersByName("张三");
System.out.println(ordersByName);
sqlSession.commit();//提交事务,否则会事务回滚
重点:细心的你不知道有没有发现一个问题,在前面我们讲解resultMap那一章里面,我们使用resulytMap我们并没有把所有的属性与字段全部写出来去一一对应,只是把名字不匹配的写出来了,在那个地方是可以的,因为那时候我们还是单表操作,但是现在我们来到多表操作后,一定要注意我们必须把所有的都映射上去,否则就会查询出来很多null(这是因为在mybatis底层没有映射的他当成不匹配,即使属性名与字段名一致)
二.一对多
这一部分我们使用的是orders表与orderdetail表来讲解,实现方案我们采取添加属性的方案,不采用扩展类。
在orders类里面添加一个集合属性
private List<Orderdetail> orderdetails;
然后实现他的getter与setter方法。
然后我们在OrdersMapper接口里面添加下面这个方法
public Orders findOrdersWithDetail(int order_id);
在OrdersMapper.xml文件添加下面内容:
<resultMap id="ordersMap2" type="orders">
<!--映射属性与列名-->
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="createtime" column="createtime"></result>
<result property="number" column="number"></result>
<result property="note" column="note"></result>
<!--利用collection来实现对集合属性的赋值-->
<collection property="orderdetails" ofType="orderdetail">
<result property="id" column="oid"></result>
<result property="ordersId" column="orders_id"></result>
<result property="itemsId" column="items_id"></result>
<result property="itemsNum" column="items_num"></result>
</collection>
</resultMap>
<select id="findOrdersWithDetail" parameterType="int" resultMap="ordersMap2">
SELECT o.*,od.id oid,od.orders_id,items_id,items_num FROM orders o,orderdetail od WHERE o.`id`=od.`orders_id` AND o.id=#{order_id}
</select>
这里的collection与association大同小异,这里我就不细说了。
Test方法内容如下:
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
Orders ordersWithDetail = mapper.findOrdersWithDetail(3);
System.out.println(ordersWithDetail);
sqlSession.commit();//提交事务,否则会事务回滚
运行结果(比较长分两次截的):
三.多对多
温馨提示:现在来到了我们本章的最后一讲了。本讲是最难的一个部分,将前面两节综合应用,请您细品。我会讲的很细致。
首先我们来看看上面上面的这个表的关联图。从这张图我们可以读出下面关键信息:
①一个user对应对个orders
②一个orders对应多个orderdetail
③一个orderdetail对应一个一个items
根据这些信息我们明白需要在user类里面添加List<Orders> orders;
在Orders类里面添加List<Orderdetail> orderdetails;
在orderdetail里添加Items item;
这些工作留给读者自行完成
现在我们需要根据姓名查出该人对应的user,orders,orderdetail,items的所有信息。
我们先分析我们的sql语句。
SELECT
u.*,o.`number`,o.`createtime` orders_createname,od.`items_num`,
it.`createtime` item_createname,it.`detail`,it.`name`,it.`price`
FROM USER
u,orders o,orderdetail od,items it
WHERE
u.`id` = o.`user_id`
AND
o.`id` = od.`orders_id`
AND
od.`items_id` = it.`id`
查询结果如下:
接下来我们在UserMapper接口里面添加下面的方法:
public List<User> findUsersAllInfoByName(String name);
那么现在我们来使用mybatis实现
将下来就是最最最重要的xml配置了,我们到UserMapper.xml文件里面添加如下内容(放心我会一步一步来的,给你讲的明明白白,这里提醒一下,基本思想就是不断的嵌套):
<resultMap id="AllInfoMap" type="User">
<id property="id" column="id"></id>
<result property="username" column="name"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<result property="address" column="address"></result>
<!--配置orders集合-->
<collection property="orders" ofType="orders">
<result property="number" column="number"></result>
<result property="createtime" column="orders_createtime"></result>
<!--插入处1-->
</collection>
</resultMap>
<select id="findUsersAllInfoByName" parameterType="String" resultMap="AllInfoMap">
select
u.*,o.`number`,o.`createtime` orders_createtime,od.`items_num`,it.`createtime` item_createtime,
it.`detail`,it.`name`,it.`price`
from user
u,orders o,orderdetail od,items it
where
u.`id` = o.`user_id`
and
o.`id` = od.`orders_id`
and
od.`items_id` = it.`id`
and u.name = #{name}
</select>
上面我们把User的属性都配置好了(除了orders的orderdetails属性,我们在代码插入处1来实现),接下来我们在代码插入处1实现下面代码:
<collection property="orderdetails" ofType="orderdetail">
<result property="itemsNum" column="items_num"></result>
<!--插入处12-->
</collection>
现在我们把orders的orderdetails配置好了(除了他的item属性,将在代码插入处2实现):
<association property="item" javaType="items">
<result property="name" column="name"></result>
<result property="price" column="price"></result>
<result property="createtime" column="item_createtime"></result>
<result property="detail" column="detail"></result>
</association>
到此大功告成。走到这里我们发现其实也没有那么难,只要把前面两节掌握好了就很简单了。
Test方法内容为:
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> AllInfo = mapper.findUsersAllInfoByName("张小明");
System.out.println(AllInfo);
sqlSession.commit();//提交事务,否则会事务回滚
结果:
[User{id=16, username='张小明', sex='1', birthday=null, address='河南郑州',
orders=[Orders [id=null, userId=null, number=1000010, createtime
=Wed Feb 04 13:22:35 CST 2015,
note=null, user=null, orderdetails=[Orderdetail{id=null, ordersId=null,
itemsId=null, itemsNum=1, item=Items [id=null, name=张小明, price=3000.0,
pic=null, createtime=Tue Feb 03 13:22:53 CST 2015, detail=该电脑质量非常
好!!!!]}, Orderdetail{id=null, ordersId=null, itemsId=null, itemsNum=3,
item=Items [id=null, name=张小明, price=6000.0, pic=null, createtime=Mon
Feb 09 13:22:57 CST 2015, detail=笔记本性能好,质量好!!!!!]}]]]}]