Mapper中多表的嵌套组合查询

76 阅读4分钟

Mapper中多表的嵌套组合查询

<!--手动映射封装,实现多表的嵌套组合查询-->
<resultMap id="NodeVoResult" type="NodeVo">
    <result property="id"    column="id"    />
    <result property="nodeName"    column="node_name"    />
    <result property="address"    column="address"    />
    <result property="businessType"    column="business_type"    />
    <result property="regionId"    column="region_id"    />
    <result property="partnerId"    column="partner_id"    />
    <result property="createTime"    column="create_time"    />
    <result property="updateTime"    column="update_time"    />
    <result property="createBy"    column="create_by"    />
    <result property="updateBy"    column="update_by"    />
    <result property="remark"    column="remark"    />
    <result property="vmCount"    column="vm_count"    />
    <!--嵌套查询
    property="region" 映射的属性名
    javaType="Region" 属性名的类型,java的类型
    column="region_id" 映射的列名,从上面拿到的值
    select="" 嵌套查询的sql,调用对应的查询方法-->
    <association property="region" javaType="Region" column="region_id" select="com.dkd.manage.mapper.RegionMapper.selectRegionById" />
    <association property="partner" javaType="Partner" column="partner_id" select="com.dkd.manage.mapper.PartnerMapper.selectPartnerById" />
