mybatis一对多及分页可能存在的问题即关联查询分页问题,嵌套的list中数量对不上

本文探讨了在一对多关系的数据库查询中,如何解决SQL查询结果与Java映射对象数量不一致的问题。通过子查询优化,确保了回复数量正确反映在Java集合中,避免了因使用LIMIT导致的数据不一致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目中遇到了一个小问题,在此记录下,方便以后代码复用并且能快速排查这个小问题。

需求如下:评论和回复是一对多的关系,并且根据评论进行分页查询,至于回复数量不做限制,有多少就查多少。

存在问题:由于两张表是用连接查询,所以对于同一条评论存在多条回复的情况,那么用sql查询出来的数量应该是由回复数量决定的。而映射到java集中的数量却是由评论来决定,多条回复只是作为评论的一个属性而已。所以在mysql中直接使用limit可能会造成sql和java两边的数据不一致。

其中的column是sql中查询字段,property是javaBean属性字段。replyList就是评论中回复列表字段,是一个集合。

 

亲测子查询有效

select column_name,(select count(distinct ticket.id) from mac_ticket ticket where ticket.ticket_type_cd=mtt.code)totalTicket,(select count (case when ticket.customer_cd is not null or ticket.out_customer_cd is not null then ticket.id end)from mac_ticket ticket where ticket.ticket_type_cd=mtt.code)receiveSum,(select count (case when ticket.activity_id is not null  then ticket.id end)from mac_ticket ticket where ticket.ticket_type_cd=mtt.code)publishSum,(select count (case when ticket.verification=1  then ticket.id end)from mac_ticket ticket where ticket.ticket_type_cd=mtt.code)receiveSum,(select ifnull (sum(ifnull(mtg.quantity,0)),0)from mac_ticket_group mtg where mtg.ticket_type_cd=mtt.code)preLockSum from  mac_ticket_type mtt left mac_ticket_type_service  mtts on mtt.code=mtts.ticket_type_cd where mtt.delete_flag=0 <include refid="findBySelective"/>

<if test="pageBean != null and pageBean.offset != null">

and mtt.code in(select temp.code from (

select code from mac_ticket_type mtt where mtt.delete_flag=0

<include refid="findBySelective"/>

limit #{pageBean.offset},#{pageBean.size} )

as temp)

</if>

总结:

1. in不能和limit在一个语句中使用,否则报错

This version of Mysql dose't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'应加临时表查询;

2. 临时表查询时和主查询的条件要一样,,否则查询出数据不对;

3. 条件中有foreach的item的名称不要和collection的名称一样,否则报错:

Error evaluating expression 'orgCds'.Return value was ont iterable.

 

<foreach collection="array" item="id" index="index" open="(" close=")" separator=",">

#{id,jdbcType=VARCHAR}

</foreach>

4.统计数时候count是单个的,可以在结果部分select count(*)from table,这样会很慢

5.ifnull可以去掉查出来的结果为null

MyBatis支持一对分页查询,可以通过嵌套查询实现。以下是一个示例,假设我们有两个表:`orders`和`order_items`,一个订单可以对应个订单项。 ```xml <!-- 定义订单查询SQL --> <select id="getOrders" resultMap="orderResultMap"> select * from orders where user_id = #{userId} </select> <!-- 定义订单项查询SQL --> <select id="getOrderItems" resultMap="orderItemResultMap"> select * from order_items where order_id in <foreach item="orderId" collection="orderIds" open="(" separator="," close=")"> #{orderId} </foreach> </select> <!-- 定义查询订单及其订单项的SQL --> <select id="getOrdersWithItems" resultMap="orderResultMap"> <!-- 分页查询订单 --> select * from orders where user_id = #{userId} limit #{offset}, #{limit} <!-- 查询订单对应的订单项 --> <foreach item="order" collection="orders" open="" close="" separator=""> <bind name="orderIds" value=""/> <foreach item="item" collection="order.items" open="" close="" separator=""> <if test="_databaseId == 'mysql'"> <bind name="orderIds" value="${orderIds + ',' + item.id}"/> </if> <if test="_databaseId == 'postgresql'"> <bind name="orderIds" value="#{orderIds,javaType=java.util.List,jdbcType=ARRAY,mode=OUT}(#{item.id})"/> </if> </foreach> <if test="order.items != null and order.items.size() > 0"> <!-- 分页查询订单项 --> <include refid="getOrderItems"/> </if> </foreach> </select> <!-- 定义订单项映射 --> <resultMap id="orderItemResultMap" type="OrderItem"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="price" column="price"/> </resultMap> <!-- 定义订单映射 --> <resultMap id="orderResultMap" type="Order"> <id property="id" column="id"/> <result property="userId" column="user_id"/> <result property="totalPrice" column="total_price"/> <collection property="items" ofType="OrderItem"> <result property="id" column="id"/> <result property="name" column="name"/> <result property="price" column="price"/> </collection> </resultMap> ``` 在上面的示例中,`getOrdersWithItems`是我们要执行的查询,它首先查询订单表,然后对每个订单查询对应的订单项。我们使用`foreach`标签来遍历订单列表,对于每个订单,我们将其对应的订单项的`id`拼接成一个字符串,然后传递给`getOrderItems`查询语句中的`in`条件。注意,为了支持不同的数据库,我们使用了不同的语法来传递`in`条件,MySQL使用`${}`,PostgreSQL使用`#{}`。同时,我们在`if`标签中判断订单是否有对应的订单项,如果没有,则不执行查询。 另外,为了支持分页查询,我们使用了`limit`和`offset`参数。`limit`表示每页查询少条记录,`offset`表示从第几条记录开始查询。这些参数可以通过`PageHelper`等分页插件来设置。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值