Mybatis多表关联查询之多对一和一对多
周sir |
2017年6月15日 |
mytatis |
0 条评论 | 4724
MyBatis 多表关联可以分成四种:一对一、一对多、多对一、多对多。映射的关键是 resultMap。网上介绍很多,例如 MyBatis学习 之 二、SQL语句映射文件(1)resultMap。本文用 person / orders 演示多对一和一对多。
多对一看订单怎么带出所属人,用 association;一对多看人怎么带出订单列表,用 collection。两种方向各给几种写法:嵌套结果、复用 resultMap、嵌套查询。
一、多对一:订单 → 人
准备两张表,person 和 order 为 1:n

类结构

映射文件是 OrderMapper.xml。
| 写法 |
association 怎么配 |
SQL |
| 嵌套结果 |
javaType + 内嵌 id/result |
一次 join,p.* 和 o.* 一起查出 |
| 复用 resultMap |
resultMap 指向 personBaseBean |
同样一次 join |
| 嵌套查询 |
select 另查 Person |
先查订单,再按外键查人 |
第一种:嵌套结果映射
column 指外键,property 指对象属性,javaType 指属性类型:
<mapper namespace="com.ittx.mybatis.demo1.dao.OrderDao">
<resultMap type="com.ittx.mybatis.demo1.model.Order" id="orderBean">
<id column="orderId" property="id"/>
<result column="orderNumber" property="number"/>
<result column="orderPrice" property="price"/>
<!-- 多对一的关系 -->
<!-- column: 外键;property: 属性;javaType: 属性类型 -->
<association column="pid" property="person" javaType="com.ittx.mybatis.demo1.model.Person">
<id column="personId" property="id"/>
<result column="personName" property="name"/>
<result column="personAddress" property="address"/>
<result column="personTel" property="tel"/>
</association>
</resultMap>
<!-- 根据 id 查询 Order,关联将 Person 查询出来 -->
<select id="selectOrderById" parameterType="string" resultMap="orderBean">
select p.*, o.* from person p, orders o where p.personId = o.pid and o.orderId = #{id}
</select>
</mapper>
第二种:association 引用已有 resultMap
<mapper namespace="com.ittx.mybatis.demo1.dao.OrderDao">
<resultMap type="com.ittx.mybatis.demo1.model.Person" id="personBaseBean">
<id column="personId" property="id"/>
<result column="personName" property="name"/>
<result column="personAddress" property="address"/>
<result column="personTel" property="tel"/>
</resultMap>
<resultMap type="com.ittx.mybatis.demo1.model.Order" id="orderBean">
<id column="orderId" property="id"/>
<result column="orderNumber" property="number"/>
<result column="orderPrice" property="price"/>
<!-- column: 外键;property: 属性;resultMap: 属性的映射 -->
<association column="pid" property="person" resultMap="com.ittx.mybatis.demo1.dao.OrderDao.personBaseBean"/>
</resultMap>
<select id="selectOrderById" parameterType="string" resultMap="orderBean">
select p.*, o.* from person p, orders o where p.personId = o.pid and o.orderId = #{id}
</select>
</mapper>
第三种:association 的 select 嵌套查询
select 使用另一个查询封装结果,适合分步加载:
<mapper namespace="com.ittx.mybatis.demo1.dao.OrderDao">
<resultMap type="com.ittx.mybatis.demo1.model.Order" id="orderBean">
<id column="orderId" property="id"/>
<result column="orderNumber" property="number"/>
<result column="orderPrice" property="price"/>
<!-- column: 外键;property: 属性;select: 使用另一个查询封装的结果 -->
<association column="orderId" property="person" select="selectPersonByOrderId"/>
</resultMap>
<select id="selectOrderById" parameterType="string" resultMap="orderBean">
select * from orders where orderId = #{id}
</select>
<select id="selectPersonByOrderId" parameterType="string" resultMap="com.ittx.mybatis.demo1.dao.OrderDao.personBaseBean">
select * from person where personId in (select pid from orders where orderId = #{id})
</select>
</mapper>
二、一对多:人 → 订单列表
表结构不变,类结构如下

映射文件换成 PersonMapper.xml,用 collection。
第一种:collection 内嵌映射
property 是集合属性,ofType 是集合元素类型:
<resultMap type="com.ittx.mybatis.demo1.model.Person" id="personBean">
<id column="personId" property="id"/>
<result column="personName" property="name"/>
<result column="personAddress" property="address"/>
<result column="personTel" property="tel"/>
<!-- 一对多的关系 -->
<!-- property: 集合属性;ofType: 集合中元素的类型 -->
<collection property="orders" ofType="com.ittx.mybatis.demo1.model.Order">
<id column="orderId" property="id"/>
<result column="orderNumber" property="number"/>
<result column="orderPrice" property="price"/>
</collection>
</resultMap>
<!-- 根据 id 查询 Person,关联将 Orders 查询出来 -->
<select id="selectPersonById" parameterType="string" resultMap="personBean">
select p.*, o.* from person p, orders o where p.personId = o.pid and p.personId = #{id}
</select>
第二种:collection 引用 orderBaseBean
<resultMap type="com.ittx.mybatis.demo1.model.Order" id="orderBaseBean">
<id column="orderId" property="id"/>
<result column="orderNumber" property="number"/>
<result column="orderPrice" property="price"/>
</resultMap>
<resultMap type="com.ittx.mybatis.demo1.model.Person" id="personBean">
<id column="personId" property="id"/>
<result column="personName" property="name"/>
<result column="personAddress" property="address"/>
<result column="personTel" property="tel"/>
<collection property="orders" resultMap="com.ittx.mybatis.demo1.dao.OrderDao.orderBaseBean"/>
</resultMap>
<select id="selectPersonById" parameterType="string" resultMap="personBean">
select p.*, o.* from person p, orders o where p.personId = o.pid and p.personId = #{id}
</select>
一句话总结:多对一用 association 装单个对象,一对多用 collection 装列表;嵌套结果一次 join,嵌套查询拆成两次 SQL。id 列必须映射对,否则集合去重会乱。
转载请注明来源:Mybatis多表关联查询之多对一和一对多
我是周sir,这是我的博客。致力于分享我学会的技术和优秀的文章。微信公众号 “周sir专栏” 欢迎大家关注。