处理 Mybatis 中一对多、多对一、多对多映射的黑魔法
来源:互联网 发布:80端口入侵 编辑:程序博客网 时间:2024/05/01 16:50
前言
先看看Mybatis官方介绍
MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
注意,这里是简单的XML! 可是,当我们的数据库表关系错综复杂,表与表之存在一对多、多对一、多对多的关系时,如何通过mybatis表示出他们的关系呢?网上很多文章都在介绍 association、 collection,我先不说association、 collection有多好,先来看看一个具体实例。
下图是订单的数据库表关系
有这样一个需求,我要展示类似于淘宝订单的效果,如下图:
我们看到上面的订单就会想到,要展示一条订单,需要:订单信息、物流信息、卖家信息、买家信息、商品信息、商品属性信息、商品状态信息…,至少也要5/6张表的数据,其中,订单对买家/卖家是多对一关系、订单对商品时多对多关系…,看看类似的xml:
<!-- 查询用户及购买的商品 type写的是user类的全路径 把数据映射到user中 --> <resultMap type="org.mybatis.po.User" id="UserAndItemsResultMap"> <!-- 用户信息 --> <id column="user_id" property="id" /> <result column="username" property="username" /> <result column="sex" property="sex" /> <result column="address" property="address" /> <!-- 订单信息一个用户对应多个订单,使用collection映射--> <collection property="ordersList" ofType="org.mybatis.po.Orders"> <id column="id" property="id" /> <result column="user_id" property="userId" /> <result column="number" property="number" /> <result column="createtime" property="createtime" /> <result column="note" property="note" /> <!-- 订单明细一个订单包括 多个明细 --> <collection property="orderdetailList" ofType="org.mybatis.po.Orderdetail"> <id column="orderdetailid" property="id" /> <result column="orders_id" property="ordersId" /> <result column="items_id" property="itemsId" /> <result column="items_num" property="itemsNum" /> <!-- 商品信息一个订单明细对应一个商品--> <association property="items" javaType="org.mybatis.po.Items"> <id column="items_id" property="id"></id> <result column="name" property="name" /> <result column="price" property="price" /> <result column="detail" property="detail" /> </association> </collection> </collection> ... <!--还有卖家、买家、物流...--> ...
仅仅这一个订单,如果用association、 collection来实现,xml何其多、何其复杂!除了xml,还有一堆实体类要写,写着写着很容易乱!这跟Mybatis官网上说的简单xml相悖,我想要的效果是简简单单的像一个实体类就能映射的xml,任何人,无论是初学者还是老程序员都能一眼直观的xml。
抛砖引玉
那么,要怎样将订单的xml简化,我先来一个抛砖引玉,mybatis和hibernate最大的区别是什么?
Mybatis可以更细致的定制化! hibernate 具体更强的移植性和缓存机制。既然说Mybatis可以更细致的定制化,如何定制!通过sql优化、sql定制,既然sql可以根据具体的需求而定,那么我可以利用sql处理数据库表的关系,只需要返回直观的结果给我就行。一言蔽之,就是:把一对多、多对一、多对多关系扔到sql中去处理,xml只需要接收最直接、最简单的数据即可!
好,回到订单,显示一个订单需要哪些信息,需要如下信息:
public class OrderInfo { //订单id private Integer id; //订单价格 private Integer price; //订单生成时间 private Date createdTime; //订单状态 private Integer status; //商品数量 private Integer util; //买家电话 private String phone; //买家名字 private String userName; //物流地址 private String receiverAddress; //支付方式 private String payName; //商品名称 private String productName; //商品属性 private String standard; //卖家名称 private String marketName; //商品缩略图 private String productPhoto; setter and getter...
xml怎么写? 我不需要association、 collection就可以实现,把数据库关系交给数据库处理,我用最原始的and 表示(这里以mysql为例)
... <select id="selectOrderInfoByOrderId" resultType="com.vbtime.thor.wrapper.OrderInfo" parameterType="java.lang.Integer"> select o.id as id, o.status as status, o.price as price,o.created_time as createdTime, o.util as util, u.name as userName, u.phone as phone, r.receiver_address as receiverAddress, pay.name as payName, group_concat(concat(ps.name,':',psv.value) Separator ';') as standard, m.name as marketName,p.name as productName,p.photo as productPhoto from rorder o, order_standard_value os, product_standard ps, product_standard_values psv, user u, product p, market m, order_market om, order_product op, pay_type pay, receiver r where u.id = o.user_id and p.id = op.product_id and o.id = op.order_id and m.id= om.market_id and o.id = om.order_id and o.id = os.order_id and psv.id = os.standard_value_id and ps.id= psv.product_standard_id and pay.id = o.pay_id and r.id = o.recevier_id and o.id = #{orderId} </select> ...
测试一下sql
说明一下,以商品的属性为例,商品属性有多个,颜色、尺码、材质、外观… 可以用mysql的group_concat() 和 concat() 函数将多行属性转化为订单的一列,多个属性之间可以用“;”或“//”分割,方便客户端处理。
总结
用sql处理数据库关系有3点好处:
减少xml复杂度,代码简洁可读性强
xml返回的数据跟实际业务需要的数据差不多,可以直接返回给客户端
充分发挥数据库本身的优势,有人说用sql语句处理表的关系,移植性差,其实mybatis本身是基于sql的,本来移植性就差,干脆我们使它差,为了偷懒!
- 处理 Mybatis 中一对多、多对一、多对多映射的黑魔法
- Mybatis一对多和多对一的映射
- Mybatis中关于映射文件一对多,多对一的方法理解
- Hibernate中一对多、多对一关系的映射
- MyBatis多对一,一对多关联映射
- MyBatis多对一,一对多关联映射
- mybatis复杂映射(一对多、多对一)
- Mybatis的多对一,一对多
- Mybatis 一对一,一对多,多对一,多对多 的处理
- Hibernate映射----(一对多,多对一)
- Hibernate一对多、多对一映射
- mybatis映射 一对一、一对多、多对多高级映射
- mybatis resaultMap 高级映射 (一对一,一对多,多对一,多对多)
- MyBatis关联表映射(一对多、多对多、一对一、多对一)
- mybatis高级映射关系,一对一,一对多,多对多,多对一
- MyBatis一对多和多对一
- MyBatis一对多和多对一
- MyBatis一对多和多对一
- Swift 中的泛型
- Android 如何做虚线边框
- 几场面试总结
- keil分散加载文件
- 实现一个UI效果,有关文字倾斜
- 处理 Mybatis 中一对多、多对一、多对多映射的黑魔法
- 基尼不纯度(Gini impurity)
- UVA725Division(紫书例题第七章1)
- vagrant启动两个实例配置
- 文章标题
- 完全卸载oracle 11g
- 数据库数据读取并且生成excel
- 计算一个整数二进制位中1的个数
- js基础-数据类型