前提描述
最近想做一个考试系统,题目和选项是一对多的关系
因为题目后续可能会越来越多,故想引入分页插件pagehelper来减轻查询压力
在做映射时,将选项放到了题目的实体类中
public class Item {
/**试题ID*/
private Integer id;
/**试题类型*/
private Integer itemType;
/**题目内容*/
private String content;
/**配图路径*/
private String image;
/**是否为正确解答,1是2否*/
private int solution;
/**选项*/
private List<Option> options;
}
public class Option {
/**选项ID*/
private int id;
/**选项内容*/
private String content;
/**是否为正确答案,1是2否*/
private int solution;
/**所属题目ID*/
private int itemId;
}
题目表
选项表
问题出现
查询所有题目:
SELECT * FROM item_bank t1
LEFT JOIN option_bank t2 ON t1.id = t2.item_id
当使用分页插件进行查询第一页,每页两条数据时,却查到了这个结果:
我想要的是题目表中的两条数据,然后关联后面的多个选项
但分页插件却将关联的选项也作为了一条数据,导致,第一个题只有两个选项
问题原因
分页插件原理就是拼接limit语句
当你用select查询出结果后,因为是一对多,它会以最终结果去limit拆分
而我们想要的是通过题目表(一方表)去limit,选项表(多方表)不应该参与limit
问题解决
可以做子查询、动态SQL、查询两次等方式
我采用了直接在SQL上动手脚 ^ - ^
-- 原SQL
SELECT t1.*, t2.* FROM item_bank t1
LEFT JOIN option_bank t2 ON t1.id = t2.item_id
LIMIT 0,2
-- 改完之后
SELECT * FROM (
SELECT * FROM item_bank t1 LIMIT 0, 2
) t2 LEFT JOIN option_bank t3 ON t2.id = t3.item_id
dao层映射文件:
startNo是通过page计算出来的,表示数据开始位置
<select id="getItems" resultMap="item">
select * from (
select * from item_bank t1
<!-- 分页 -->
<if test="startNo != null and size != null">
limit #{startNo}, #{size}
</if>
) t2
left join option_bank t3 on t2.id = t3.item_id
</select>