MyBatis关联查询的方式


MyBatis是一个优秀的持久层框架,它支持复杂的SQL查询、映射以及高级映射。在处理关联查询时,MyBatis提供了强大的支持,无论是通过XML配置文件还是注解方式。本文将详细介绍如何使用MyBatis处理一对一、一对多和多对多的关联查询,并对比XML配置和注解方式。

一对一关联查询

XML方式

一对一关联查询通常用于查询两个表,且这两个表中的数据通过某个字段一一对应。在MyBatis中,我们可以使用标签来处理一对一的关联映射。

<!-- 查询用户及其详细信息 -->  
<select id="selectUserWithDetail" resultMap="userDetailMap">  
    SELECT u.*, ud.address  
    FROM user u  
    LEFT JOIN user_detail ud ON u.id = ud.user_id  
    WHERE u.id = #{id}  
</select>  
  
<resultMap id="userDetailMap" type="User">  
    <id property="id" column="id" />  
    <result property="name" column="name" />  
    <association property="userDetail" javaType="UserDetail">  
        <result property="address" column="address" />  
    </association>  
</resultMap>

注解方式

在Mapper接口中使用@Results和@Result注解,配合@One注解来表示一对一的关联。

@Select("SELECT u.*, ud.address FROM user u LEFT JOIN user_detail ud ON u.id = ud.user_id WHERE u.id = #{id}")  
@Results({  
    @Result(property = "id", column = "id"),  
    @Result(property = "name", column = "name"),  
    @Result(property = "userDetail", javaType = UserDetail.class, 
            one = @One(select = "selectUserDetailById", fetchType = FetchType.LAZY))  
})  
User selectUserWithDetail(@Param("id") Integer id);  
  
@Select("SELECT address FROM user_detail WHERE user_id = #{id}")  
UserDetail selectUserDetailById(@Param("id") Integer id);

注意:@One注解中的select属性需要指向另一个查询用户详情的Mapper方法,并且fetchType可以控制是否延迟加载。

一对多关联查询

XML方式

一对多关联查询用于查询一个主表记录和多个从表记录的关系。在MyBatis中,使用标签来处理一对多的关联映射。

<!-- 查询用户及其订单列表 -->  
<select id="selectUserWithOrders" resultMap="userOrderMap">  
    SELECT u.*, o.id as "order.id", o.order_no as "order.orderNo"  
    FROM user u  
    LEFT JOIN order o ON u.id = o.user_id  
    WHERE u.id = #{id}  
</select>  
  
<resultMap id="userOrderMap" type="User">  
    <id property="id" column="id" />  
    <result property="name" column="name" />  
    <collection property="orders" ofType="Order">  
        <id property="id" column="order.id" />  
        <result property="orderNo" column="order.orderNo" />  
    </collection>  
</resultMap>

注解方式

在Mapper接口中使用@Results和@Result注解,配合@Many注解来表示一对多的关联。

@Select("SELECT u.*, o.id as 'order.id', o.order_no as 'order.orderNo' FROM user u LEFT JOIN order o ON u.id = o.user_id WHERE u.id = #{id}")  
@Results({  
    @Result(property = "id", column = "id"),  
    @Result(property = "name", column = "name"),  
    @Result(property = "orders", javaType = List.class,  
            many = @Many(select = "selectOrdersByUserId", fetchType = FetchType.LAZY))  
})  
User selectUserWithOrders(@Param("id") Integer id);  
  
@Select("SELECT id, order_no FROM order WHERE user_id = #{id}")  
List<Order> selectOrdersByUserId(@Param("id") Integer id);

多对多关联查询

多对多关联查询通常涉及一个中间表。在MyBatis中,处理多对多关联查询时,可以将它分解为两个一对多关联查询,分别处理两端实体与中间表的关联。

XML方式

<!-- StudentMapper.xml -->  
<mapper namespace="com.example.mapper.StudentMapper">  
  
    <!-- 查询学生及其选修的课程列表 -->  
    <select id="selectStudentWithCourses" resultMap="studentCourseMap">  
        SELECT  
            s.id AS "student.id",  
            s.name AS "student.name",  
            c.id AS "course.id",  
            c.name AS "course.name"  
        FROM  
            student s  
        LEFT JOIN student_course sc ON s.id = sc.student_id  
        LEFT JOIN course c ON sc.course_id = c.id  
        WHERE  
            s.id = #{studentId}  
    </select>  
  
    <resultMap id="studentCourseMap" type="Student">  
        <id property="id" column="student.id"/>  
        <result property="name" column="student.name"/>  
        <collection property="courses" ofType="Course" javaType="list">  
            <id property="id" column="course.id"/>  
            <result property="name" column="course.name"/>  
        </collection>  
    </resultMap>  
  
</mapper>

注解方式

// 假设这是StudentMapper接口的一部分  
@Mapper  
public interface StudentMapper {  
  
    @Select("SELECT id, name FROM student WHERE id = #{studentId}")  
    @Results({  
        @Result(property = "id", column = "id"),  
        @Result(property = "name", column = "name"),  
        @Result(property = "courses", javaType = List.class,  
                many = @Many(select = "selectCoursesByStudentId", fetchType = FetchType.LAZY))  
    })  
    Student selectStudentWithCourses(@Param("studentId") Integer studentId);  
  
    @Select("SELECT id, name FROM course WHERE id IN (SELECT course_id FROM student_course WHERE student_id = #{studentId})")  
    List<Course> selectCoursesByStudentId(@Param("studentId") Integer studentId);  
}

注意事项

  • 性能优化:关联查询可能会涉及大量数据的处理和传输,务必注意SQL语句的优化,合理使用索引。
  • 延迟加载与立即加载:MyBatis支持延迟加载和立即加载,根据实际业务场景选择合适的加载策略。
  • SQL注入风险:无论是使用XML还是注解方式,都需要注意SQL注入的风险,尤其是当动态构建SQL语句时
  • 对于复杂的多对多关联查询,建议使用MyBatis的XML配置方式,因为它提供了更高的灵活性和可读性。注解方式在处理简单查询时很方便,但在处理复杂关联时可能会显得力不从心。在设计查询时,务必考虑查询性能和数据一致性
  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis关联查询是指在查询数据库时,通过配置映射文件,将多个表之间的关联数据查询出来并进行组合。可以使用嵌套结果映射或嵌套查询来处理关联查询。 在嵌套结果映射中,可以使用\<resultMap>来定义映射关系,并使用\<association>来设置关联对象。例如,可以定义一个resultMap来映射Classes和Teacher表之间的关联关系,然后通过联表查询将两个表的数据关联起来。 另一种方式是使用嵌套查询,即在映射文件中通过\<select>标签设置嵌套查询语句来获取关联数据。通过联表查询获取到的数据可以作为嵌套查询的参数,从而获取到关联数据。 以上就是MyBatis关联查询的基本概念和使用方式。可以根据具体的需求选择合适的方式进行关联查询操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SSM框架的学习与应用-Java EE企业级应用开发学习记录(第四天)Mybatis的关联映射和缓存机制](https://download.csdn.net/download/m0_53659738/88253127)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [mybatis关联查询](https://blog.csdn.net/faramita_of_mine/article/details/122202515)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值