Mybatis 级联查询

MyBatis 的级联查询(Cascade Query)是指在一个查询中,通过关联多个表,将查询结果映射到包含嵌套对象的复杂数据结构中。MyBatis 提供了强大的级联查询支持,可以通过 resultMapassociationcollection 等标签来实现。

下面我们详细讲解 MyBatis 中级联查询的使用方法。


1. 一对一关联(association

一对一关联是指一个对象中包含另一个对象的引用。例如,一个 User 对象中包含一个 Address 对象。

实体类

public class User {
    private int id;
    private String name;
    private int age;
    private Address address; // 一对一关联
    // getters and setters
}

public class Address {
    private String city;
    private String street;
    // getters and setters
}

Mapper 接口

public interface UserMapper {
    User selectUserWithAddressById(int id);
}

Mapper XML 文件

<resultMap id="UserResultMap" type="User">
    <id property="id" column="id" />
    <result property="name" column="name" />
    <result property="age" column="age" />
    <!-- 一对一关联 -->
    <association property="address" javaType="Address">
        <result property="city" column="city" />
        <result property="street" column="street" />
    </association>
</resultMap>

<select id="selectUserWithAddressById" resultMap="UserResultMap">
    SELECT u.id, u.name, u.age, a.city, a.street
    FROM user u
    LEFT JOIN address a ON u.id = a.user_id
    WHERE u.id = #{id}
</select>
  • association:用于映射一对一关联。
  • property="address":表示 User 对象中的 address 属性。
  • javaType="Address":表示 address 属性的类型是 Address
  • 查询结果中的 citystreet 列会映射到 Address 对象的属性中。

2. 一对多关联(collection

一对多关联是指一个对象中包含另一个对象的集合。例如,一个 User 对象中包含多个 Order 对象。

实体类

public class User {
    private int id;
    private String name;
    private int age;
    private List<Order> orders; // 一对多关联
    // getters and setters
}

public class Order {
    private int id;
    private String orderNo;
    private double amount;
    // getters and setters
}

Mapper 接口

public interface UserMapper {
    User selectUserWithOrdersById(int id);
}

Mapper XML 文件

<resultMap id="UserWithOrdersResultMap" type="User">
    <id property="id" column="id" />
    <result property="name" column="name" />
    <result property="age" column="age" />
    <!-- 一对多关联 -->
    <collection property="orders" ofType="Order">
        <id property="id" column="order_id" />
        <result property="orderNo" column="order_no" />
        <result property="amount" column="amount" />
    </collection>
</resultMap>

<select id="selectUserWithOrdersById" resultMap="UserWithOrdersResultMap">
    SELECT u.id, u.name, u.age, o.id AS order_id, o.order_no, o.amount
    FROM user u
    LEFT JOIN orders o ON u.id = o.user_id
    WHERE u.id = #{id}
</select>
  • collection:用于映射一对多关联。
  • property="orders":表示 User 对象中的 orders 属性。
  • ofType="Order":表示 orders 集合中的元素类型是 Order
  • 查询结果中的 order_idorder_noamount 列会映射到 Order 对象的属性中,并添加到 orders 集合中。

3. 多级嵌套关联

多级嵌套关联是指一个对象中包含另一个对象,而另一个对象又包含其他对象。例如,一个 User 对象中包含 Address 对象,而 Address 对象又包含 Country 对象。

实体类

public class User {
    private int id;
    private String name;
    private int age;
    private Address address; // 一对一关联
    // getters and setters
}

public class Address {
    private String city;
    private String street;
    private Country country; // 一对一关联
    // getters and setters
}

public class Country {
    private String name;
    private String code;
    // getters and setters
}

Mapper 接口

public interface UserMapper {
    User selectUserWithAddressAndCountryById(int id);
}

Mapper XML 文件

<resultMap id="UserWithAddressAndCountryResultMap" type="User">
    <id property="id" column="id" />
    <result property="name" column="name" />
    <result property="age" column="age" />
    <!-- 一对一关联 -->
    <association property="address" javaType="Address">
        <result property="city" column="city" />
        <result property="street" column="street" />
        <!-- 嵌套一对一关联 -->
        <association property="country" javaType="Country">
            <result property="name" column="country_name" />
            <result property="code" column="country_code" />
        </association>
    </association>
</resultMap>

<select id="selectUserWithAddressAndCountryById" resultMap="UserWithAddressAndCountryResultMap">
    SELECT u.id, u.name, u.age, a.city, a.street, c.name AS country_name, c.code AS country_code
    FROM user u
    LEFT JOIN address a ON u.id = a.user_id
    LEFT JOIN country c ON a.country_id = c.id
    WHERE u.id = #{id}
</select>
  • 多级嵌套关联通过嵌套的 association 实现。
  • 查询结果中的 country_namecountry_code 列会映射到 Country 对象的属性中。

4. 延迟加载(Lazy Loading)

当级联查询的嵌套对象较多时,可以使用延迟加载来优化性能。延迟加载是指在需要时才加载嵌套对象的数据。

配置延迟加载

在 MyBatis 配置文件中启用延迟加载:

<settings>
    <setting name="lazyLoadingEnabled" value="true" />
    <setting name="aggressiveLazyLoading" value="false" />
</settings>

使用延迟加载

associationcollection 标签中设置 fetchType="lazy"

<resultMap id="UserWithOrdersResultMap" type="User">
    <id property="id" column="id" />
    <result property="name" column="name" />
    <result property="age" column="age" />
    <!-- 延迟加载 orders -->
    <collection property="orders" ofType="Order" fetchType="lazy">
        <id property="id" column="order_id" />
        <result property="orderNo" column="order_no" />
        <result property="amount" column="amount" />
    </collection>
</resultMap>
  • fetchType="lazy":表示延迟加载 orders 集合。
  • 只有在访问 user.getOrders() 时,才会执行加载 orders 的查询。

总结

  • 一对一关联:使用 association 标签。
  • 一对多关联:使用 collection 标签。
  • 多级嵌套关联:通过嵌套的 associationcollection 实现。
  • 延迟加载:通过配置 fetchType="lazy" 实现,优化性能。

通过合理使用级联查询,可以轻松处理复杂的对象关系映射,并提高查询效率。

要是想图省事儿,这样也可以,1对多性能不好,每一条主表数据都会再通过一条sql查询子表数据

<resultMap id="one2manyMap" type="com.study.mybatis.dto.ItemWithSku">
    <id column="id" property="id" jdbcType="BIGINT"/>
    <result column="code" property="code" jdbcType="VARCHAR"/>
    <result column="name" property="name" jdbcType="VARCHAR"/>
    <collection property="skus"
                column="id"
                javaType="ArrayList"
                ofType="com.study.mybatis.dto.ItemWithSku$Sku"
                select="getSkusByItemId"
    />
</resultMap>
<!-- 先查主表,以主表分页就不会有分页问题 -->
<select id="findItemAndSku" resultMap="one2manyMap">
    select a.id, a.code, a.name from t_item a
</select>
<!-- 再根据主表查询子表 -->
<select id="getSkusByItemId" resultType="com.study.mybatis.dto.ItemWithSku$Sku">
    select a.id, a.code, a.name from t_sku a where a.item_id = #{id}
</select>
posted @   CyrusHuang  阅读(49)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示