mybatis级联,一对多(2)

来源:互联网 发布:淘宝信鸽出售 编辑:程序博客网 时间:2024/05/19 18:47
宽为限 紧用功 工夫到 滞塞通

我又回来了

接着上一篇博文,我又回来了这里写图片描述

业务场景

商城购物,用户可以有多个订单,每个订单可以有多个商品。它们间的关系是:

  1. 用户对订单,一对多,订单对用户,一对一;
  2. 订单对订单明细,一对多,订单明细对订单多对一;
  3. 订单明细对订单明细项,一对一,订单明细项对订单明细,一对一;
  4. 订单明细项对商品,一对一,商品对订单明细项,一对一;
  5. 订单明细项对订单,多对一;
  6. 用户对商品,多对多。

下图是从用户开始到商品间顺的关系
这里写图片描述

根据数据库开始编码

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入门基础(六)—-高级映射(一对一,一对多,多对多)