Mybatis多表关联查询之多对一和一对多

    |     2017年6月15日   |   mytatis   |     0 条评论   |    4724

MyBatis 多表关联可以分成四种:一对一、一对多、多对一、多对多。映射的关键是 resultMap。网上介绍很多,例如 MyBatis学习 之 二、SQL语句映射文件(1)resultMap。本文用 person / orders 演示多对一和一对多。

多对一看订单怎么带出所属人,用 association;一对多看人怎么带出订单列表,用 collection。两种方向各给几种写法:嵌套结果、复用 resultMap、嵌套查询。

一、多对一:订单 → 人

准备两张表,person 和 order 为 1:n

person_order

类结构

class7

映射文件是 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多表关联查询之多对一和一对多
本文链接地址:https://ai.zhousir.top/?p=1982
回复 取消