MyBatis(14)MyBatis 如何实现多对一和一对多的映射关系

MyBatis 中实现多对一和一对多的映射主要依赖于映射文件中的 <association><collection> 标签。这两种映射关系的实现,是通过嵌套查询或嵌套结果映射来完成的。在源码层面,MyBatis 使用相应的处理器来处理这些标签,最终实现复杂关系对象的装配。

多对一映射(Association)

多对一映射通常用于关联查询中的“多”的一端关联到“一”的一端的情形。在MyBatis中,可以通过 <association> 标签来实现。

映射文件配置

假设有订单(Order)和用户(User)两个实体,其中订单属于某一个用户,即多对一的关系。

首先,定义用户和订单的实体类,然后在订单的映射文件中使用 <association> 来映射用户信息:

<mapper namespace="com.example.OrderMapper">
  <resultMap id="OrderResultMap" type="Order">
    <id column="order_id" property="id"/>
    <result column="order_number" property="orderNumber"/>
    <result column="order_date" property="orderDate"/>
    <association property="user" javaType="User">
      <id column="user_id" property="id"/>
      <result column="username" property="username"/>
      <result column="email" property="email"/>
    </association>
  </resultMap>

  <select id="selectOrderById" resultMap="OrderResultMap">
    SELECT o.order_id, o.order_number, o.order_date,
           u.user_id, u.username, u.email
    FROM orders o
    JOIN users u ON o.user_id = u.user_id
    WHERE o.order_id = #{id}
  </select>
</mapper>

在上面的示例中,<association> 标签用于映射订单到用户的多对一关系。property 属性指定了目标对象中的属性名,而 javaType 属性指定了关联对象的类型。

源码解析

在解析 <association> 标签时,MyBatis 将创建一个 ResultMapping 对象来存储与关联有关的元数据。解析过程主要由 XMLMapperBuilderResultMapResolver 完成。

当执行查询时,MyBatis 调用 DefaultResultSetHandler 类来处理结果集。如果存在嵌套查询,则可能先执行主查询,然后根据主查询的结果执行嵌套查询。对于嵌套结果映射,MyBatis 会在处理结果集的过程中根据配置直接填充关联的对象。

一对多映射(Collection)

一对多映射通常用于关联查询中的“一”的一端关联到“多”的一端的情形。在MyBatis中,可以通过 <collection> 标签来实现。

映射文件配置

假设用户(User)和订单(Order)之间的关系,用户可以拥有多个订单,即一对多的关系。

在用户的映射文件中使用 <collection> 来映射订单信息:

<mapper namespace="com.example.UserMapper">
  <resultMap id="UserResultMap" type="User">
    <id column="user_id" property="id"/>
    <result column="username" property="username"/>
    <result column="email" property="email"/>
    <collection property="orders" ofType="Order">
      <id column="order_id" property="id"/>
      <result column="order_number" property="orderNumber"/>
      <result column="order_date" property="orderDate"/>
    </collection>
  </resultMap>

  <select id="selectUserWithOrders" resultMap="UserResultMap">
    SELECT u.user_id, u.username, u.email,
           o.order_id, o.order_number, o.order_date
    FROM users u
    LEFT JOIN orders o ON u.user_id = o.user_id
    WHERE u.user_id = #{id}
  </select>
</mapper>

在上面的示例中,<collection> 标签用于映射用户到订单的一对多关系。property 属性指定了目标对象中的集合属性名,而 ofType 属性指定了集合中元素的类型。

源码解析

<association> 类似,MyBatis 在解析 <collection> 标签时也会创建一个 ResultMapping 对象。解析过程同样主要由 XMLMapperBuilderResultMapResolver 完成。

在执行查询并处理结果集时,MyBatis 使用 DefaultResultSetHandler 类并采用与 <association> 类似的处理逻辑。不同之处在于,MyBatis 会将每条记录映射到子对象中,并将这些子对象收集到父对象的集合属性中,从而实现一对多的关系映射。

总结

MyBatis 通过 <association><collection> 标签提供了强大的关系映射能力,允许开发者以相对简单的方式实现复杂的关系映射。在底层,MyBatis 通过解析配置文件中的映射定义,创建相应的映射和结果处理器来实现这些关系映射。这种方式不仅简化了SQL的编写,还为实现复杂的关系数据提取提供了强有力的支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辞暮尔尔-烟火年年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值