设为首页 收藏本站
查看: 1360|回复: 0

[经验分享] mybatis系列三:一对多双向关联

[复制链接]

尚未签到

发表于 2016-11-27 06:36:36 | 显示全部楼层 |阅读模式
  一 建表,提供初始数据。
  表说明:t_customer为客户信息表;t_orders为订单表。一个客户可以有多个订单,一个订单只属于一个客户。多方使用外键(t_orders表的customer_id)来约束。这里并没有建立强制的外键约束,做更新,删除操作时会很麻烦。

CREATE TABLE `t_customer` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`cell_phone` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `t_customer` VALUES ('1', 'bing', '652346543');
INSERT INTO `t_customer` VALUES ('2', 'jade', '76345');
CREATE TABLE `t_orders` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`number` varchar(40) NOT NULL,
`address` varchar(40) NOT NULL,
`customer_id` int(10) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `t_orders` VALUES ('1', 'GASDF235', '北京朝阳', '1');
INSERT INTO `t_orders` VALUES ('2', 'JHGFVSD34', '河南郑州', '1');
INSERT INTO `t_orders` VALUES ('3', 'KJHGFDC234', '北京海淀', '2');
  表模型如下
DSC0000.jpg
二 实体类
  Customer

package com.alex.app.entity;
import java.util.List;
/**
* 客户信息
* @author leileiyuan
*
*/
public class Customer {
private Integer id;
private String name;
private String cellPhone;
//一对多
private List<Orders> orders;
public List<Orders> getOrders() {
return orders;
}
public void setOrders(List<Orders> orders) {
this.orders = orders;
}
// 略 getter setter方法
@Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", cellPhone=" + cellPhone + "]";
}
}

  Orders

package com.alex.app.entity;
/**
* 客户订单信息
* @author leileiyuan
*
*/
public class Orders {
private Integer id;
private String number;
private String address;
// 多对一
private Customer customer;
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
//  略 getter setter方法
@Override
public String toString() {
return "Orders [id=" + id + ", number=" + number + ", address=" + address + ", customer="
+ customer + "]";
}
}

  多对一映射
  1)问题简单分析
  从orders 到 customer 多对一的关联关联。
  就是说 我们要查询orders的信息,然后经该orders可以导航到它对应的customer
  考虑这个sql

select o.*, c.* from t_orders o
join t_customer c
on o.customer_id = c.id
where o.id = 2
  查询是没有问题的
  DSC0001.jpg
 映射文件配置时可以。

<select id="selectById" parameterType="int" resultMap="???????">
select
c.id           cid,
c.name         name,
c.cell_phone   cellPhone,
o.id           oid,
o.number       number,
o.address      address
from t_orders o
join t_customer c
on o.customer_id = c.id
where o.id = #{id}
</select>
  因为我们查询的结果集中包含的是orders和customer的所有列,所以返回的结果集应该使用resultMap而不是resultType(也可以也写一个VO,来封装结果中的列,那么就可以使用resultType指向那个VO)。
  2)映射结果集
  我们来写个resultMap 来封装这个复杂结果集
Orders.xml的映射文件如下。t_orders和t_customer的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="com.alex.app.dao.OrdersDao">
<resultMap type="Orders" id="OrdersResultMap">
<id property="id" column="oid"/>
<result property="number" column="number"/>
<result property="address" column="address"/>
</resultMap>
<select id="selectById" parameterType="int" resultMap="OrdersResultMap">
select
c.id           cid,
c.name         name,
c.cell_phone   cellPhone,
o.id           oid,
o.number       number,
o.address      address
from t_orders o
join t_customer c
on o.customer_id = c.id
where o.id = #{id}
</select>
</mapper>
  定义了一个resultMap,id为OrdersResultMap,查询的结果集指向这个resultMap。
  来测试下

@Test
public void test() {
SqlSession session = null;
try {
session = MyBatisUtil.openSession();
OrdersDao ordersDao = session.getMapper(OrdersDao.class);
Orders orders = ordersDao.selectById(1);
System.out.println(orders);
} catch (Exception e) {
e.printStackTrace();
session.rollback();
}finally{
MyBatisUtil.coloseSession(session);
}
}

  结果如下

Orders [id=1, number=GASDF235, address=北京朝阳, customer=null]
  customer为null。
  
  3)表达关联关系
  我们还需要把orders到customer多对一,这个一方,也表示在resultMap里。使用association 标签。
  t_orders和t_customer的id列,要使用别名来区分

<resultMap type="Orders" id="OrdersResultMap">
<id property="id" column="oid"/>
<result property="number" column="number"/>
<result property="address" column="address"/>
<association property="customer" javaType="Customer">
<id property="id" column="cid"/>
<result property="name" column="name"/>
<result property="cellPhone" column="cell_phone"/>
</association>
</resultMap>
   
  association解释
  属性:property,当然是Orders实体中定义的属性名customer;
  javaType,是customer所要映射成那个Java对象,这可以使用别名
  子标签:
  id,表示主键,property是实体类的属性名,column是对应表的字段列名
  result,表示普通属性
  4)再运行上面的测试代码,得到结果