</resultMap>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dkd.manage.mapper.NodeMapper">
    <!--手动映射封装,实现多表的嵌套组合查询-->
    <resultMap id="NodeVoResult" type="NodeVo">
        <result property="id"    column="id"    />
        <result property="nodeName"    column="node_name"    />
        <result property="address"    column="address"    />
        <result property="businessType"    column="business_type"    />
        <result property="regionId"    column="region_id"    />
        <result property="partnerId"    column="partner_id"    />
        <result property="createTime"    column="create_time"    />
        <result property="updateTime"    column="update_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateBy"    column="update_by"    />
        <result property="remark"    column="remark"    />
        <result property="vmCount"    column="vm_count"    />
        <!--嵌套查询
        property="region" 映射的属性名
        javaType="Region" 属性名的类型,java的类型
        column="region_id" 映射的列名,从上面拿到的值
        select="" 嵌套查询的sql,调用对应的查询方法-->
        <association property="region" javaType="Region" column="region_id" select="com.dkd.manage.mapper.RegionMapper.selectRegionById" />
        <association property="partner" javaType="Partner" column="partner_id" select="com.dkd.manage.mapper.PartnerMapper.selectPartnerById" />
    </resultMap>
    <resultMap type="Node" id="NodeResult">
        <result property="id"    column="id"    />
        <result property="nodeName"    column="node_name"    />
        <result property="address"    column="address"    />
        <result property="businessType"    column="business_type"    />
        <result property="regionId"    column="region_id"    />
        <result property="partnerId"    column="partner_id"    />
        <result property="createTime"    column="create_time"    />
        <result property="updateTime"    column="update_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateBy"    column="update_by"    />
        <result property="remark"    column="remark"    />
    </resultMap>

    <sql id="selectNodeVo">
        select id, node_name, address, business_type, region_id, partner_id, create_time, update_time, create_by, update_by, remark from tb_node
    </sql>

    <select id="selectNodeList" parameterType="Node" resultMap="NodeResult">
        <include refid="selectNodeVo"/>
        <where>  
            <if test="nodeName != null  and nodeName != ''"> and node_name like concat('%', #{nodeName}, '%')</if>
            <if test="regionId != null "> and region_id = #{regionId}</if>
            <if test="partnerId != null "> and partner_id = #{partnerId}</if>
        </where>
    </select>
    
    <select id="selectNodeById" parameterType="Long" resultMap="NodeResult">
        <include refid="selectNodeVo"/>
        where id = #{id}
    </select>
    <select id="selectNodeVoList" resultMap="NodeVoResult">
        SELECT n.*, COUNT(vm.node_id) AS vm_count
        FROM tb_node n
                 LEFT JOIN tb_vending_machine vm ON n.id = vm.node_id
        <where>
            <if test="nodeName != null  and nodeName != ''"> and n.node_name like concat('%', #{nodeName}, '%')</if>
            <if test="regionId != null "> and n.region_id = #{regionId}</if>
            <if test="partnerId != null "> and n.partner_id = #{partnerId}</if>
        </where>
        GROUP BY n.id
    </select>

    <insert id="insertNode" parameterType="Node" useGeneratedKeys="true" keyProperty="id">
        insert into tb_node
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="nodeName != null and nodeName != ''">node_name,</if>
            <if test="address != null and address != ''">address,</if>
            <if test="businessType != null">business_type,</if>
            <if test="regionId != null">region_id,</if>
            <if test="partnerId != null">partner_id,</if>
            <if test="createTime != null">create_time,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="updateBy != null">update_by,</if>
            <if test="remark != null">remark,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="nodeName != null and nodeName != ''">#{nodeName},</if>
            <if test="address != null and address != ''">#{address},</if>
            <if test="businessType != null">#{businessType},</if>
            <if test="regionId != null">#{regionId},</if>
            <if test="partnerId != null">#{partnerId},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="updateBy != null">#{updateBy},</if>
            <if test="remark != null">#{remark},</if>
         </trim>
    </insert>

    <update id="updateNode" parameterType="Node">
        update tb_node
        <trim prefix="SET" suffixOverrides=",">
            <if test="nodeName != null and nodeName != ''">node_name = #{nodeName},</if>
            <if test="address != null and address != ''">address = #{address},</if>
            <if test="businessType != null">business_type = #{businessType},</if>
            <if test="regionId != null">region_id = #{regionId},</if>
            <if test="partnerId != null">partner_id = #{partnerId},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
            <if test="remark != null">remark = #{remark},</if>
        </trim>
        where id = #{id}
    </update>

    <delete id="deleteNodeById" parameterType="Long">
        delete from tb_node where id = #{id}
    </delete>

    <delete id="deleteNodeByIds" parameterType="String">
        delete from tb_node where id in 
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>
</mapper>

实例记录

在 LyPositionClockAddress 中增加嵌套查询,通过 clock_range_id 查询 LyPositionClockRange 的数据

实体类1

package com.ruoyi.positionClock.domain;

        import com.ruoyi.common.core.domain.BaseCrmEntity;
        import lombok.Data;
        import lombok.Getter;
        import lombok.Setter;
        import org.apache.commons.lang3.builder.ToStringBuilder;
        import org.apache.commons.lang3.builder.ToStringStyle;
        import com.ruoyi.common.annotation.Excel;
        import com.ruoyi.common.core.domain.BaseEntity;

        import java.util.List;

        /**
        * 打卡地址对象 ly_position_clock_address
        *
        * @author wuJiaWei
        * @date 2024-12-04
        */
        @Data
        public class LyPositionClockAddress extends BaseCrmEntity
        {
        private static final long serialVersionUID = 1L;

        /** 打卡地址表 */
        private Long id;

        /** 打卡策略表id */
        private Long clockStrategyId;

        /** 用工方id */
        private Long customerId;

        /** 自定义地址名称 */
        private String addressName;

        /** 简略地址 */
        private String briefAddress;

        /** 详细地址 */
        private String detailedAddress;

        /** 纬度 */
        private String latitude;

        /** 经度 */
        private String longitude;

        /** 打卡范围id */
        private Integer clockRangeId;

        /** 状态 */
        private Integer status;

        /** 假删除 */
        private Integer isDel;
    }

实体类2

package com.ruoyi.positionClock.domain;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;

/**
* 打卡地址对象 ly_position_clock_address
*
* @author wuJiaWei
* @date 2024-12-04
*/
@Data
public class LyPositionClockRange implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ApiModelProperty(value = "主键", name = "id")
@JsonProperty("clockRangeId") // 设置JSON序列化时使用的字段名
private Long id;

/**
* 打卡范围名称
*/
@ApiModelProperty(value = "打卡范围名称", name = "rangeName")
private String rangeName;

/**
* 打卡范围
*/
@ApiModelProperty(value = "打卡范围", name = "rangeValue")
private Integer rangeValue;

}

Mapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.positionClock.mapper.LyPositionClockAddressMapper">

    <resultMap type="LyPositionClockAddress" id="LyPositionClockAddressResult">
        <result property="id"    column="id"    />
        <result property="clockStrategyId"    column="clock_strategy_id"    />
        <result property="customerId"    column="customer_id"    />
        <result property="addressName"    column="address_name"    />
        <result property="briefAddress"    column="brief_address"    />
        <result property="detailedAddress"    column="detailed_address"    />
        <result property="latitude"    column="latitude"    />
        <result property="longitude"    column="longitude"    />
        <result property="clockRangeId"    column="clock_range_id"    />
        <result property="status"    column="status"    />
        <result property="isDel"    column="is_del"    />
        <result property="createTime"    column="create_time"    />
        <result property="updateTime"    column="update_time"    />
    </resultMap>

    <sql id="selectLyPositionClockAddressVo">
        select id, clock_strategy_id, customer_id, address_name, brief_address, detailed_address, latitude, longitude, clock_range_id, status, is_del, create_time, update_time from ly_position_clock_address
    </sql>

    <select id="selectLyPositionClockAddressList" parameterType="LyPositionClockAddress" resultMap="LyPositionClockAddressResult">
        <include refid="selectLyPositionClockAddressVo"/>
        <where>
            <if test="clockStrategyId != null "> and clock_strategy_id = #{clockStrategyId}</if>
        </where>
    </select>
</mapper>

修改实体类

首先,在 LyPositionClockAddress 类中添加一个属性,用于保存关联的 LyPositionClockRange 对象或者对象列表(取决于您的业务逻辑)。

// 如果是单个打卡范围关联,则使用对象 
private LyPositionClockRange lyPositionClockRange; 

// 如果是多个打卡范围关联,则使用列表 
private List<LyPositionClockRange> lyPositionClockRangeList;

修改 MyBatis 映射文件

接下来,你需要在 MyBatis 的映射文件中添加一个新的 <resultMap> 或者修改现有的 LyPositionClockAddressResult 来映射新的关系。这里我们假设每个地址仅对应一个打卡范围,因此我们将使用单个对象而不是列表。

<resultMap type="LyPositionClockAddress" id="LyPositionClockAddressResult">
    <!-- 现有的结果映射 -->

    <!-- 新增关联对象的结果映射 -->
    <association property="lyPositionClockRange" javaType="LyPositionClockRange" select="selectLyPositionClockRangeById" column="clock_range_id"/>
</resultMap>

        <!-- 添加一个新查询,用于根据 clock_range_id 获取 LyPositionClockRange 对象 -->
<select id="selectLyPositionClockRangeById" resultType="LyPositionClockRange" parameterType="Long">
SELECT * FROM ly_position_clock_range WHERE id = #{id}
</select>

如果每个 LyPositionClockAddress 可能与多个 LyPositionClockRange 相关联,你应该使用 <collection> 标签代替 <association> 并调整 javaType 属性为 List<LyPositionClockRange>

更新查询语句

最后,确保所有相关的查询语句都正确地包含了对 clock_range_id 的处理,这样当执行查询时,MyBatis 会自动加载对应的 LyPositionClockRange 数据并将其填充到 LyPositionClockAddress 实例中。

现在,当你调用相应的查询方法时,MyBatis 将执行嵌套查询,并将相关联的 LyPositionClockRange 数据填充到 LyPositionClockAddress 对象中。