Mybatis手写分页代码
目录
仅为代码记录。
方式一、Executor.class
参考 自己动手写一个MyBatis自定义拦截器实现分页 - 简书
<resultMap id="categoryVoResultMap" type="com.lw.familysystem.vo.VideoCategoryVo">
<id property="categoryId" column="category_id"/>
<result property="categoryName" column="category_name"/>
<result property="createTimeFmt" column="create_time_fmt"/>
<result property="updateTimeFmt" column="update_time_fmt"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<select id="findCategoriesByPage" resultMap="categoryVoResultMap" parameterType="VideoCategoryVo">
select t.*,
date_format(t.create_time,'%Y/%m/%d %H:%i') as create_time_fmt,
date_format(t.update_time,'%Y/%m/%d %H:%i') as update_time_fmt
from video_category t
</select>
补充方式一里面没有 xml的写法。
实践后补充说明
如果是分页还带有参数,按照方式一照抄就有问题,会出现报错一的问题,
<select id="findCategoriesByPage" resultMap="categoryVoResultMap" parameterType="VideoCategoryVo">
select t.*,
date_format(t.create_time,'%Y/%m/%d %H:%i') as create_time_fmt,
date_format(t.update_time,'%Y/%m/%d %H:%i') as update_time_fmt
from video_category t
<where>
<if test="vo.categoryName!=null and vo.categoryName!=''">
and t.category_name = #{vo.categoryName}
</if>
</where>
</select>
![](https://img-blog.csdnimg.cn/dd09dba1c49047679dad7a8f33c9b721.png)
即使是把vo.categoryName改为 categoryName,也会报错,会报只有pageRequest,vo,param1,param2,找不到categoryName。
问题就是如下的两张图处,需要改为传递原始的参数,而不是转换后的。
问题就在于whereParam是一个对象,里面并没有封装传入的参数,而param是一个ParamMap,是继承于HashMap的一个Map,所以才能vo.XXX成功。
param对象里面的param1,param2这个两个key其实和方法的传参顺序有关。
Page<VideoCategoryVo> findCategoriesByPage(@Param("vo") VideoCategoryVo vo,PageRequest pageRequest);
List<VideoCategoryVo> findCategories(@Param("vo") VideoCategoryVo vo);
在Mapper.java中不分页查询,也可以用分页的SQL样式,如下
<select id="findCategories" resultMap="categoryVoResultMap" parameterType="VideoCategoryVo">
select t.*,
date_format(t.create_time,'%Y/%m/%d %H:%i') as create_time_fmt,
date_format(t.update_time,'%Y/%m/%d %H:%i') as update_time_fmt
from video_category t
<where>
<if test="vo.categoryName!=null and vo.categoryName!=''">
and t.category_name = #{vo.categoryName}
</if>
</where>
</select>
附上完整代码
Controller
@RequestMapping("/findCategoriesByPage")
@ResponseBody
public ReturnInfo findCategoriesByPage(){
Page<VideoCategoryVo> categories = this.videoService.findCategoriesByPage();
return ReturnInfo.returnSuccessInfo(categories);
}
Service
@Autowired
private VideoCategoryMapper categoryMapper;
public Page<VideoCategoryVo> findCategoriesByPage(){
VideoCategoryVo vo = new VideoCategoryVo();
vo.setCategoryName("电影");
PageRequest pageRequest = new PageRequest(0,3);
return this.categoryMapper.findCategoriesByPage(vo,pageRequest);
}
Mapper.java
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 类别
*/
@Mapper
public interface VideoCategoryMapper {
List<VideoCategoryVo> findAllCategories();
Page<VideoCategoryVo> findCategoriesByPage(@Param("vo") VideoCategoryVo vo,PageRequest pageRequest);
}
Mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lw.familysystem.video.mapper.VideoCategoryMapper">
<resultMap id="categoryVoResultMap" type="com.lw.familysystem.vo.VideoCategoryVo">
<id property="categoryId" column="category_id"/>
<result property="categoryName" column="category_name"/>
<result property="createTimeFmt" column="create_time_fmt"/>
<result property="updateTimeFmt" column="update_time_fmt"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<select id="findAllCategories" resultMap="categoryVoResultMap">
select t.*,
date_format(t.create_time,'%Y/%m/%d %H:%i') as create_time_fmt,
date_format(t.update_time,'%Y/%m/%d %H:%i') as update_time_fmt
from video_category t
</select>
<select id="findCategoriesByPage" resultMap="categoryVoResultMap" parameterType="VideoCategoryVo">
select t.*,
date_format(t.create_time,'%Y/%m/%d %H:%i') as create_time_fmt,
date_format(t.update_time,'%Y/%m/%d %H:%i') as update_time_fmt
from video_category t
<where>
<if test="vo.categoryName!=null and vo.categoryName!=''">
and t.category_name = #{vo.categoryName}
</if>
</where>
</select>
</mapper>
MybatisPageInterceptor.java 拦截器
package com.lw.config;
import com.lw.config.mybatis.BoundSqlSqlSource;
import com.lw.config.mybatis.page.Page;
import com.lw.config.mybatis.page.PageRequest;
import com.mysql.cj.x.protobuf.MysqlxPrepare;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.util.StringUtils;
import javax.xml.bind.PropertyException;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
/**
* mybatis 分页拦截器
* 自定义分页
*/
@Intercepts({@Signature(
type = Executor.class,
method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
)})
@Slf4j
public class MybatisPageInterceptor implements Interceptor {
private static String dialect = "";
private static String pageSqlId = "";
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
if (mappedStatement.getId().matches(pageSqlId)) {
//获取参数
Object param = invocation.getArgs()[1];
Object whereParam = getWhereParameter(param);
BoundSql boundSql = mappedStatement.getBoundSql(param);
if (log.isDebugEnabled()) {
log.debug("[sql_id]=" + mappedStatement.getId());
log.debug("[sql]=" + boundSql.getSql());
}
//获取查询SQL
String sql = boundSql.getSql();
//获取数据库连接
Configuration config = mappedStatement.getConfiguration();
Connection connection = config.getEnvironment().getDataSource().getConnection();
//查询总数据
String countSql = "select count(*) from (" + sql + ") tmp_count";
PreparedStatement countStmt = connection.prepareStatement(countSql);
BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), boundSql.getParameterObject());
this.setParameters(countStmt, mappedStatement, countBS, boundSql.getParameterObject());
ResultSet rs = countStmt.executeQuery();
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
countStmt.close();
PageRequest pageRequest = this.getPageRequest(param);
String pageSql = generatePageSql(sql, pageRequest);
executeSql(invocation,pageSql);
//重新执行新的sql
Object result = invocation.proceed();
connection.close();
//处理新的结构
Page<?> page = new Page((List)result, pageRequest, count);
List<Page> returnResultList = new ArrayList<>();
returnResultList.add(page);
return returnResultList;
}
return invocation.proceed();
}
private void executeSql(Invocation invocation, String sql){
final Object[] args = invocation.getArgs();
MappedStatement statement = (MappedStatement) args[0];
BoundSql boundSql = statement.getBoundSql(args[1]);
MappedStatement newStatement = createNewMappedStatement(statement, new BoundSqlSqlSource(boundSql));
MetaObject msObject = MetaObject.forObject(newStatement, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());
msObject.setValue("sqlSource.boundSql.sql", sql);
args[0] = newStatement;
}
/**
* 获取新的MappedStatement
* @param ms
* @param newSqlSource
* @return
*/
private MappedStatement createNewMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
MappedStatement.Builder builder =
new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
builder.resource(ms.getResource());
builder.fetchSize(ms.getFetchSize());
builder.statementType(ms.getStatementType());
builder.keyGenerator(ms.getKeyGenerator());
if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) {
StringBuilder keyProperties = new StringBuilder();
for (String keyProperty : ms.getKeyProperties()) {
keyProperties.append(keyProperty).append(",");
}
keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
builder.keyProperty(keyProperties.toString());
}
builder.timeout(ms.getTimeout());
builder.parameterMap(ms.getParameterMap());
builder.resultMaps(ms.getResultMaps());
builder.resultSetType(ms.getResultSetType());
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return builder.build();
}
/**
* 从参数列表返回PageRequest
*/
private PageRequest getPageRequest(Object paramMap) {
if (paramMap == null) {
return null;
} else if (PageRequest.class.isAssignableFrom(paramMap.getClass())) {
return (PageRequest) paramMap;
} else {
if (paramMap instanceof MapperMethod.ParamMap) {
MapperMethod.ParamMap map = (MapperMethod.ParamMap) paramMap;
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
Object obj = entry.getValue();
if (obj != null && PageRequest.class.isAssignableFrom(obj.getClass())) {
return (PageRequest) obj;
}
}
}
return null;
}
}
private Object getWhereParameter(Object obj) {
if (obj instanceof MapperMethod.ParamMap) {
MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) obj;
if (paramMap.size() == 4) {
Iterator iterator = paramMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry var4 = (Map.Entry) iterator.next();
Object var5 = var4.getValue();
if (PageRequest.class.isAssignableFrom(var5.getClass())) {
return paramMap.get("param1");
}
}
}
}
return obj;
}
private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
Configuration configuration = mappedStatement.getConfiguration();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
for (int i = 0; i < parameterMappings.size(); ++i) {
ParameterMapping parameterMapping = (ParameterMapping) parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
String propertyName = parameterMapping.getProperty();
PropertyTokenizer prop = new PropertyTokenizer(propertyName);
Object value = null;
if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (propertyName.startsWith("__frch_") && boundSql.hasAdditionalParameter(prop.getName())) {
value = boundSql.getAdditionalParameter(prop.getName());
if (value != null) {
value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
}
} else {
value = metaObject == null ? null : metaObject.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
if (typeHandler == null) {
throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId());
}
typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
}
}
}
}
/**
* 重新生成分页SQL
*
* @param sql
* @param pageRequest
* @return
*/
private String generatePageSql(String sql, PageRequest pageRequest) {
if (pageRequest != null && !StringUtils.isEmpty(dialect)) {
StringBuffer pageSql = new StringBuffer();
if ("mysql".equals(dialect)) {
pageSql.append(sql);
pageSql.append(" limit " + pageRequest.getOffset() + "," + pageRequest.getPageSize());
} else if ("oracle".equals(dialect)) {
pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
pageSql.append(sql);
pageSql.append(" ) tmp_tb ");
pageSql.append(") where row_id>");
pageSql.append(pageRequest.getOffset());
pageSql.append(" and row_id<= ");
pageSql.append(pageRequest.getOffset() + pageRequest.getPageSize());
} else if ("pg".equals(dialect)) {
pageSql.append(sql);
int offsetNum = 0;
if (pageRequest != null && pageRequest.getOffset() != 0) {
offsetNum = pageRequest.getOffset() - 1;
}
pageSql.append(" limit " + pageRequest.getPageSize() + " offset " + offsetNum * pageRequest.getPageSize());
}
log.debug(pageSql.toString());
return pageSql.toString();
} else {
return sql;
}
}
public Object plugin(Object arg0) {
return Plugin.wrap(arg0, this);
}
/**
* 加载mybatis-config.xml中配置
*
* @param p
*/
public void setProperties(Properties p) {
dialect = p.getProperty("dialect");
if (StringUtils.isEmpty(dialect)) {
try {
throw new PropertyException("dialect property is not found!");
} catch (PropertyException var4) {
var4.printStackTrace();
}
}
pageSqlId = p.getProperty("pageSqlId");
if (StringUtils.isEmpty(pageSqlId)) {
try {
throw new PropertyException("pageSqlId property is not found!");
} catch (PropertyException var3) {
var3.printStackTrace();
}
}
}
}
Page.java
package com.lw.config.mybatis.page;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 分页封装返回
* @param <T>
*/
@Data
public class Page<T> implements Serializable {
private static final long serialVersionUID = 1625981207349025919L;
//查询结果集
private final List<T> content;
//分页参数
private PageRequest pageRequest;
//总记录数
private int total;
public Page(List<T> content, PageRequest pageRequest, int total) {
this.content = new ArrayList();
if (null == content) {
throw new IllegalArgumentException("Content must not be null!");
} else {
this.content.addAll(content);
this.total = total;
this.pageRequest = pageRequest;
}
}
}
PageRequest.java
package com.lw.config.mybatis.page;
import lombok.Data;
import java.io.Serializable;
/**
* 分页参数
*/
@Data
public class PageRequest implements Serializable {
private static final long serialVersionUID = -2464407342708149892L;
/**
*页码(从0开始)
*/
private int page;
/**
*每页显示数量
*/
private int size;
public PageRequest() {
this(0, 10);
}
public PageRequest(int page, int size) {
if (page < 0) {
page = 0;
}
if (size < 0) {
size = 0;
}
this.page = page;
this.size = size;
}
public int getPageSize() {
return this.size;
}
public int getOffset() {
return this.page * this.size;
}
}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="true" />
<setting name="multipleResultSetsEnabled" value="true" />
<!--日志打印,可以输出SQL-->
<!-- <setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/>-->
<setting name="logImpl" value="com.lw.config.MybatisLogConfig"/>
<setting name="vfsImpl" value="org.mybatis.spring.boot.autoconfigure.SpringBootVFS" />
</settings>
<!--自定义分页-->
<plugins>
<plugin interceptor="com.lw.config.MybatisPageInterceptor">
<property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*ByPage"/>
</plugin>
</plugins>
</configuration>
方式二、StatementHandler.class
在方式一上的变体,
package com.lw.config;
import com.lw.config.mybatis.page.Page;
import com.lw.config.mybatis.page.PageRequest;
import com.mysql.cj.x.protobuf.MysqlxPrepare;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.util.StringUtils;
import javax.xml.bind.PropertyException;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
/**
* mybatis 分页拦截器
* 自定义分页
*/
@Intercepts({@Signature(
type = StatementHandler.class,
method = "prepare", args = {Connection.class, Integer.class}
)})
@Slf4j
public class MybatisPageInterceptor implements Interceptor {
private static String dialect = "";
private static String pageSqlId = "";
@Override
public Object intercept(Invocation invocation) throws Throwable {
if (invocation.getTarget() instanceof RoutingStatementHandler) {
RoutingStatementHandler statementHandler = (RoutingStatementHandler)invocation.getTarget();
BaseStatementHandler delegate = (BaseStatementHandler)getValueByFieldName(statementHandler, "delegate");
MappedStatement mappedStatement = (MappedStatement)getValueByFieldName(delegate, "mappedStatement");
if (mappedStatement.getId().matches(pageSqlId)) {
BoundSql boundSql = delegate.getBoundSql();
if (log.isDebugEnabled()) {
log.debug("[sql_id]=" + mappedStatement.getId());
log.debug("[sql]=" + boundSql.getSql());
}
//获取参数
String sql = boundSql.getSql();
//获取相关配置
Configuration config = mappedStatement.getConfiguration();
Connection connection = config.getEnvironment().getDataSource().getConnection();
//查询总数据
String countSql = "select count(*) from (" + sql + ") tmp_count";
PreparedStatement countStmt = connection.prepareStatement(countSql);
BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), boundSql.getParameterObject());
this.setParameters(countStmt, mappedStatement, countBS, boundSql.getParameterObject());
ResultSet rs = countStmt.executeQuery();
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
countStmt.close();
Object paramObject = boundSql.getParameterObject();
PageRequest pageRequest = getPageRequest(paramObject);
String pageSql = generatePageSql(sql, pageRequest);
setValueByFieldName(boundSql, "sql", pageSql);
//重新执行新的sql
Object result = invocation.proceed();
connection.close();
pageRequest.setTotalCount(count);
return result;
}
}
return invocation.proceed();
}
/**
* 从参数列表返回PageRequest
*/
public PageRequest getPageRequest(Object paramMap) {
if (paramMap == null) {
return null;
} else if (PageRequest.class.isAssignableFrom(paramMap.getClass())) {
return (PageRequest)paramMap;
} else {
if (paramMap instanceof MapperMethod.ParamMap) {
MapperMethod.ParamMap map = (MapperMethod.ParamMap)paramMap;
Iterator iterator = map.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry entry = (Map.Entry)iterator.next();
Object obj = entry.getValue();
if (obj != null && PageRequest.class.isAssignableFrom(obj.getClass())) {
return (PageRequest)obj;
}
}
}
return null;
}
}
private Object getWhereParameter(Object obj) {
if (obj instanceof MapperMethod.ParamMap) {
MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap)obj;
if (paramMap.size() == 4) {
Iterator iterator = paramMap.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry var4 = (Map.Entry)iterator.next();
Object var5 = var4.getValue();
if (PageRequest.class.isAssignableFrom(var5.getClass())) {
return paramMap.get("param1");
}
}
}
}
return obj;
}
private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
Configuration configuration = mappedStatement.getConfiguration();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
for(int i = 0; i < parameterMappings.size(); ++i) {
ParameterMapping parameterMapping = (ParameterMapping)parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
String propertyName = parameterMapping.getProperty();
PropertyTokenizer prop = new PropertyTokenizer(propertyName);
Object value = null;
if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (propertyName.startsWith("__frch_") && boundSql.hasAdditionalParameter(prop.getName())) {
value = boundSql.getAdditionalParameter(prop.getName());
if (value != null) {
value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
}
} else {
value = metaObject == null ? null : metaObject.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
if (typeHandler == null) {
throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId());
}
typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
}
}
}
}
/**
* 重新生成分页SQL
* @param sql
* @param pageRequest
* @return
*/
private String generatePageSql(String sql, PageRequest pageRequest) {
if (pageRequest != null && !StringUtils.isEmpty(dialect)) {
StringBuffer pageSql = new StringBuffer();
if ("mysql".equals(dialect)) {
pageSql.append(sql);
pageSql.append(" limit " + pageRequest.getOffset() + "," + pageRequest.getPageSize());
} else if ("oracle".equals(dialect)) {
pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
pageSql.append(sql);
pageSql.append(" ) tmp_tb ");
pageSql.append(") where row_id>");
pageSql.append(pageRequest.getOffset());
pageSql.append(" and row_id<= ");
pageSql.append(pageRequest.getOffset() + pageRequest.getPageSize());
} else if ("pg".equals(dialect)) {
pageSql.append(sql);
int offsetNum = 0;
if (pageRequest != null && pageRequest.getOffset()!= 0) {
offsetNum = pageRequest.getOffset() - 1;
}
pageSql.append(" limit " + pageRequest.getPageSize() + " offset " + offsetNum * pageRequest.getPageSize());
}
log.debug(pageSql.toString());
return pageSql.toString();
} else {
return sql;
}
}
public Object plugin(Object arg0) {
return Plugin.wrap(arg0, this);
}
/**
* 加载mybatis-config.xml中配置
* @param p
*/
public void setProperties(Properties p) {
dialect = p.getProperty("dialect");
if (StringUtils.isEmpty(dialect)) {
try {
throw new PropertyException("dialect property is not found!");
} catch (PropertyException var4) {
var4.printStackTrace();
}
}
pageSqlId = p.getProperty("pageSqlId");
if (StringUtils.isEmpty(pageSqlId)) {
try {
throw new PropertyException("pageSqlId property is not found!");
} catch (PropertyException var3) {
var3.printStackTrace();
}
}
}
private static Field getFieldByFieldName(Object obj, String fieldName) {
Class<?> superClass = obj.getClass();
while(superClass != Object.class) {
try {
return superClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException var4) {
superClass = superClass.getSuperclass();
}
}
return null;
}
private static Object getValueByFieldName(Object obj, String fieldName) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field field = getFieldByFieldName(obj, fieldName);
Object value = null;
if (field != null) {
if (field.isAccessible()) {
value = field.get(obj);
} else {
field.setAccessible(true);
value = field.get(obj);
field.setAccessible(false);
}
}
return value;
}
private static void setValueByFieldName(Object obj, String fieldName, Object value) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field field = obj.getClass().getDeclaredField(fieldName);
if (field.isAccessible()) {
field.set(obj, value);
} else {
field.setAccessible(true);
field.set(obj, value);
field.setAccessible(false);
}
}
}
变体是拦截对应的方法,同时将数据总数写入pageRequest中。
mybatis-config.xml中也配置了拦截 ByPage结尾的方法,并标注了是mysql类型。
<!--自定义分页-->
<plugins>
<plugin interceptor="com.lw.config.MybatisPageInterceptor">
<property name="dialect" value="mysql"/>
<property name="pageSqlId" value=".*ByPage"/>
</plugin>
</plugins>
**Mapper.xml的写法没有改变,改变的是 **Mapper.java中方法的返回,不在是Page<T>,
List<VideoCategoryVo> findCategoriesByPage(VideoCategoryVo vo, PageRequest pageRequest);
总数据量就在PageRequest中。
总的来说,好像第一种方式更好,第二种变体污染了PageRequest。