left join 导致的分页错误


背景:有规则表t_rule,标签表t_label,中间表t_rule_label,根据t_rule的name和t_label表的name组合查询规则

t_rule表数据

idname
1rule1
2rule2

t_label表数据

idname
1label1
2label2

t_rule_label表数据

rule_idlabel_id
11
12
21
22

使用mybatis-plus 查询

Page<CheckRule> page = new Page<>(query.getPageNum(), query.getPageSize());
select rule.id,rule.name,label.id label_id,label.name label_name
from t_rule rule
left join t_rule_label con on con.rule_id = rule.id
left join t_label label on label.id = con.label_id
where rule.name like '%ru%' and label.id in ('1','2')

left join 导致查询出4条数据
在这里插入图片描述

page.getTotal() 和 page.getRecords() 对应不上
因为一对多导致getTotal()数量比getRecords()多,getRecords()为resultMap 组合之后的数据

<resultMap id="ruleResultMap" type="com.yss.rule.entity.Rule">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <collection property="labelList" ofType="com.yss.rule.entity.Label" >
            <id column="lable_id" property="id" />
            <result column="lable_name" property="name" />
        </collection>
    </resultMap>
    
<select id="getRules" resultMap="rulListMap">
	select rule.id,rule.name,label.id label_id,label.name label_name
	from t_rule rule
	left join t_rule_label con on con.rule_id = rule.id
	left join t_label label on label.id = con.label_id
	<where>
		<if test="ruleAndLabelVo.ruleName !=null and ruleAndLabelVo.ruleName !=''">
		and rule.name like '%${ruleAndLabelVo.ruleName }%'
		</if>
		<if test="ruleAndLabelVo.labelIds !=null and ruleAndLabelVo.labelIds.size() !=0">
            and lable.id in
            <foreach collection="ruleAndLabelVo.labelIds" index="index" item="item" open="(" separator="," close=")">
                #{item}
            </foreach>
        </if>
	</where>                     
</select>

行转列解决

对于oracle 行转列

wmsys.wm_concat,oracle 10g推出的函数,12c以后被去掉 select
id,wmsys.wm.concat(name) lable_name from t_label group by id

LISTAGG,是oracle11g推出的函数 select id, listagg(lable_name,’,’) within
group (order by lable_name) lable_name from t_label group by id;

对于mysql 行转列

SELECT GROUP_CONCAT(cast(user_id as char(10)) SEPARATOR ‘,’) as id
from user;

先分页再组装

public class RuleAndLabelVo{
	//前端传递条件
	private String ruleName;
	private List<String> labelIds;
	//第一次查询出的t_rule的主键集合
	private List<String> ruleIds;
}

第一次查询,分页查询,查询出t_rule的主键集合

<select id="getRulesPage" resultMap="string">
	select distinct rule.id
    from t_rule rule
    left join t_rule_label con on con.rule_id = rule.id
	left join t_label label on label.id = con.label_id
	<where>
		<if test="ruleAndLabelVo.ruleName !=null and ruleAndLabelVo.ruleName !=''">
		and rule.name like '%${ruleAndLabelVo.ruleName }%'
		</if>
		<if test="ruleAndLabelVo.labelIds !=null and ruleAndLabelVo.labelIds.size() !=0">
            and lable.id in
            <foreach collection="ruleAndLabelVo.labelIds" index="index" item="item" open="(" separator="," close=")">
                #{item}
            </foreach>
        </if>
	</where>  
	order by rule.id
</select>

第二次查询,将t_rule的主键集合带入查询

List ruleIds = checkRuleMapper.getRulesPage(page,
ruleByRuleOrLabelVo); ruleAndLabelVo.setRuleIds(ruleIds);

<resultMap id="ruleResultMap" type="com.yss.rule.entity.Rule">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <collection property="labelList" ofType="com.yss.rule.entity.Label" >
            <id column="lable_id" property="id" />
            <result column="lable_name" property="name" />
        </collection>
    </resultMap>
    
<select id="getRules" resultMap="rulListMap">
	select rule.id,rule.name,label.id label_id,label.name label_name
	from t_rule rule
	left join t_rule_label con on con.rule_id = rule.id
	left join t_label label on label.id = con.label_id
	<where>
		<if test="ruleAndLabelVo.ruleIds !=null and ruleAndLabelVo.ruleIds.size() !=0">
            and rule.id in
            <foreach collection="ruleAndLabelVo.ruleIds" index="index" item="item" open="(" separator="," close=")">
                #{item}
            </foreach>
        </if>
	</where>                     
</select>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、使用 SelectProvider 进行 left join Mybatis Plus 提供了一个 SelectProvider 类,可以动态生成 SQL 语句。在 left join 操作中,我们可以使用 SelectProvider 来实现。 例如,我们有两个表,一个是用户表 user,另一个是订单表 order。我们想要查询某个用户的所有订单信息,可以使用 left join 来实现。 首先,我们需要定义一个查询语句的模板,使用 @SelectProvider 注解来指定: ``` @SelectProvider(type = MyProvider.class, method = "selectUserOrders") List<UserOrder> selectUserOrders(@Param("userId") Long userId); ``` 其中,MyProvider 是我们定义的一个 SelectProvider 类,selectUserOrders 是其中的一个方法,用来生成查询语句。 然后,在 MyProvider 中,我们需要实现 selectUserOrders 方法,生成查询语句: ``` public String selectUserOrders(@Param("userId") Long userId) { return new SQL(){{ SELECT("user.*, order.*"); FROM("user"); LEFT_JOIN("order ON user.id = order.user_id"); WHERE("user.id = #{userId}"); }}.toString(); } ``` 在这个方法中,我们使用 SQL 类来生成查询语句。首先,使用 SELECT 方法指定要查询的字段,使用 FROM 方法指定主表,使用 LEFT_JOIN 方法来进行左连接操作,使用 WHERE 方法来指定查询条件。 2、使用分页插件进行分页查询 Mybatis Plus 提供了一个分页插件,可以方便地实现分页查询。 首先,我们需要在配置文件中开启分页插件: ``` <plugins> <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"> <property name="dialectType" value="mysql"/> </plugin> </plugins> ``` 然后,在查询方法中,我们可以使用 Page 类来进行分页查询: ``` Page<UserOrder> page = new Page<>(1, 10); List<UserOrder> userOrders = userOrderMapper.selectUserOrders(page, userId); ``` 其中,Page 的第一个参数是当前页码,第二个参数是每页显示的记录数。userOrderMapper 是我们定义的一个 Mapper 接口,selectUserOrders 是其中的一个方法,用来进行查询操作。 在 selectUserOrders 方法中,我们需要使用 Mybatis Plus 提供的分页参数注解 @Param 来指定分页参数: ``` List<UserOrder> selectUserOrders(@Param("page") Page<UserOrder> page, @Param("userId") Long userId); ``` 然后,在 SQL 语句中,我们可以使用 Mybatis Plus 提供的分页语句来进行分页操作: ``` public String selectUserOrders(@Param("page") Page<UserOrder> page, @Param("userId") Long userId) { return new SQL(){{ SELECT("user.*, order.*"); FROM("user"); LEFT_JOIN("order ON user.id = order.user_id"); WHERE("user.id = #{userId}"); }}.toString() + " LIMIT " + page.getOffset() + ", " + page.getSize(); } ``` 在这个方法中,我们需要使用 Page 类提供的 getOffset 和 getSize 方法来获取当前分页的偏移量和每页显示的记录数,然后将它们拼接到 SQL 语句的末尾。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值