问题描述
最近做项目时使用了mybatisplus,分页插件也使用的是mybatisplus自带的分页插件,业务需求是查询客户列表,每个客户列表中有一个子列表 ,在通过分页插件查询后,会出现数量总数为子列表总数、客户列表与子列表不对等。
1、配置mybatis-plus插件
java
@Configuration
@MapperScan("com.guigu.mapper") //可以将启动类中的注解移到此处
public class MybatisPlusConfig {
/**
*
* 1 怎么来配置mybatis-plus中的插件?
* 这里所需要的类型是MybatisPlusInterceptor,这是mybatis-plus的一个拦截器,用于配置mybatis-plus中的插件。
* 2 为什么要使用拦截器MybatisPlusInterceptor呢?
* 这里边的原理和mybatis分页插件的功能是一样的,工作流程如下 :
* (1)第一步:执行查询功能。
* (2)第二步:拦截器对查询功能进行拦截。
* (3)第三步:拦截器对查询功能的基础上做了额外的处理,达到分页的效果(功能)。
* 3 对比配置mybatis中的插件?
* 用的也是拦截器的方式。
*
* @return MybatisPlusInterceptor
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加:分页插件
//参数:new PaginationInnerInterceptor(DbType.MYSQL),是专门为mysql定制实现的内部的分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
2、mapper语句
java
需求:根据年龄查询用户列表,分页显示
*
* 第一步:xml自定义分页,Mapper接口方法
* 第1步:如果想要mybatis-plus的分布插件来作用于我们自定义的sql语句的话,
* 第一个参数必须得是一个分页对象:@Param("page") Page<User> page。
* 第二步:因为Mapper接口方法有2个参数的话
* 方案1:使用mybatis提供的访问方式
* 方案2:也可以使用@param来设置命名参数,来规定参数的访问规则
Page<CustomerEntity> queryCustomerList(@Param("page") Page<CustomerEntity> customerPage,
@Param("customerName") String customerName,
@Param("deptIds") List<Long> deptIds,
@Param("userIds") List<Long> userIds,
@Param("delFlag") Integer logicNotDeleteValue)
xml
<resultMap id="customerList" type="customerEntity">
<id property="customerId" column="customer_id"/>
<result property="customerName" column="customer_name"/>
<collection property="children" select="queryList" column="customer_id" ofType="customerInfoEntity">
</collection>
<collection property="children" ofType="customerInfoEntity">
<id property="customerInfoId" column="customer_info_id"/>
<result property="customerId" column="customer_id"/>
<result property="deptId" column="dept_id"/>
<result property="industry" column="industry"/>
<result property="level" column="level"/>
<result property="source" column="source"/>
<result property="highSeas" column="high_seas"/>
<result property="remark" column="remark"/>
<result property="crtTime" column="crt_time"/>
<result property="crtName" column="crt_name"/>
<result property="crtUserId" column="crt_user_id"/>
</collection>
</resultMap>
<select id="queryCustomerList" resultMap="customerList">
SELECT
c.customer_id,
c.customer_name,
ci.customer_info_id,
ci.customer_id,
ci.dept_id,
ci.industry,
ci.level,
ci.source,
ci.high_seas,
ci.remark,
ci.crt_time,
ci.crt_name,
ci.crt_user_id
FROM customer c
JOIN customer_info ci on c.customer_id = ci.customer_id
where ci.high_seas = 0
and ci.del_flag = #{delFlag}
and c.del_flag =#{delFlag}
<if test="customerName != null">
AND c.customer_name like concat('%',#{customerName},'%')
</if>
<if test="deptIds.size>0">
AND ci.dept_id in
<foreach collection="deptIds" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</if>
<if test="userIds.size>0">
AND ci.crt_user_id in
<foreach collection="userIds" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</if>
</select>
上述语句查询的结果数是表customer_info 的数量而不是表customer的数量,客户列表下有多个子列表时会分成多个相同的客户。
解决办法
那我们怎么才能查到正确得一对多的分页结果呢?mybatis提供另一种方式,使用mybatis的子查询映射。
java
<resultMap id="customerList" type="customerEntity">
<id property="customerId" column="customer_id"/>
<result property="customerName" column="customer_name"/>
<collection property="children" select="queryList" column="customer_id" ofType="customerInfoEntity">
</collection>
</resultMap>
<select id="queryList" resultType="customerInfoEntity">
select ci.customer_info_id,
ci.customer_id,
ci.dept_id,
ci.industry,
ci.level,
ci.source,
ci.high_seas,
ci.remark,
ci.crt_time,
ci.crt_name,
ci.crt_user_id
from customer_info ci
where ci.customer_id = #{customer_id};
</select>
<!-- 查询未加入公海池的客户列表-->
<select id="queryCustomerList" resultMap="customerList">
SELECT
c.customer_id,
c.customer_name,
ci.customer_info_id,
ci.customer_id,
ci.dept_id,
ci.industry,
ci.level,
ci.source,
ci.high_seas,
ci.remark,
ci.crt_time,
ci.crt_name,
ci.crt_user_id
FROM customer c
JOIN customer_info ci on c.customer_id = ci.customer_id
where ci.high_seas = 0
and ci.del_flag = #{delFlag}
and c.del_flag =#{delFlag}
<if test="customerName != null">
AND c.customer_name like concat('%',#{customerName},'%')
</if>
<if test="deptIds.size>0">
AND ci.dept_id in
<foreach collection="deptIds" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</if>
<if test="userIds.size>0">
AND ci.crt_user_id in
<foreach collection="userIds" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</if>
</select>
注意: collection中的colum属性需要填两表关联的字段,也就是customer_id