mybatis-一对多分页查询

  • 问题
    在用mybatis做一对多查询时候,常用collection配合完成结果查询。在不涉及分页查询情况下,查询结果是没有问题的。但当涉及分页查询时,就会出现问题,即结果总数量total多于实际数量。

  • 演示示例如下

  • 实体类

@Data
public class JudgePicPointSatatusResVo {
    private Integer id;
    private String judgePicPoint;
    private String productNum;
    private String judgePicStation;
    private String stationName;
    private List<String> stationNameList;
    private Integer status;
}
  • Dao层
List<JudgePicPointSatatusResVo> getJudgePicPointListByJudgePicStationId(JudgePicPointSatatusReqVo judgePicPointSatatusReqVo);
  • 查询
    <resultMap id="judgePicPointListMap" type="com.qxmz.vo.judgePic.JudgePicPointSatatusResVo">
        <id column="id" property="id"/>
        <result column="judgePicPoint" property="judgePicPoint"/>
        <result column="productNum" property="productNum"/>
        <result column="judgePicStation" property="judgePicStation"/>
        <result column="status" property="status"/>
        <collection property="stationNameList" ofType="String">
            <id column="stationName"/>
        </collection>
    </resultMap>
    <select id="getJudgePicPointListByJudgePicStationId" parameterType="com.qxmz.vo.judgePic.JudgePicPointSatatusReqVo"
            resultMap="judgePicPointListMap">
        SELECT cj.`id`,cj.`productNum`,cj.`status`, jpp.`name` judgePicPoint,jps.`name`
        judgePicStation,st.station_name stationName FROM client_judgePicPoint cj
        LEFT JOIN judge_pic_point jpp ON cj.`judgePicPointId`=jpp.`id`
        LEFT JOIN judge_pic_station jps ON jpp.`judgePicStationId`=jps.`id`
        LEFT JOIN station st ON jps.`id`=st.`judgePicStationId`
        <where>
            cj.isAdd=1
            <if test="judgePicStationIdList!=null">
                and jps.id in
                <foreach item="judgePicStationId" collection="judgePicStationIdList" open="(" separator="," close=")">
                    #{judgePicStationId}
                </foreach>
            </if>
            <if test="status != null and status != 0">
                and cj.status = #{status}
            </if>
        </where>
    </select>
  • 结果
{
    "code": 200,
    "message": "success",
    "data": {
        "total": 2,
        "rows": [
            {
                "id": 2,
                "judgePicPoint": "判图点3",
                "productNum": "002",
                "judgePicStation": "判图站B",
                "stationName": "郑州西站、南阳寨站",
                "stationNameList": [
                    "郑州西站",
                    "南阳寨站"
                ],
                "status": 2
            }
        ]
    }
}

从结果中可以看到,实际只查询出来一条数据,但总数却是2。这就是一对多分页查询会出现的问题。原因也很简单,以上面数据为例。在mysql客户端执行一对多SQL命令时,结果就是两条。一对多情况下,mybatis会自动将结果装备到collection中,但是在分页情况下,mybatis会认为查询的两台数据就是总的数据。

  • 解决方法
    采用父子查询来实现,具体代码如下:
  • 父查询
    <resultMap id="judgePicPointListMap" type="com.qxmz.vo.judgePic.JudgePicPointSatatusResVo">
        <id column="id" property="id"/>
        <result column="judgePicPoint" property="judgePicPoint"/>
        <result column="productNum" property="productNum"/>
        <result column="judgePicStation" property="judgePicStation"/>
        <result column="status" property="status"/>
        <collection property="stationNameList" ofType="String" column="judgePicStationId"
                    select="selectStationNameByJudgePicStationId">
        </collection>
    </resultMap>
    <select id="getJudgePicPointListByJudgePicStationId" parameterType="com.qxmz.vo.judgePic.JudgePicPointSatatusReqVo"
            resultMap="judgePicPointListMap">
        SELECT cj.`id`,cj.`productNum`,cj.`status`, jpp.`name` judgePicPoint,jps.`name`
        judgePicStation,jps.id judgePicStationId FROM client_judgePicPoint cj
        LEFT JOIN judge_pic_point jpp ON cj.`judgePicPointId`=jpp.`id`
        LEFT JOIN judge_pic_station jps ON jpp.`judgePicStationId`=jps.`id`
        <where>
            cj.isAdd=1
            <if test="judgePicStationIdList!=null">
                and jps.id in
                <foreach item="judgePicStationId" collection="judgePicStationIdList" open="(" separator="," close=")">
                    #{judgePicStationId}
                </foreach>
            </if>
            <if test="status != null and status != 0">
                and cj.status = #{status}
            </if>
        </where>
    </select>
  • 子查询
