MyBatis-plusページングプラグイン------筆者はページングプラグインの使用をお勧めしません
15773 ワード
MyBatis-plusページングプラグイン1、ページングオブジェクト 2、ページングカード(実はブロック) 3、反射工具 4、配置(主にpluginsを参照) 1、ページングオブジェクト
2、ページングカード(実はブロック)
package com.dsanjun.common.autopage;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author dyw
* @date 2019 9 20
* @param
*/
public class AutoPage implements Serializable {
private static final long serialVersionUID = 2862962633786434439L;
/**
* , 10
*/
private int pageSize = 10; //
/**
* ,
*/
private int currentPage = 1; //
/**
* ,
*/
private int currentDBIndex;
/**
*
*/
private int totalPage;
/**
*
*/
private int totalCount;
/**
*
*/
private List records;
public List getRecords() {
return records;
}
public void setRecords(List records) {
this.records = records;
}
public int getTotalPage() {
if (totalCount % pageSize == 0) {
totalPage = totalCount / pageSize;
} else {
totalPage = totalCount / pageSize + 1;
}
return totalPage;
}
public int getCurrentPage() {
if (currentPage <= 0) {
currentPage = 1;
}
if (currentPage > getTotalPage()) {
currentPage = getTotalPage();
}
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getCurrentDBIndex() {
currentDBIndex = (getCurrentPage() - 1) * getCurrentPage();
return currentDBIndex;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
}
2、ページングカード(実はブロック)
package com.dsanjun.common.autopage;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
import javax.xml.bind.PropertyException;
import org.apache.ibatis.binding.MapperMethod.ParamMap;
import org.apache.ibatis.executor.ErrorContext;
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.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
/**
* , , 。
*
*
* Mybatis :
* 1、 JDBC Statement 。
* 2、Mybatis Sql Sql Statement , Sql Statement 。
* 3、 Mybatis Statement RoutingStatementHandler prepare 。
* 4、 StatementHandler prepare , Sql Sql , StatementHandler prepare ( invocation.proceed())。
* 5、 , Sql , Mybatis Sql , Sql 。
*
*
* @author dyw
*@date 2019 9 20
* @param
*/
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
@SuppressWarnings("unchecked")
public class AutoPageInterceptor implements Interceptor {
private Logger log = LoggerFactory.getLogger(AutoPageInterceptor.class);
/**
*データベース・タイプ
*/
private String databaseType;
/**
*ページングSql ID(Mapperインタフェースページングメソッドの には、ページングプラグインがメソッドをブロックするためにこのフィールドを める があります)
*/
private String pageSqlId;
/**
*ページング・オブジェクト・インタフェースの (MapperインタフェースAutoPageパラメータの .ページング・インタフェースのページング・オブジェクト がここと することを する)
*/
private String autoPageParamName;
/**
*
* :
* StatementHandler
* ---RoutingStatementHandler
* ---BaseStatementHandler
* ---SimpleStatementHandler
* ---PreparedStatementHandler
* ---CallableStatementHandler
* :
* SimpleStatementHandler Statement
* PreparedStatementHandler PreparedStatement
* CallableStatementHandler CallableStatement
*
* :
* 1、Mybatis Sql RoutingStatementHandler
* 2、 RoutingStatementHandler StatementHandler delegate
* 3、RoutingStatementHandler Statement BaseStatementHandler
* ( SimpleStatementHandler、 PreparedStatementHandler CallableStatementHandler)
* 4、 RoutingStatementHandler StatementHandler delegate 。
* 5、 PageInterceptor @Signature Interceptor StatementHandler prepare ,
* Mybatis RoutingStatementHandler Interceptor plugin ,
* RoutingStatementHandler 。
*
*/
@Override
public Object intercept(Invocation ivk) throws Throwable {
RoutingStatementHandler statementHandler = (RoutingStatementHandler) PluginUtils.realTarget(ivk.getTarget());
BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper.getValueByFieldName(statementHandler,
"delegate");
MappedStatement mappedStatement = (MappedStatement) ReflectHelper.getValueByFieldName(delegate,
"mappedStatement");
if (mappedStatement.getId().contains(pageSqlId){//ページングが なSQLをブロック
BoundSql boundSql = delegate.getBoundSql();
//ページングSQLのparameterType に するエンティティパラメータ、つまりMapperインタフェースでページングメソッドを するパラメータ.このパラメータは にしてはならない
ParamMap parameterObject = (ParamMap) boundSql.getParameterObject();
if (parameterObject == null) {
throw new NullPointerException(「parameterObjectはまだインスタンス されていません!」);
} else {
Connection connection = (Connection) ivk.getArgs()[0];
String sql = boundSql.getSql();
String countSql = "select count(0) from ("+ sql + ") b";//レコード
PreparedStatement countStmt = connection.prepareStatement(countSql);
BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql,
boundSql.getParameterMappings(), parameterObject);
setParameters(countStmt, mappedStatement, countBS, parameterObject);
ResultSet rs = countStmt.executeQuery();
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
countStmt.close();
AutoPage page = (AutoPage) parameterObject.get(autoPageParamName);
page.setTotalCount(count);
parameterObject.put(autoPageParamName, page);
String pageSql = generatePageSql(sql, page);
ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql);//ページングsql をBoundSqlに する.
}
}
return ivk.proceed();
}
/**
*SQLパラメータ(?) 、org. .apache.ibatis.executor.parameter.DefaultParameterHandler
*
* @param ps
* @param mappedStatement
* @param boundSql
* @param parameterObject
* @throws SQLException
*/
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 = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
PropertyTokenizer prop = new PropertyTokenizer(propertyName);
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(ForEachSqlNode.ITEM_PREFIX)
&& 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 = (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 page
* @return
*/
private String generatePageSql(String sql, AutoPage page) {
if (page != null && databaseType != null && !databaseType.equals("")) {
StringBuffer pageSql = new StringBuffer();
if ("mysql".equals(databaseType.trim())) {
pageSql.append(sql);
pageSql.append("limit "+ page.getCurrentDBIndex() + ","+ page.getPageSize());
} else if ("oracle".equals(databaseType.trim())) {
pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
pageSql.append(sql);
pageSql.append(") tmp_tb where ROWNUM<=");
pageSql.append(page.getCurrentDBIndex() + page.getPageSize());
pageSql.append(") where row_id>");
pageSql.append(page.getCurrentDBIndex());
}
return pageSql.toString();
} else {
return sql;
}
}
@Override
public Object plugin(Object target) {
//statementHandlerのサブクラスかどうかを する
if (target instanceof StatementHandler) {
//そうであればpluginのwarpメソッドを び し、パッケージします.
return Plugin.wrap(target, this);
}
return target;
}
@Override
public void setProperties(Properties p) {
autoPageParamName = p.getProperty("autoPageParamName");
if (autoPageParamName == null || autoPageParamName.equals("")) {
try {
throw new PropertyException("autoPageParamName property is not found!");
} catch (PropertyException e) {
log.warn(「ページング の :」,e.getMessage()
e.printStackTrace();
}
}
databaseType = p.getProperty("databaseType");
if (databaseType == null || databaseType.equals("")) {
try {
throw new PropertyException("dialect property is not found!");
} catch (PropertyException e) {
log.warn(「ページング の :」,e.getMessage()
e.printStackTrace();
}
}
pageSqlId = p.getProperty("pageSqlId");
if (pageSqlId == null || pageSqlId.equals("")) {
try {
throw new PropertyException("pageSqlId property is not found!");
} catch (PropertyException e) {
log.warn(「ページング の :」,e.getMessage()
e.printStackTrace();
}
}
}
}
3、 ツールpackage com.dsanjun.common.autopage;
import java.lang.reflect.Field;
/**
*
*
* @author dyw
* @date 2019 9 20
*/
public class ReflectHelper {
/**
* obj fieldName Field
*
* @param obj
* @param fieldName
* @return
*/
public static Field getFieldByFieldName(Object obj, String fieldName) {
for (Class> superClass = obj.getClass(); superClass != Object.class; superClass = superClass
.getSuperclass()) {
try {
return superClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
}
}
return null;
}
/**
* obj fieldName
*
* @param obj
* @param fieldName
* @return
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public 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;
}
/**
* obj fieldName
*
* @param obj
* @param fieldName
* @param value
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public 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);
}
}
}
4、 ( にpluginsを )