MyBatis-Flex集成Spring
MyBatis filex 分页查询官网API如下
在 MyBatis-Flex 的 BaseMapper 中,提供了如下的分页查询功能:
paginate(pageNumber, pageSize, queryWrapper)
:分页查询。paginateWithRelations(pageNumber, pageSize, queryWrapper)
:分页查询,及其 Relation 字段内容。paginate(pageNumber, pageSize, whereConditions)
:分页查询。paginateWithRelations(pageNumber, pageSize, whereConditions)
:分页查询,及其 Relation 字段内容。paginate(pageNumber, pageSize, totalRow, queryWrapper)
:分页查询。paginateWithRelations(pageNumber, pageSize, totalRow, queryWrapper)
:分页查询,及其 Relation 字段内容。paginate(pageNumber, pageSize, totalRow, whereConditions)
:分页查询。paginateWithRelations(pageNumber, pageSize, totalRow, whereConditions)
:分页查询,及其 Relation 字段内容。paginate(page, queryWrapper)
:分页查询。paginate(page, queryWrapper, consumers)
:分页查询。paginateWithRelations(page, queryWrapper)
:分页查询,及其 Relation 字段内容。paginateWithRelations(page, queryWrapper, consumers)
:分页查询,及其 Relation 字段内容。paginateAs(pageNumber, pageSize, queryWrapper, asType)
:分页查询。paginateAs(pageNumber, pageSize, totalRow, queryWrapper, asType)
:分页查询。paginateAs(page, queryWrapper, asType)
:分页查询。paginateAs(page, queryWrapper, asType, consumers)
:分页查询。paginateWithRelationsAs(pageNumber, pageSize, queryWrapper, asType)
:分页查询,及其 Relation 字段内容。paginateWithRelationsAs(pageNumber, pageSize, totalRow, queryWrapper, asType)
:分页查询,及其 Relation 字段内容。paginateWithRelationsAs(page, queryWrapper, asType)
:分页查询,及其 Relation 字段内容。paginateWithRelationsAs(page, queryWrapper, asType, consumers)
:分页查询,及其 Relation 字段内容。
参数说明:
- pageNumber: 当前页码,从 1 开始
- pageSize: 每 1 页的数据量
- totalRow: 非必须值,若传入该值,mybatis-flex 则不再去查询总数据量(若传入小于 0 的数值,也会去查询总量)。
- queryWrapper: 查询条件
- queryCondition: 查询条件
采用MyBatis flex实现分页存在局限性,复杂逻辑多张表关联查询时使用flex的api不是很好,因此我们需要自己通过xml实现自定义SQL查询,但是查询时除了查询list数据,还需要进行分页count统计,需要编写2个SQL组合,非常麻烦!因此我们采用flex整合PageHelper插件实现分页。
MyBaits PageHelper 分页插件官网
1. 普通项目添加maven依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.2</version>
</dependency>
2. 使用 Spring Boot 时
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>最新版本</version>
</dependency>
3. 配置拦截器插件
1).在 MyBatis 配置 xml 中配置拦截器插件
<!--
plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下:
properties?, settings?,
typeAliases?, typeHandlers?,
objectFactory?,objectWrapperFactory?,
plugins?,
environments?, databaseIdProvider?, mappers?
-->
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
<property name="param1" value="value1"/>
</plugin>
</plugins>
2).在 Spring 配置文件中配置拦截器插件
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注意其他配置 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
params=value1
</value>
</property>
</bean>
</array>
</property>
</bean>
3). 在 Spring Boot 中配置
Spring Boot 引入 starter 后自动生效,对分页插件进行配置时,在 Spring Boot 对应的配置文件 application.[properties|yaml]
中配置。
MyBatis Flex集成PageHelper
MyBaits Flex是在mybatis框架基础上进行的增强,在springboot项目中使用pagehelper-spring-boot-starter自动装配后会导致mybatis flex查询异常,执行sql时参数无法正常填充到预处理sql中。打开PageHelper starter的pom如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency>
</dependencies>
PageHelper starter依赖了mybatis starter和PageHelper,PageHelper是分页的实现包,pagehelper autoconfigure是基于springbooot 的自动装配包。问题就出在此包上。我们打开源码查看
@Configuration
@ConditionalOnBean({SqlSessionFactory.class})
@EnableConfigurationProperties({PageHelperProperties.class})
@AutoConfigureAfter({MybatisAutoConfiguration.class})
@Lazy(false)
public class PageHelperAutoConfiguration implements InitializingBean {
private final List<SqlSessionFactory> sqlSessionFactoryList;
private final PageHelperProperties properties;
public PageHelperAutoConfiguration(List<SqlSessionFactory> sqlSessionFactoryList, PageHelperProperties properties) {
this.sqlSessionFactoryList = sqlSessionFactoryList;
this.properties = properties;
}
public void afterPropertiesSet() throws Exception {
PageInterceptor interceptor = new PageInterceptor();
interceptor.setProperties(this.properties);
Iterator var2 = this.sqlSessionFactoryList.iterator();
while(var2.hasNext()) {
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory)var2.next();
org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
if (!this.containsInterceptor(configuration, interceptor)) {
configuration.addInterceptor(interceptor);
}
}
}
private boolean containsInterceptor(org.apache.ibatis.session.Configuration configuration, Interceptor interceptor) {
try {
return configuration.getInterceptors().contains(interceptor);
} catch (Exception var4) {
return false;
}
}
}
注意:@AutoConfigureAfter({MybatisAutoConfiguration.class}) 这里,mybatis flex也是在MybatisAutoConfiguration之后初始化的,这就导致mybatis flex和PageHelper出现问题。我们改造也很简单,只需要让PageHelper在mybatis flex初始化完毕后再注册PageInterceptor。因此PageHelper autoconfigure我们需要自己实现。具体方法如下:
1). 删除POM中的依赖
<!--
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.2</version>
</dependency>
2).自己实现config,改动就一句,让PageHelper插件注册在mybatis flex 配置完毕后执行。
@Configuration
@AutoConfigureAfter(MybatisFlexAutoConfiguration.class)
public class PageHelperConfig implements InitializingBean {
@Autowired
private List<SqlSessionFactory> sqlSessionFactoryList;
@Override
public void afterPropertiesSet() throws Exception {
PageInterceptor interceptor = new PageInterceptor();
Properties props = new Properties();
props.setProperty("helperDialect", "mysql");
interceptor.setProperties(props);
for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
if (!containsInterceptor(configuration, interceptor)) {
configuration.addInterceptor(interceptor);
}
}
}
/**
* 是否已经存在相同的拦截器
*
* @param configuration
* @param interceptor
* @return
*/
private boolean containsInterceptor(org.apache.ibatis.session.Configuration configuration, Interceptor interceptor) {
try {
return configuration.getInterceptors().stream().anyMatch(config->interceptor.getClass().isAssignableFrom(config.getClass()));
} catch (Exception e) {
return false;
}
}
}