<select id="selectStationNameByJudgePicStationId" resultType="String">
        SELECT  station_name FROM station WHERE judgePicStationId=#{judgePicStationId}
    </select>
  • 正确结果
{
    "code": 200,
    "message": "success",
    "data": {
        "total": 1,
        "rows": [
            {
                "id": 2,
                "judgePicPoint": "判图点3",
                "productNum": "002",
                "judgePicStation": "判图站B",
                "stationName": "郑州西站、南阳寨站",
                "stationNameList": [
                    "郑州西站",
                    "南阳寨站"
                ],
                "status": 2
            }
        ]
    }
}
  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
假设我们有两个实体类`User`和`Order`,它们之间是一对多的关系,即一个用户可以有多个订单。我们需要实现一个连表分页查询的功能,可以按照用户的某个字段进行排序。 1. 首先在`pom.xml`文件中添加Mybatis-Plus和MySql的依赖: ```xml <!-- Mybatis-Plus依赖 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> <!-- MySql驱动依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> ``` 2. 创建两个实体类`User`和`Order`,并在`User`类中添加`@TableId`注解: ```java @Data public class User { @TableId(type = IdType.AUTO) private Long id; private String name; private Integer age; private String email; } @Data public class Order { private Long id; private Long userId; private String orderNo; private BigDecimal amount; } ``` 3. 创建`UserMapper`和`OrderMapper`接口,并继承`BaseMapper`接口: ```java public interface UserMapper extends BaseMapper<User> { } public interface OrderMapper extends BaseMapper<Order> { } ``` 4. 创建`UserAndOrderVO`类,用于封装查询结果: ```java @Data public class UserAndOrderVO { private Long userId; private String userName; private Integer userAge; private String userEmail; private Long orderId; private String orderNo; private BigDecimal orderAmount; } ``` 5. 创建`UserAndOrderMapper`接口,用于实现连表分页查询: ```java public interface UserAndOrderMapper extends BaseMapper<UserAndOrderVO> { List<UserAndOrderVO> selectUserAndOrderPage(IPage<UserAndOrderVO> page, @Param("orderByField") String orderByField, @Param("userId") Long userId); } ``` 6. 在`UserAndOrderMapper.xml`中实现具体的查询逻辑: ```xml <select id="selectUserAndOrderPage" resultMap="UserAndOrderVO"> SELECT u.id AS userId, u.name AS userName, u.age AS userAge, u.email AS userEmail, o.id AS orderId, o.order_no AS orderNo, o.amount AS orderAmount FROM user u INNER JOIN `order` o ON u.id = o.user_id <if test="userId != null"> WHERE u.id = #{userId} </if> ORDER BY ${orderByField} DESC </select> ``` 7. 在业务逻辑中调用`UserAndOrderMapper`接口中的方法,实现分页查询: ```java @Service public class UserAndOrderService { @Autowired private UserAndOrderMapper userAndOrderMapper; public IPage<UserAndOrderVO> selectUserAndOrderPage(Page<UserAndOrderVO> page, String orderByField, Long userId) { return userAndOrderMapper.selectUserAndOrderPage(page, orderByField, userId); } } ``` 以上就是使用Mybatis-Plus实现连表分页查询的全部代码。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值