Orders [id=1, number=GASDF235, address=北京朝阳, customer=Customer [id=1, name=bing, cellPhone=null, orders=null]]
 看到我们已经关联上了,也返回了正确的结果。  5)Orders.xml完整内容。t_orders和t_customer的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="com.alex.app.dao.OrdersDao">
<resultMap type="Orders" id="OrdersResultMap">
<id property="id" column="oid"/>
<result property="number" column="number"/>
<result property="address" column="address"/>
<association property="customer" javaType="Customer">
<id property="id" column="cid"/>
<result property="name" column="name"/>
<result property="cellPhone" column="cell_phone"/>
</association>
</resultMap>
<select id="selectById" parameterType="int" resultMap="OrdersResultMap">
select
c.id           cid,
c.name         name,
c.cell_phone   cellPhone,
o.id           oid,
o.number       number,
o.address      address
from t_orders o
join t_customer c
on o.customer_id = c.id
where o.id = #{id}
</select>
</mapper>
  四  一对多关联映射
  从customer到orders一对多的关联关系。一个客户对多个订单信息
  1)问题分析
  考虑这个sql

select c.*, o.* from t_customer c
join t_orders o
on c.id = o.customer_id
where c.id = 1
  查询结果bing这个客户拥有两个订单
  DSC0002.jpg
2)映射结果集
  映射文件的sql

<select id="selectById" parameterType="int" resultMap="CustomerResultMap">
select
c.id          cid,
c.name        name,
c.cell_phone  cellPhone,
o.id          oid,
o.number      number,
o.address     address
from t_customer c, t_orders o
where c.id = o.customer_id
and   c.id = #{id}
</select>
  3)一对多关联
  上面我们需要提供一个resultMap="CustomerResultMap"。t_orders和t_customer的id列,要使用别名来区分

<resultMap type="Customer" id="CustomerResultMap">
<id property="id" column="cid" />
<result property="name" column="name" />
<collection property="orders" javaType="ArrayList" ofType="Orders">
<id property="id" column="oid" />
<result property="number" column="number" />
</collection>
</resultMap>
  一对多关联,多的一方使用collection表示
  collection 属性 解释:
  property,是实体类中的属性orders;
  javaType,这里的JavaType代表的是实体类中的属性orders的类型是ArrayList

//一对多
private List<Orders> orders;
  ofType,是集合中的放置的内容的类型,这里集合放的东西是Orders对象
  4)测试下

@Test
public void testSelectCustomer() {
SqlSession session = null;
try {
session = MyBatisUtil.openSession();
CustomerDao customerDao = session.getMapper(CustomerDao.class);
Customer customer = customerDao.selectById(1);
System.out.println(customer);
List<Orders> orders = customer.getOrders();
System.out.println(orders);
} catch (Exception e) {
e.printStackTrace();
}finally{
MyBatisUtil.coloseSession(session);
}
}
  结果

DEBUG 2015-05-10 08:59:28,640 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==>  Preparing: select c.id cid, c.name name, c.cell_phone cellPhone, o.id oid, o.number number, o.address address from t_customer c, t_orders o where c.id = o.customer_id and c.id = ?
DEBUG 2015-05-10 08:59:28,687 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Parameters: 1(Integer)
DEBUG 2015-05-10 08:59:28,718 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: <==      Total: 2
Customer [id=1, name=bing, cellPhone=null, orders=[Orders [id=1, number=GASDF235, address=null, customer=null], Orders [id=2, number=JHGFVSD34, address=null, customer=null]]]
[Orders [id=1, number=GASDF235, address=null, customer=null], Orders [id=2, number=JHGFVSD34, address=null, customer=null]]
  5)Customer.xml完整内容。t_orders和t_customer的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="com.alex.app.dao.CustomerDao">
<resultMap type="Customer" id="CustomerResultMap">
<id property="id" column="cid" />
<result property="name" column="name" />
<collection property="orders" javaType="ArrayList" ofType="Orders">
<id property="id" column="oid" />
<result property="number" column="number" />
</collection>
</resultMap>
<select id="selectById" parameterType="int" resultMap="CustomerResultMap">
select
c.id          cid,
c.name        name,
c.cell_phone  cellPhone,
o.id          oid,
o.number      number,
o.address     address
from t_customer c, t_orders o
where c.id = o.customer_id
and   c.id = #{id}
</select>
</mapper>
  
 

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-305879-1-1.html 上篇帖子: Mybatis 打印完整sql 下篇帖子: ibatis2.x与mybatis(ibatis3.x)的比较
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表