mybatis级联,一对多(2)
来源:互联网 发布:淘宝信鸽出售 编辑:程序博客网 时间:2024/05/19 18:47
宽为限 紧用功 工夫到 滞塞通
接着上一篇博文,我又回来了
业务场景
商城购物,用户可以有多个订单,每个订单可以有多个商品。它们间的关系是:
- 用户对订单,一对多,订单对用户,一对一;
- 订单对订单明细,一对多,订单明细对订单多对一;
- 订单明细对订单明细项,一对一,订单明细项对订单明细,一对一;
- 订单明细项对商品,一对一,商品对订单明细项,一对一;
- 订单明细项对订单,多对一;
- 用户对商品,多对多。
下图是从用户开始到商品间顺的关系
根据数据库开始编码
1、用户实体类
package mybatis.cascade.test.po;/** * @Description: 用户实体 * @author 浮华 * @date 2017年8月9日,下午9:07:33 * */ public class User { /** * fdId */ private String fdId; public String getFdId() { return fdId; } /** * 用户名 */ private String fdName; public String getFdName() { return fdName; } public void setFdName(String fdName) { this.fdName = fdName; } /** * 手机号 */ private String fdPhone; public String getFdPhone() { return fdPhone; } public void setFdPhone(String fdPhone) { this.fdPhone = fdPhone; } /** * 地址 */ private String fdAddress; public String getFdAddress() { return fdAddress; } public void setFdAddress(String fdAddress) { this.fdAddress = fdAddress; }}
用户类本身无任何关联关系,是非常干净滴。它的Mapper和xml文件也很简单
UserMapper.java
package mybatis.cascade.test.mapper;import mybatis.cascade.test.po.User;public interface UserMapper { /** * 通过id获取用户 * @param fdId * @return */ public User getUserById(String fdId);}
userMapper.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="mybatis.cascade.test.mapper.UserMapper"> <!-- 用户 --> <resultMap type="user1" id="userMap"> <id property="fdId" column="fd_id" /> <result property="fdName" column="fd_name" /> <result property="fdPhone" column="fd_phone" /> <result property="fdAddress" column="fd_address" /> </resultMap> <select id="getUserById" resultMap="userMap"> select * from g_user where fd_id = #{fdId} </select></mapper>
2、订单实体类
package mybatis.cascade.test.po;import java.util.Date;import java.util.List;/** * @Description: 客户订单 * @author 浮华 * @date 2017年8月9日,下午9:13:31 * */ public class Orders { /** * fdId */ private String fdId; public String getFdId() { return fdId; } /** * 订单名(号) */ private String fdName; public String getFdName() { return fdName; } public void setFdName(String fdName) { this.fdName = fdName; } /** * 订单明细 */ private List<OrderItem> orderItemList; public List<OrderItem> getOrderItemList() { return orderItemList; } public void setOrderItemList(List<OrderItem> orderItemList) { this.orderItemList = orderItemList; } /** * 订单总价 */ private double fdTotalPrices; public double getFdTotalPrices() { return fdTotalPrices; } public void setFdTotalPrices(double fdTotalPrices) { this.fdTotalPrices = fdTotalPrices; } /** * 下单用户(订单角度,一对一) */ private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } /** * 下单时间 */ private Date fdOrderDateTime; public Date getFdOrderDateTime() { return fdOrderDateTime; } public void setFdOrderDateTime(Date fdOrderDateTime) { this.fdOrderDateTime = fdOrderDateTime; }}
订单类就开始不单纯了,它关联了用户private User user;
及订单明细private List<OrderItem> orderItemList;
,与用户的关系是一对一,与订单明细的关系是一对多。
我们看看它的Mapper和xml
OrdersMapper.java
package mybatis.cascade.test.mapper;import java.util.List;import mybatis.cascade.test.po.Orders;public interface OrdersMapper { /** * 通过id获取订单 * @param fdId * @return */ public Orders getOrdersById(String fdId); /** * 通过用户id获取用户订单 * @param fdUserId * @return */ public List<Orders> getOrdersListByUserId(String fdUserId);}
一个标配的getOrdersById(String fdId)
方法,一个getOrdersListByUserId(String fdUserId)
方法,这个方法就是用户关联订单的那条线。一对多,通过用户id可以获取该用户的所有订单。
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="mybatis.cascade.test.mapper.OrdersMapper"> <!-- 订单 --> <resultMap type="orders1" id="ordersMap"> <id property="fdId" column="fd_id" /> <result property="fdName" column="fd_name" /> <result property="fdTotalPrices" column="fd_total_prices" /> <result property="fdOrderDateTime" column="fd_order_datetime" /> <!-- 用户,一对一 --> <association property="user" column="fd_user_id" select="mybatis.cascade.test.mapper.UserMapper.getUserById" /> <!-- 订单明细项,一对多 --> <collection property="orderItemList" column="fd_id" select="mybatis.cascade.test.mapper.OrderItemMapper.getOrderItemListByOrderId" /> </resultMap> <select id="getOrdersById" resultMap="ordersMap"> select * from g_orders where fd_id = #{fdId} </select> <select id="getOrdersListByUserId" resultMap="ordersMap"> select * from g_orders where fd_user_id = #{fdUserId} </select></mapper>
看 resultMap,简单属性略讲。
①关联用户的配置:<association property="user" column="fd_user_id"
,
select="mybatis.cascade.test.mapper.UserMapper.getUserById" />
property=”user”,当前Order类的user属性;column=”fd_user_id”,Order类对应数据库表的关联用户的fd_id;select=”mybatis.cascade.test.mapper.UserMapper.getUserById”,拿到fd_user_id 在这里指定的地方去查询,这里的就是你mybatis.cascade.test.mapper.UserMapper.java文件中的getUserById(String fdId))
方法咯。
②关联明细项的配置:<collection property="orderItemList" column="fd_id"
,
select="mybatis.cascade.test.mapper.OrderItemMapper.getOrderItemListByOrderId" />
同上,这里column=”fd_id”要讲一下,因为一个订单可以有多个订单明细嘛,所以订单明细可以通过订单id来查,所以这里要的column就是订单自己的id咯。
3、订单明细实体类
package mybatis.cascade.test.po;/** * @Description: 订单明细 * @author 浮华 * @date 2017年8月10日,下午11:53:22 * */ public class OrderItem { /** * fdId */ private String fdId; public String getFdId() { return fdId; } /** * 所属订单,一对一 */ private Orders orders; public Orders getOrders() { return orders; } public void setOrders(Orders orders) { this.orders = orders; } /** * 商品记录项,一对一(不是直接关联商品而是关联一个商品记录项) */ private OrderDetail orderDetail; public OrderDetail getOrderDetail() { return orderDetail; } public void setOrderDetail(OrderDetail orderDetail) { this.orderDetail = orderDetail; }}
嗯,订单明细,我们来看看。
一个private Orders orders;
,关联用户;一个private OrderDetail orderDetail;
关联。。。等等,OrderDetail 这个是啥? 不是订单明细直接就可以关联商品了吗?
一开始博主也是订单明细直接关联商品的,但后来发现问题了所以就加了这个OrderDetail订单明细项,具体啥问题呢,我们稍后再聊。
接下来看看Mapper和xml文件:
OrderItemMapper .java
package mybatis.cascade.test.mapper;import java.util.List;import mybatis.cascade.test.po.OrderItem;public interface OrderItemMapper { /** * 通过id获取订单明细 * @param fdId * @return */ public OrderItem getOrderItemById(String fdId); /** * 通过订单id 获取订单明细列表 * @param fdOrderId * @return */ public List<OrderItem> getOrderItemListByOrderId(String fdOrderId);}
通订单实体一样,一个标配,一个通过订单id获取属于该订单的所有订单明细。
orderItemMapper.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="mybatis.cascade.test.mapper.OrderItemMapper"> <!-- 订单明细项 --> <resultMap type="orderItem1" id="orderItemMap"> <id property="fdId" column="fd_id" /> <!-- 订单,一对一 --> <association property="orders" column="fd_order_id" select="mybatis.cascade.test.mapper.OrdersMapper.getOrdersById" /> <!-- 订单明细,一对一 --> <association property="orderDetail" column="fd_order_detail_id" select="mybatis.cascade.test.mapper.OrderDetailMapper.getOrderDetailById" /> </resultMap> <select id="getOrderItemById" resultMap="orderItemMap"> select * from g_order_item where fd_id = #{fdId} </select> <!-- 通过订单id,获取订单明细项 --> <select id="getOrderItemListByOrderId" resultMap="orderItemMap"> select * from g_order_item where fd_order_id = #{fdOrderId} </select></mapper>
看看它的 resultMap,很简单,都是一对一关联关系,上面讲过了 yes略过。
4、订单明细项
package mybatis.cascade.test.po;/** * @Description: 订单明细商品项实体 * @author 浮华 * @date 2017年8月9日,下午9:23:56 * */ public class OrderDetail { /** * fdId */ private String fdId; public String getFdId() { return fdId; } /** * 所属订单(订单角度,一对一) */ private Orders orders; public Orders getOrders() { return orders; } public void setOrders(Orders orders) { this.orders = orders; } /** * 所属商品(订单角度,一对一) */ private Commodity commodity; public Commodity getCommodity() { return commodity; }}
额,看了这个Mapper和xml都不想贴出来了,都一样的! 唉~ 一开始还真不知道要你何用 ╮(╯▽╰)╭,不能厚此薄彼 是吧,还是牵出来溜溜 (*^_^*)
OrderDetailMapper .java
package mybatis.cascade.test.mapper;import mybatis.cascade.test.po.OrderDetail;public interface OrderDetailMapper { /** * 通过id获取订单明细商品项 * @param fdId * @return */ public OrderDetail getOrderDetailById(String fdId);}
嗯,也有点不一样吧,这里没有获取明细项List的是吧,因为这里已经没必要了,它的作用和OrderItem的确很像,所以它哪里有了这里就不需要了。
orderDetailMapper.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="mybatis.cascade.test.mapper.OrderDetailMapper"> <!-- 订单明细商品项 --> <resultMap type="orderDetail1" id="orderDetailMap"> <id property="fdId" column="fd_id" /> <!-- 用户订单,一对一 --> <association property="orders" column="fd_order_id" select="mybatis.cascade.test.mapper.OrdersMapper.getOrdersById" /> <!-- 商品,一对一 --> <association property="commodity" column="fd_commodity_id" select="mybatis.cascade.test.mapper.CommodityMapper.getCommodityById" /> </resultMap> <select id="getOrderDetailById" resultMap="orderDetailMap"> select * from g_order_detail where fd_id = #{fdId} </select></mapper>
OK,明细项结束,那我们顺便把上面留下的疑问也结束掉吧!
为什么OrderDetail作用与OrderItem类似,不用OrderItem直接关联商品而要通过它呢? 看一下我之前没有明细项这个中间实体时产生的问题吧
数据库里的数据
这里订单d01有5个商品,正常来说可以查出5个商品的是吧
实际查出来的结果
测试代码里是 orderDetail.getCommodity(); 之前是这里直接关联的商品,那为什么实际查出来的只有4个呢? 是这样的,因为用户购买的相同的商品,而在订单表明细表里记录的商品id是一样的,所以查询商品时就算一个了,这相当于是查的商品种类。
5、商品实体类
package mybatis.cascade.test.po;/** * @Description: 商品实体 * @author 浮华 * @date 2017年8月10日,下午11:52:40 * */ public class Commodity { /** * fdId */ private String fdId; public String getFdId() { return fdId; } /** * 商品名 */ private String fdName; public String getFdName() { return fdName; } public void setFdName(String fdName) { this.fdName = fdName; } /** * 单价 */ private double fdPrice; public double getFdPrice() { return fdPrice; } public void setFdPrice(double fdPrice) { this.fdPrice = fdPrice; } /** * 商品描述 */ private String fdDescribe; public String getFdDescribe() { return fdDescribe; } public void setFdDescribe(String fdDescribe) { this.fdDescribe = fdDescribe; } /** * 库存 */ private Integer fdReserve; public Integer getFdReserve() { return fdReserve; } public void setFdReserve(Integer fdReserve) { this.fdReserve = fdReserve; }}
和用户实体类一样的单纯
CommodityMapper.java
package mybatis.cascade.test.mapper;import mybatis.cascade.test.po.Commodity;public interface CommodityMapper { /** * 通过id获取商品 * @param fdId * @return */ public Commodity getCommodityById(String fdId);}
commodityMapper.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="mybatis.cascade.test.mapper.CommodityMapper"> <!-- 商品 --> <resultMap type="commodity1" id="commodityMap"> <id property="fdId" column="fd_id" /> <result property="fdName" column="fd_name" /> <result property="fdPrice" column="fd_price" /> <result property="fdDescribe" column="fd_describe" /> <result property="fdReserve" column="fd_reserve" /> </resultMap> <select id="getCommodityById" resultMap="commodityMap"> select * from g_commodity where fd_id = #{fdId} </select></mapper>
最后我们来看看测试类
package mybatis.cascade.test.test;import java.util.List;import org.apache.ibatis.session.SqlSession;import mybatis.cascade.test.mapper.OrdersMapper;import mybatis.cascade.test.po.Commodity;import mybatis.cascade.test.po.OrderDetail;import mybatis.cascade.test.po.OrderItem;import mybatis.cascade.test.po.Orders;import mybatis.cascade.test.po.User;import mybatis.cascade.test.util.SqlSessionFactoryUtil;/** * @Description: mybatis级联测试 * @author 浮华 * @date 2017年8月9日,下午9:40:33 * */ public class TestMain { public static void main(String[] args) { SqlSession sqlSession = null; try { sqlSession = SqlSessionFactoryUtil.openSqlSession(); // 创建订单代理对象 OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class); /** * 通过用户id获取订单 */ List<Orders> ordersListByUserId = ordersMapper.getOrdersListByUserId("u01"); for(Orders order : ordersListByUserId) { System.out.println("\n" + order.getFdName()); // 订单关联的用户(一对一) User user = order.getUser(); System.out.println("客户名称:" + user.getFdName()); // 获取订单商品项(一对多) List<OrderItem> orderItemList = order.getOrderItemList(); for (OrderItem orderItem : orderItemList) { // 之前把这过商品过渡类忽略了,然后相同id的商品就合一起了。 OrderDetail orderDetail = orderItem.getOrderDetail(); // 终于得到商品列表 Commodity commodity = orderDetail.getCommodity(); String fdName = commodity.getFdName(); System.out.println(fdName); } } } finally { if(sqlSession != null) { sqlSession.close(); } } }}
运行结果
d01订单这里也是4个,因为这里也4条数据
虽然说实际上不会这样找商品,找到了也没什么意义,多个商品可以直接在订单明细那里记录数量就行,但一开始想的就是订单里有几个商品我就要通过用户id找到他当前订单的几个商品,所以就酱紫搞咯 \(^o^)/YES!
奉上源码
https://github.com/zgmFlashy/mybatis_test/tree/master/mybatis_cascade
站在巨人的肩膀上
本博文参考的文章
mybatis官方参考文档
mybatis入门基础(六)—-高级映射(一对一,一对多,多对多)
- mybatis级联,一对多(2)
- mybatis级联,一对多(1)
- mybatis ---- 级联查询 一对多 (集合映射)
- mybatis ---- 级联查询 一对多 (集合映射)
- mybatis ---- 级联查询 一对多 (集合映射)
- mybatis ---- 级联查询 一对多 (集合映射)
- mybatis ---- 级联查询 一对多 (集合映射)
- MyBatis 级联查询,一对一,一对多
- MyBatis学习总结——实现级联表查询(一对一,一对多)
- myBatis级联一对一,一对多及批量操作
- 【JPA 级联保存/级联删除】@OneToMany (双向) 一对多
- 【JPA 级联保存/级联删除】@OneToMany (双向) 一对多
- [NHibernate]一对多关系(级联删除,级联添加)
- 【转】[NHibernate]一对多关系(级联删除,级联添加)
- hibernate_day03_07_一对多操作(级联删除)
- MyBatis一对多(预习)
- mybatis一对多(二)
- Hibernate----@Annotation----一对多----级联
- C++之函数
- EasyDemo*android面试常见题
- 解决python写入csv后用wps打开乱码
- linux环境变量的修改操作
- hdu6108 小C的倍数问题(超简单题)
- mybatis级联,一对多(2)
- Day49-Spring-03
- SocksCap64全局代理设置教程
- HDU_1671 POJ_3630 Phone List 【字典树】
- NYOJ 34 韩信点兵
- 前端小知识点
- android (多moudle集成aar的另一种思路)app集成第3方app的方案记录
- 收藏安装Python
- SQL语言基础回顾整理