MyBatis 中 Association 和 Collection 的使用方法及区别

一、引言

在 MyBatis 的世界里,当处理数据库中的关联关系时,AssociationCollection是两个非常重要的概念。它们能够帮助我们高效地获取和处理与主实体相关的其他实体信息。无论是一对一(Association)还是一对多(Collection)的关系,正确地使用它们可以让我们的持久层代码更加清晰和高效。

二、Association的使用方法

(一)含义

Association主要用于处理一对一的关联关系。例如,在一个简单的用户系统中,一个用户可能对应一个用户详情(如用户的扩展信息),这种关系就可以通过Association来映射。

(二)XML 配置方式

  1. 基本查询与结果映射
    • 假设我们有User表和UserDetail表,UserDetail表通过user_id外键关联到User表的id
    • 首先,在UserMapper.xml中定义查询语句:

收起

xml

复制

<select id="getUserWithDetailById" resultMap="UserWithDetailResultMap">
    select u.*, ud.*
    from user u
    left join user_detail ud on u.id = ud.user_id
    where u.id = #{id}
</select>

  • 然后,定义resultMap来映射结果:

收起

xml

复制

<resultMap id="UserWithDetailResultMap" type="User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <association property="userDetail" javaType="UserDetail">
        <id property="id" column="user_detail_id"/>
        <result property="address" column="address"/>
    </association>
</resultMap>

  • 在这里,select语句通过left join将两张表的数据一起查询出来。在resultMap中,idresult标签用于映射User表的列到User实体的属性。Association标签用于处理一对一关系,property属性指定了在User实体中关联UserDetail对象的属性名,javaType属性指定了关联对象的类型为UserDetail。在Association内部的idresult标签用于映射UserDetail表的列到UserDetail实体的属性。

  1. 延迟加载(嵌套查询)方式
    • MyBatis 也支持通过嵌套查询来实现关联查询并进行延迟加载。例如:

收起

xml

复制

<resultMap id="UserWithDetailLazyResultMap" type="User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <association property="userDetail" javaType="UserDetail"
                 select="com.example.dao.UserDetailMapper.getUserDetailById"
                 column="id">
    </association>
</resultMap>

  • 在这个resultMap中,Association标签的select属性指定了一个查询UserDetail对象的方法(在UserDetailMapper.xml中定义),column属性指定了传递给这个查询方法的参数(通常是关联外键的值)。这样,只有当访问User对象中的userDetail属性时,才会执行UserDetailMapper中的查询方法,实现了延迟加载,提高了性能。

(三)注解方式

  1. 示例代码
    • 假设我们使用 MyBatis 的注解方式来处理一对一关系。

收起

java

复制

public interface UserMapper {
    @Select("select * from user where id = #{id}")
    @Results({
        @Result(id = true, property = "id", column = "id"),
        @Result(property = "username", column = "username"),
        @Result(property = "userDetail", javaType = UserDetail.class,
                one = @One(select = "com.example.dao.UserDetailMapper.getUserDetailById"),
                column = "id")
    })
    User getUserWithDetailById(int id);
}

  • 在这个示例中,@Results注解用于定义结果集映射。@Result注解中的property指定实体类中的属性名,column指定数据库表中的列名。对于关联关系部分,one = @One(select = "com.example.dao.UserDetailMapper.getUserDetailById")表示这是一个一对一的关联查询,select属性指定了查询关联对象的方法,column属性指定了传递给该方法的参数,和 XML 配置中的延迟加载方式类似,实现了关联对象的查询。

三、Collection的使用方法

(一)含义

Collection用于处理一对多的关联关系。例如,一个用户可能有多个订单,这种用户和订单之间的一对多关系就可以通过Collection来映射。

(二)XML 配置方式

  1. 基本查询与结果映射
    • 假设我们有User表和Order表,Order表通过user_id外键关联到User表的id
    • 首先,在UserMapper.xml中定义查询语句:

收起

xml

复制

<select id="getUserWithOrdersById" resultMap="UserWithOrdersResultMap">
    select u.*, o.*
    from user u
    left join orders o on u.id = o.user_id
    where u.id = #{id}
</select>

  • 然后,定义resultMap

收起

xml

复制

<resultMap id="UserWithOrdersResultMap" type="User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <collection property="orders" ofType="Order">
        <id property="id" column="order_id"/>
        <result property="orderNumber" column="order_number"/>
    </collection>
</resultMap>

  • 在这里,select语句通过left join将用户和订单的数据一起查询出来。在resultMap中,idresult标签用于映射User表的列到User实体的属性。Collection标签用于处理一对多关系,property属性指定了在User实体中关联订单集合的属性名(假设User类中有一个List<Order>类型的属性叫orders),ofType属性指定了集合中元素的类型为Order。在Collection内部的idresult标签用于映射Order表的列到Order实体的属性。

  1. 延迟加载(嵌套查询)方式
    • 同样可以使用嵌套查询实现延迟加载。例如:

收起

xml

复制

<resultMap id="UserWithOrdersLazyResultMap" type="User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <collection property="orders" ofType="Order"
                 select="com.example.dao.OrderMapper.getOrdersByUserId"
                 column="id">
    </collection>
</resultMap>

  • 在这个resultMap中,Collection标签的select属性指定了一个查询订单集合的方法(在OrderMapper.xml中定义),column属性指定了传递给这个查询方法的参数(通常是关联外键的值)。只有当访问User对象中的orders属性时,才会执行OrderMapper中的查询方法,实现了延迟加载。

(三)注解方式

  1. 示例代码
    • 假设我们使用注解方式来处理一对多关系。

收起

java

复制

public interface UserMapper {
    @Select("select * from user where id = #{id}")
    @Results({
        @Result(id = true, property = "id", column = "id"),
        @Result(property = "username" column = "username"),
        @Result(property = "orders", javaType = ArrayList.class, ofType = Order.class,
                many = @Many(select = "com.example.dao.OrderMapper.getOrdersByUserId"),
                column = "id")
    })
    User getUserWithOrdersById(int id);
}

  • 在这个示例中,@Results注解用于定义结果集映射。@Result注解中的property指定实体类中的属性名,column指定数据库表中的列名。对于关联关系部分,many = @Many(select = "com.example.dao.OrderMapper.getOrdersByUserId")表示这是一个一对多的关联查询,select属性指定了查询关联对象集合的方法,column属性指定了传递给该方法的参数,实现了一对多关联对象的查询和延迟加载(如果配置了的话)。

四、AssociationCollection的区别

(一)关联关系类型

  • Association处理一对一的关联关系,例如一个用户对应一个用户详情。它主要关注的是单个相关对象与主对象的映射。
  • Collection处理一对多的关联关系,比如一个用户对应多个订单。它强调的是主对象与一组相关对象(通常是一个集合)的映射。

(二)配置细节

  • 在 XML 配置的resultMap中:
    • Association使用javaType属性来指定关联对象的类型,因为它是一对一的关系,只涉及一个对象类型。
    • Collection使用ofType属性来指定集合中元素的类型,因为它是一对多的关系,需要明确集合内元素的类型。
  • 在注解方式中:
    • Association使用one = @One来表示一对一关联查询。
    • Collection使用many = @Many来表示一对多关联查询。

(三)数据结构

  • Association在实体类中对应的属性通常是一个单一对象,例如User类中的UserDetail userDetail
  • Collection在实体类中对应的属性是一个集合,例如User类中的List<Order> orders

希望这篇文章能够帮助你更好地理解和使用 MyBatis 中的AssociationCollection,在实际的开发中能够根据具体的关联关系类型灵活地选择和应用它们。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值