PageHelper一对多查询分页问题
在一个项目中,用到了PageHelper作为分页工具,正常使用没有问题,但是当碰到一对多联合查询分页的时候,查询语句用到了join,PageHelper就出现了问题,导致分页不准确,在网上查阅资料后,发现利用Mybatis中的嵌套子查询可以解决这个问题
一、实体类
需要用到一对多查询的实体
Task.java
/**
* @Auther: kiritoghy
* @Date: 19-7-26 上午9:17
*/
public class Task {
private Long taskId;
private String taskName;
private String taskDesc;
private int imageNumber;
private int taskType;
private List<Long> userIds;
private List<Long> reviewerIds;
private List<Long> labelIds;
private List<UserInfo> users;
private List<String> reviewers;
private int finish;
}
其中userIds,reviewerIds,labelIds等List需要用到一对多查询
二、Mapper
1. 建立resultMap
<resultMap id="BaseResultMap" type="com.uestc.labelproject.entity.Task">
<id column="task_id" jdbcType="BIGINT" property="taskId" />
<result column="task_name" jdbcType="VARCHAR" property="taskName" />
<result column="task_desc" jdbcType="VARCHAR" property="taskDesc" />
<result column="image_number" jdbcType="INTEGER" property="imageNumber"/>
<result column="task_type" jdbcType="INTEGER" property="taskType"/>
<result column="finish" jdbcType="INTEGER" property="finish"/>
<collection property="userIds" ofType="Long" select="selectUserId" column="task_id">
<result column="user_id" jdbcType="BIGINT"/>
</collection>
<collection property="labelIds" ofType="Long" select="selectLabelId" column="task_id">
<result column="label_id" jdbcType="BIGINT"/>
</collection>
<collection property="reviewerIds" ofType="Long" select="selectReviewerId" column="task_id">
<result column="reviewer_id" jdbcType="BIGINT"/>
</collection>
</resultMap>
基本的resultMap格式都不变,一对多的查询就是加入collection,有点区别的就是其中的参数加入了select="",这个便是子查询
2. 主查询
<select id="getTaskList" resultMap="BaseResultMap">
select t.task_id,
t.task_name,
t.image_number,
t.task_type,
(select count(*) from image i where i.task_id = t.task_id and i.user_confirm_id is not null) finish,
t.task_desc
from task t where t.is_created = 1
</select>
3. 子查询
<select id="selectUserId" parameterType="Long" resultType="Long">
select user_id from taskuserinfo where task_id = #{task_id}
</select>
<select id="selectLabelId" parameterType="Long" resultType="Long">
select label_id from tasklabelinfo where task_id = #{task_id}
</select>
<select id="selectReviewerId" parameterType="Long" resultType="Long">
select reviewer_id from taskreviewerinfo where task_id = #{task_id}
</select>
三、Controller
现在就可以直接使用PageHelper来进行分页
就是最基本的用法
PageHelper.startPage(page,limit);
List<Task> tasks = adminTaskService.getTaskList();
这样就可以成功分页
四、其他一些问题
这样带来的问题就是1+N的问题,即
例如1次select查询到N个Task后,对于查询到的每个Task,又会进行一次select子查询,因此一共是1+N次,造成性能消耗极大,因此可以在项目配置中对Mybatis使用懒加载
lazyLoadingEnabled=true
这样当在需要用到该子查询的数据时,才会进行子查询,在一定程度上缓解1+N带来的性能问题
当然也还有其他解决办法,例如使用Spring Data Jpa,但是当时项目已经开发到后期,再换持久层的框架成本较大,再者此项目的数据量并不大,只有少量一对多的查询需要分页,然后用到子查询,其余一对多的查询可以直接使用join,因此还是继续使用Mybatis
Comments | 1 条评论