Spring-Boot整合Mybatis的基础使用-复杂对象一对多映射
在我们日常开发中,经常会遇到查询一对多的业务场景,比如:订单,用户权限,用户菜单,文章评论,以前没有用到ORM的时候,都是批量取出再重新匹配或者循环取出,这在代码里面实现起来还是有些繁琐。在现今Mybatis
、Hibernate
等ORM框架里,都给我们提供方便的一对多的映射功能,使得我们的开发效率得到了提高。今天,我们就来演示一下订单一对多的关系映射。
我们先创建两张表,分别为td_order(订单表)
和td_order_line(订单行表)
:
1 | CREATE TABLE `mybatis`.`td_order` ( |
该表结构仅为演示所用,并不规范。
接下来继续新建两个类:
1 | @Getter |
然后新建一个OrderMapper
接口,接下来就该创建一对多的映射关系了,这里主要介绍两种方式,第一种主映射和子映射在一个resultMap
中:
1 | <resultMap id="OrderResult" type="com.mybatis.demo.dto.Order"> |
还有另外一种就是主映射和子映射分为两个resultMap
:
1 | <resultMap id="OrderResult" type="com.mybatis.demo.dto.Order"> |
现在,我们开始编写SQL来把数据查询出来
1 | <select id="queryOrder" resultMap="OrderResult"> |
为了方便后面做分页测试,我们就新增一个Controller
来看看调用效果:
1 | @RestController |
我从上面打印的查询结果可以看出,Mybatis
把我们LEFT JOIN
查询出来的数据进行了聚合分组,但是这样会有个弊端,就是在分页时计算出总记录数会有问题,什么问题,其实就是LEFT JOIN 关联出来的总记录数,但是其实我们只是想要主表的总记录数。我们来看看问题的现象吧
我们从SQL可以看得出,它是直接基于我们SQL来COUNT的,如果主表
和从表
是一对一的关系则不会出现这种问题,那么遇到一对多的分页该怎么办呢?接下来就是需要换种方式,采用主子表分别查询。直接看xml文件吧
1 | <mapper namespace="com.mybatis.demo.mapper.OrderMapper"> |
这里需要注意的是,collection
和子查询的sql中只能存在一个resultMap
,否则会报错
1 | Caused by: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'file [G:\mybatis\demo\target\classes\mapper\OrderMapper.xml]'. Cause: java.lang.IllegalStateException: Cannot define both nestedQueryId and nestedResultMapId in property lines |
collection
里需要指定column
来传递到子查询中,这里的id
指的是主表查询结果中的id列。现在,我们来看看效果,
可以从上面的SQL看到,它是先查询主表的总记录数,取出主表当前分页的记录,再循环查询子表。
collection
里指定column
除了上面的单个字段,还可以指定多个字段如column="{id=id,year=year}"
,指定的列表在主表查询出来的结果必须存在。
Spring-Boot整合Mybatis的基础使用-复杂对象一对多映射