Mybatis中<association>和<collection>的使用时机,以及懒加载和预加载问题

134 阅读3分钟

在MyBatis中,<association><collection>是两个重要的元素,它们用于处理对象之间的关联关系,特别是在处理一对多(如订单和订单项)和多对一(如用户和部门)等关系时。以下是这两个元素的简要总结:

<association>

<association>元素用于处理“一对一”和“多对一”的关系。它用于将另一个表(或查询)的结果映射到一个复杂类型的属性上。

属性说明

  • property:指定映射到哪个Java对象的属性。
  • javaType:指定该属性的Java类型。
  • column:指定数据库中的哪一列用于作为外键。
  • select:指定一个用于加载关联对象的子查询ID。当使用懒加载时,这个属性特别有用。
  • fetchType:可选,指定加载策略(默认为eager,即预加载;也可以设置为lazy,即懒加载)。

示例

<resultMap id="userResultMap" type="User">
    <id property="id" column="id" />
    <result property="username" column="username" />
    <association property="department" javaType="Department" column="department_id" select="getDepartmentById" />
</resultMap>

在这个例子中,User对象有一个Department类型的属性,该属性通过department_iddepartments表关联。当查询User对象时,如果设置了select属性,MyBatis会在需要时执行getDepartmentById查询来加载关联的Department对象。

<collection>

<collection>元素用于处理“一对多”的关系。它用于将多个结果行映射到一个集合或数组上。

属性说明

  • property:指定映射到哪个Java对象的属性(通常是一个集合或数组)。
  • ofType:指定集合或数组中元素的类型。
  • column:指定数据库中的哪一列用于作为外键。
  • foreignColumn:指定关联表中哪一列是外键。
  • select:指定一个用于加载关联对象的子查询ID(同样,在懒加载时有用)。
  • fetchType:可选,指定加载策略(默认为eager,即预加载;也可以设置为lazy,即懒加载)。

示例

<resultMap id="orderResultMap" type="Order">
    <id property="id" column="id" />
    <result property="orderDate" column="order_date" />
    <collection property="orderItems" ofType="OrderItem" column="id" foreignColumn="order_id" select="getOrderItemsByOrderId" />
</resultMap>

在这个例子中,Order对象有一个orderItems集合,它包含了与当前订单关联的多个OrderItem对象。当查询Order对象时,如果设置了select属性,MyBatis会在需要时执行getOrderItemsByOrderId查询来加载关联的OrderItem集合。

注意点:

  1. 性能:懒加载可以减少初始查询的复杂性,但可能会增加后续访问关联对象时的数据库查询次数。预加载(默认行为)可以减少数据库查询次数,但可能会增加初始查询的复杂性和结果集的大小。
  2. 事务:懒加载可能导致跨多个事务边界的问题,特别是当在不同的会话或事务中访问关联对象时。预加载通常更适合在单个事务中处理所有数据。
  3. N+1查询问题:懒加载可能会导致N+1查询问题,即首先执行一个查询来获取N个主对象,然后对每个主对象执行一个额外的查询来获取其关联对象。这可以通过适当的查询优化或预加载来避免。
  4. 配置:确保正确配置MyBatis的懒加载和预加载策略,以避免不必要的性能问题或数据不一致性。