mybatis级联,一对多(2)

宽为限 紧用功 工夫到 滞塞通

我又回来了

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

业务场景

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

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值