PageHelper.java
import
java.util.List;
import
java.util.Map.Entry;
import
java.util.Properties;
import
java.util.Set;
import
org.apache.ibatis.binding.MapperMethod.ParamMap;
import
org.apache.ibatis.executor.Executor;
import
org.apache.ibatis.mapping.MappedStatement;
import
org.apache.ibatis.mapping.SqlSource;
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.session.ResultHandler;
import
org.apache.ibatis.session.RowBounds;
import
org.springframework.beans.BeanUtils;
import
com.ai.sipom.sjfw.data.query.interfaces.vo.page.Page;
import
com.ai.sipom.sjfw.data.query.server.util.SystemConfig;
import
com.ai.sipom.sjfw.data.query.server.util.db.DbContextHolder;
/**
* Mybatis - 通用分页拦截器
*
* @author
* @version 3.3.0
* @createdate 2018年01月03日
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
@Intercepts
(
@Signature
(type = Executor.
class
, method =
"query"
, args = {
MappedStatement.
class
, Object.
class
, RowBounds.
class
,
ResultHandler.
class
}))
public
class
PageHelper
implements
Interceptor {
// sql工具类
private
static
SqlUtil SQLUTIL =
null
;
/**
* Mybatis拦截器方法
*
* @param invocation
* 拦截器入参
* @return 返回执行结果
* @throws Throwable
* 抛出异常
*/
public
Object intercept(Invocation invocation)
throws
Throwable {
final
Object[] args = invocation.getArgs();
Page<?> page =
null
;
int
flag =
0
;
if
(args[
1
]
instanceof
ParamMap) {
Set<Entry> entrySet = ((ParamMap) args[
1
]).entrySet();
for
(Entry entry : entrySet) {
if
(entry.getValue()
instanceof
Page) {
page = (Page<?>) entry.getValue();
break
;
}
}
flag =
1
;
}
else
if
(((MappedStatement) args[
0
]).getId().matches(
".*Page$"
)) {
Integer pageNum = (Integer) BeanUtils.getPropertyDescriptor(args[
1
].getClass(),
"pageNum"
).getReadMethod().invoke(args[
1
],
new
Object[
0
]);
Integer pageSize = (Integer) BeanUtils.getPropertyDescriptor(args[
1
].getClass(),
"pageSize"
).getReadMethod().invoke(args[
1
],
new
Object[
0
]);
page =
new
Page(pageNum, pageSize);
flag =
2
;
}
if
(page !=
null
) {
// 忽略RowBounds-否则会进行Mybatis自带的内存分页
args[
2
] = RowBounds.DEFAULT;
// 获取原始的ms
MappedStatement ms = (MappedStatement) args[
0
];
SqlSource sqlSource = ms.getSqlSource();
// 将参数中的MappedStatement替换为新的qs
SQLUTIL.processCountMappedStatement(ms, sqlSource, args);
// 查询总数
Object totalResult = invocation.proceed();
// 设置总数
long
totalCount = ((Integer) ((List) totalResult).get(
0
))
.longValue();
page.setTotal(totalCount);
long
totalPage = totalCount / page.getPageSize() + ((totalCount % page.getPageSize() ==
0
) ?
0
:
1
);
page.setPages(totalPage);
// 将参数中的MappedStatement替换为新的qs
SQLUTIL.processPageMappedStatement(ms, sqlSource, page,
args);
// 执行分页查询
Object list = invocation.proceed();
// 得到处理结果
page.setList((List) list);
//--------------------------
if
(flag ==
2
) {
PageList pageList =
new
PageList();
pageList.setPageNum(page.getPageNum());
pageList.setPageSize(page.getPageSize());
pageList.setStartRow(page.getStartRow());
pageList.setEndRow(page.getEndRow());
pageList.setPages(page.getPages());
pageList.setTotal(page.getTotal());
if
(page.getList() !=
null
) {
pageList.addAll(page.getList());
//pageList.setList(page.getList());
}
return
pageList;
}
else
if
(flag ==
1
) {
return
list;
}
}
// 返回结果
return
invocation.proceed();
}
/**
* 只拦截Executor
*
* @param target
* @return
*/
public
Object plugin(Object target) {
if
(target
instanceof
Executor) {
return
Plugin.wrap(target,
this
);
}
else
{
return
target;
}
}
/**
* 设置属性值
*
* @param p
* 属性值
*/
public
void
setProperties(Properties p) {
String dialect = SystemConfig.getValue(
"jdbc"
+ DbContextHolder.getDBType() +
".dbtype"
);
if
(dialect ==
null
) {
dialect =
"mysql"
;
// 默认oracle数据库
}
SQLUTIL =
new
SqlUtil(dialect);
}
}
SqlUtil.java
import
java.util.ArrayList;
import
java.util.HashMap;
import
java.util.List;
import
java.util.Map;
import
org.apache.ibatis.builder.SqlSourceBuilder;
import
org.apache.ibatis.builder.StaticSqlSource;
import
org.apache.ibatis.builder.annotation.ProviderSqlSource;
import
org.apache.ibatis.mapping.BoundSql;
import
org.apache.ibatis.mapping.MappedStatement;
import
org.apache.ibatis.mapping.ParameterMapping;
import
org.apache.ibatis.mapping.ResultMap;
import
org.apache.ibatis.mapping.ResultMapping;
import
org.apache.ibatis.mapping.SqlSource;
import
org.apache.ibatis.reflection.MetaObject;
import
org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import
org.apache.ibatis.reflection.factory.ObjectFactory;
import
org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import
org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import
org.apache.ibatis.scripting.xmltags.DynamicContext;
import
org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
import
org.apache.ibatis.scripting.xmltags.MixedSqlNode;
import
org.apache.ibatis.scripting.xmltags.SqlNode;
import
org.apache.ibatis.session.Configuration;
import
com.ai.sipom.sjfw.data.query.interfaces.vo.page.Page;
/**
* Mybatis - sql工具,获取分页和count的MappedStatement,设置分页参数
*
* @author
* @since 3.3.0
* @createdate 2018年01月03日
*/
@SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
public
class
SqlUtil {
private
static
final
List<ResultMapping> EMPTY_RESULTMAPPING =
new
ArrayList<ResultMapping>(
0
);
//分页的id后缀
private
static
final
String SUFFIX_PAGE =
"_PageHelper"
;
//count查询的id后缀
private
static
final
String SUFFIX_COUNT = SUFFIX_PAGE +
"_Count"
;
//第一个分页参数
private
static
final
String PAGEPARAMETER_FIRST =
"First"
+ SUFFIX_PAGE;
//第二个分页参数
private
static
final
String PAGEPARAMETER_SECOND =
"Second"
+ SUFFIX_PAGE;
private
static
final
String PROVIDER_OBJECT =
"_provider_object"
;
private
static
final
ObjectFactory DEFAULT_OBJECT_FACTORY =
new
DefaultObjectFactory();
private
static
final
ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY =
new
DefaultObjectWrapperFactory();
/**
* 反射对象,增加对低版本Mybatis的支持
*
* @param object 反射对象
* @return
*/
private
static
MetaObject forObject(Object object) {
return
MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
}
private
SqlUtil.Parser sqlParser;
//数据库方言 - 使用枚举限制数据库类型
public
enum
Dialect {
mysql, mariadb, sqlite, oracle, hsqldb, postgresql
}
/**
* 构造方法
*
* @param strDialect
*/
public
SqlUtil(String strDialect) {
if
(strDialect ==
null
||
""
.equals(strDialect)) {
throw
new
IllegalArgumentException(
"Mybatis分页插件无法获取dialect参数!"
);
}
try
{
Dialect dialect = Dialect.valueOf(strDialect);
String sqlParserClass =
this
.getClass().getPackage().getName() +
".SqlParser"
;
try
{
//使用SqlParser必须引入jsqlparser-x.x.x.jar
Class.forName(
"net.sf.jsqlparser.statement.select.Select"
);
sqlParser = (Parser) Class.forName(sqlParserClass).getConstructor(Dialect.
class
).newInstance(dialect);
}
catch
(Exception e) {
//找不到时,不用处理
}
if
(sqlParser ==
null
) {
sqlParser = SimpleParser.newParser(dialect);
}
}
catch
(IllegalArgumentException e) {
String dialects =
null
;
for
(Dialect d : Dialect.values()) {
if
(dialects ==
null
) {
dialects = d.toString();
}
else
{
dialects +=
","
+ d;
}
}
throw
new
IllegalArgumentException(
"Mybatis分页插件dialect参数值错误,可选值为["
+ dialects +
"]"
);
}
}
/**
* 设置分页参数
*
* @param parameterObject
* @param page
* @return
*/
public
Map setPageParameter(MappedStatement ms, Object parameterObject, Page page) {
BoundSql boundSql = ms.getBoundSql(parameterObject);
return
sqlParser.setPageParameter(ms, parameterObject, boundSql, page);
}
/**
* 处理count查询的MappedStatement
*
* @param ms
* @param sqlSource
* @param args
*/
public
void
processCountMappedStatement(MappedStatement ms, SqlSource sqlSource, Object[] args) {
args[
0
] = getMappedStatement(ms, sqlSource, args[
1
], SUFFIX_COUNT);
}
/**
* 处理分页查询的MappedStatement
*
* @param ms
* @param sqlSource
* @param page
* @param args
*/
public
void
processPageMappedStatement(MappedStatement ms, SqlSource sqlSource, Page page, Object[] args) {
args[
0
] = getMappedStatement(ms, sqlSource, args[
1
], SUFFIX_PAGE);
//处理入参
args[
1
] = setPageParameter((MappedStatement) args[
0
], args[
1
], page);
}
/**
* 处理SQL
*/
public
static
interface
Parser {
void
isSupportedSql(String sql);
String getCountSql(String sql);
String getPageSql(String sql);
Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page);
}
public
static
abstract
class
SimpleParser
implements
Parser {
public
static
Parser newParser(Dialect dialect) {
Parser parser =
null
;
switch
(dialect) {
case
mysql:
case
mariadb:
case
sqlite:
parser =
new
MysqlParser();
break
;
case
oracle:
parser =
new
OracleParser();
break
;
case
hsqldb:
parser =
new
HsqldbParser();
break
;
case
postgresql:
default
:
parser =
new
PostgreSQLParser();
}
return
parser;
}
public
void
isSupportedSql(String sql) {
if
(sql.trim().toUpperCase().endsWith(
"FOR UPDATE"
)) {
throw
new
RuntimeException(
"分页插件不支持包含for update的sql"
);
}
}
/**
* 获取总数sql - 如果要支持其他数据库,修改这里就可以
*
* @param sql 原查询sql
* @return 返回count查询sql
*/
public
String getCountSql(
final
String sql) {
isSupportedSql(sql);
StringBuilder stringBuilder =
new
StringBuilder(sql.length() +
40
);
stringBuilder.append(
"select count(*) from ("
);
stringBuilder.append(sql);
stringBuilder.append(
") tmp_count"
);
return
stringBuilder.toString();
}
/**
* 获取分页sql - 如果要支持其他数据库,修改这里就可以
*
* @param sql 原查询sql
* @return 返回分页sql
*/
public
abstract
String getPageSql(String sql);
public
Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page) {
Map paramMap =
null
;
if
(parameterObject ==
null
) {
paramMap =
new
HashMap();
}
else
if
(parameterObject
instanceof
Map) {
paramMap = (Map) parameterObject;
}
else
{
paramMap =
new
HashMap();
//动态sql时的判断条件不会出现在ParameterMapping中,但是必须有,所以这里需要收集所有的getter属性
//TypeHandlerRegistry可以直接处理的会作为一个直接使用的对象进行处理
boolean
hasTypeHandler = ms.getConfiguration().getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass());
MetaObject metaObject = forObject(parameterObject);
//需要针对注解形式的MyProviderSqlSource保存原值
if
(ms.getSqlSource()
instanceof
MyProviderSqlSource) {
paramMap.put(PROVIDER_OBJECT, parameterObject);
}
if
(!hasTypeHandler) {
for
(String name : metaObject.getGetterNames()) {
paramMap.put(name, metaObject.getValue(name));
}
}
//下面这段方法,主要解决一个常见类型的参数时的问题
if
(boundSql.getParameterMappings() !=
null
&& boundSql.getParameterMappings().size() >
0
) {
for
(ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
String name = parameterMapping.getProperty();
if
(!name.equals(PAGEPARAMETER_FIRST)
&& !name.equals(PAGEPARAMETER_SECOND)
&& paramMap.get(name) ==
null
) {
if
(hasTypeHandler
|| parameterMapping.getJavaType().equals(parameterObject.getClass())) {
paramMap.put(name, parameterObject);
}
else
{
paramMap.put(name, metaObject.getValue(name));
}
}
}
}
}
return
paramMap;
}
}
//Mysql
private
static
class
MysqlParser
extends
SimpleParser {
@Override
public
String getPageSql(String sql) {
StringBuilder sqlBuilder =
new
StringBuilder(sql.length() +
14
);
sqlBuilder.append(sql);
sqlBuilder.append(
" limit ?,?"
);
return
sqlBuilder.toString();
}
@Override
public
Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page) {
Map paramMap =
super
.setPageParameter(ms, parameterObject, boundSql, page);
paramMap.put(PAGEPARAMETER_FIRST, page.getStartRow());
paramMap.put(PAGEPARAMETER_SECOND, page.getPageSize());
return
paramMap;
}
}
//Oracle
private
static
class
OracleParser
extends
SimpleParser {
@Override
public
String getPageSql(String sql) {
StringBuilder sqlBuilder =
new
StringBuilder(sql.length() +
120
);
sqlBuilder.append(
"select * from ( select tmp_page.*, rownum row_id from ( "
);
sqlBuilder.append(sql);
sqlBuilder.append(
" ) tmp_page where rownum <= ? ) where row_id > ?"
);
return
sqlBuilder.toString();
}
@Override
public
Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page) {
Map paramMap =
super
.setPageParameter(ms, parameterObject, boundSql, page);
paramMap.put(PAGEPARAMETER_FIRST, page.getEndRow());
paramMap.put(PAGEPARAMETER_SECOND, page.getStartRow());
return
paramMap;
}
}
//Oracle
private
static
class
HsqldbParser
extends
SimpleParser {
@Override
public
String getPageSql(String sql) {
StringBuilder sqlBuilder =
new
StringBuilder(sql.length() +
20
);
sqlBuilder.append(sql);
sqlBuilder.append(
" limit ? offset ?"
);
return
sqlBuilder.toString();
}
@Override
public
Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page) {
Map paramMap =
super
.setPageParameter(ms, parameterObject, boundSql, page);
paramMap.put(PAGEPARAMETER_FIRST, page.getPageSize());
paramMap.put(PAGEPARAMETER_SECOND, page.getStartRow());
return
paramMap;
}
}
//PostgreSQL
private
static
class
PostgreSQLParser
extends
SimpleParser {
@Override
public
String getPageSql(String sql) {
StringBuilder sqlBuilder =
new
StringBuilder(sql.length() +
14
);
sqlBuilder.append(sql);
sqlBuilder.append(
" limit ? offset ?"
);
return
sqlBuilder.toString();
}
@Override
public
Map setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page page) {
Map paramMap =
super
.setPageParameter(ms, parameterObject, boundSql, page);
paramMap.put(PAGEPARAMETER_FIRST, page.getPageSize());
paramMap.put(PAGEPARAMETER_SECOND, page.getStartRow());
return
paramMap;
}
}
/**
* 自定义动态SqlSource
*/
private
class
MyDynamicSqlSource
implements
SqlSource {
private
Configuration configuration;
private
SqlNode rootSqlNode;
/**
* 用于区分动态的count查询或分页查询
*/
private
Boolean count;
public
MyDynamicSqlSource(Configuration configuration, SqlNode rootSqlNode, Boolean count) {
this
.configuration = configuration;
this
.rootSqlNode = rootSqlNode;
this
.count = count;
}
public
BoundSql getBoundSql(Object parameterObject) {
DynamicContext context =
new
DynamicContext(configuration, parameterObject);
rootSqlNode.apply(context);
SqlSourceBuilder sqlSourceParser =
new
SqlSourceBuilder(configuration);
Class<?> parameterType = parameterObject ==
null
? Object.
class
: parameterObject.getClass();
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
if
(count) {
sqlSource = getCountSqlSource(configuration, sqlSource, parameterObject);
}
else
{
sqlSource = getPageSqlSource(configuration, sqlSource, parameterObject);
}
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
//设置条件参数
for
(Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
}
return
boundSql;
}
}
/**
* 自定义ProviderSqlSource,代理方法
*/
private
class
MyProviderSqlSource
implements
SqlSource {
private
Configuration configuration;
private
ProviderSqlSource providerSqlSource;
/**
* 用于区分动态的count查询或分页查询
*/
private
Boolean count;
private
MyProviderSqlSource(Configuration configuration, ProviderSqlSource providerSqlSource, Boolean count) {
this
.configuration = configuration;
this
.providerSqlSource = providerSqlSource;
this
.count = count;
}
@Override
public
BoundSql getBoundSql(Object parameterObject) {
BoundSql boundSql =
null
;
if
(parameterObject
instanceof
Map && ((Map) parameterObject).containsKey(PROVIDER_OBJECT)) {
boundSql = providerSqlSource.getBoundSql(((Map) parameterObject).get(PROVIDER_OBJECT));
}
else
{
boundSql = providerSqlSource.getBoundSql(parameterObject);
}
if
(count) {
return
new
BoundSql(
configuration,
sqlParser.getCountSql(boundSql.getSql()),
boundSql.getParameterMappings(),
parameterObject);
}
else
{
return
new
BoundSql(
configuration,
sqlParser.getPageSql(boundSql.getSql()),
getPageParameterMapping(configuration, boundSql),
parameterObject);
}
}
}
/**
* 获取ms - 在这里对新建的ms做了缓存,第一次新增,后面都会使用缓存值
*
* @param ms
* @param sqlSource
* @param suffix
* @return
*/
private
MappedStatement getMappedStatement(MappedStatement ms, SqlSource sqlSource, Object parameterObject, String suffix) {
MappedStatement qs =
null
;
try
{
qs = ms.getConfiguration().getMappedStatement(ms.getId() + suffix);
}
catch
(Exception e) {
//ignore
}
if
(qs ==
null
) {
//创建一个新的MappedStatement
qs = newMappedStatement(ms, getsqlSource(ms, sqlSource, parameterObject, suffix), suffix);
try
{
ms.getConfiguration().addMappedStatement(qs);
}
catch
(Exception e) {
//ignore
}
}
return
qs;
}
/**
* 新建count查询和分页查询的MappedStatement
*
* @param ms
* @param sqlSource
* @param suffix
* @return
*/
private
MappedStatement newMappedStatement(MappedStatement ms, SqlSource sqlSource, String suffix) {
String id = ms.getId() + suffix;
MappedStatement.Builder builder =
new
MappedStatement.Builder(ms.getConfiguration(), id, sqlSource, 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());
if
(suffix == SUFFIX_PAGE) {
builder.resultMaps(ms.getResultMaps());
}
else
{
//count查询返回值int
List<ResultMap> resultMaps =
new
ArrayList<ResultMap>();
ResultMap resultMap =
new
ResultMap.Builder(ms.getConfiguration(), id,
int
.
class
, EMPTY_RESULTMAPPING).build();
resultMaps.add(resultMap);
builder.resultMaps(resultMaps);
}
builder.resultSetType(ms.getResultSetType());
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return
builder.build();
}
/**
* 判断当前执行的是否为动态sql
*
* @param ms
* @return
*/
public
boolean
isDynamic(MappedStatement ms) {
return
ms.getSqlSource()
instanceof
DynamicSqlSource;
}
/**
* 获取新的sqlSource
*
* @param ms
* @param sqlSource
* @param parameterObject
* @param suffix
* @return
*/
private
SqlSource getsqlSource(MappedStatement ms, SqlSource sqlSource, Object parameterObject, String suffix) {
//1. 从XMLLanguageDriver.java和XMLScriptBuilder.java可以看出只有两种SqlSource
//2. 增加注解情况的ProviderSqlSource
//3. 对于RawSqlSource需要进一步测试完善
//如果是动态sql
if
(isDynamic(ms)) {
MetaObject msObject = forObject(ms);
SqlNode sqlNode = (SqlNode) msObject.getValue(
"sqlSource.rootSqlNode"
);
MixedSqlNode mixedSqlNode =
null
;
if
(sqlNode
instanceof
MixedSqlNode) {
mixedSqlNode = (MixedSqlNode) sqlNode;
}
else
{
List<SqlNode> contents =
new
ArrayList<SqlNode>(
1
);
contents.add(sqlNode);
mixedSqlNode =
new
MixedSqlNode(contents);
}
return
new
MyDynamicSqlSource(ms.getConfiguration(), mixedSqlNode, suffix == SUFFIX_COUNT);
}
else
if
(sqlSource
instanceof
ProviderSqlSource) {
return
new
MyProviderSqlSource(ms.getConfiguration(), (ProviderSqlSource) sqlSource, suffix == SUFFIX_COUNT);
}
//如果是静态分页sql
else
if
(suffix == SUFFIX_PAGE) {
//改为分页sql
return
getPageSqlSource(ms.getConfiguration(), sqlSource, parameterObject);
}
//如果是静态count-sql
else
{
return
getCountSqlSource(ms.getConfiguration(), sqlSource, parameterObject);
}
}
/**
* 增加分页参数映射
*
* @param configuration
* @param boundSql
* @return
*/
private
List<ParameterMapping> getPageParameterMapping(Configuration configuration, BoundSql boundSql) {
List<ParameterMapping> newParameterMappings =
new
ArrayList<ParameterMapping>();
newParameterMappings.addAll(boundSql.getParameterMappings());
newParameterMappings.add(
new
ParameterMapping.Builder(configuration, PAGEPARAMETER_FIRST, Integer.
class
).build());
newParameterMappings.add(
new
ParameterMapping.Builder(configuration, PAGEPARAMETER_SECOND, Integer.
class
).build());
return
newParameterMappings;
}
/**
* 获取分页的sqlSource
*
* @param configuration
* @param sqlSource
* @return
*/
private
SqlSource getPageSqlSource(Configuration configuration, SqlSource sqlSource, Object parameterObject) {
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
return
new
StaticSqlSource(configuration, sqlParser.getPageSql(boundSql.getSql()), getPageParameterMapping(configuration, boundSql));
}
/**
* 获取count的sqlSource
*
* @param sqlSource
* @return
*/
private
SqlSource getCountSqlSource(Configuration configuration, SqlSource sqlSource, Object parameterObject) {
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
return
new
StaticSqlSource(configuration, sqlParser.getCountSql(boundSql.getSql()), boundSql.getParameterMappings());
}
/**
* 测试[控制台输出]count和分页sql
*
* @param dialet 数据库类型
* @param originalSql 原sql
*/
public
static
void
testSql(String dialet, String originalSql) {
SqlUtil sqlUtil =
new
SqlUtil(dialet);
String countSql = sqlUtil.sqlParser.getCountSql(originalSql);
System.out.println(countSql);
String pageSql = sqlUtil.sqlParser.getPageSql(originalSql);
System.out.println(pageSql);
}
}
PageList.java
import
java.util.ArrayList;
/**
* 分页
*
* @author
*
* @param <E>
* @createdate 2018年01月03日
*/
public
class
PageList<E>
extends
ArrayList<E> {
/**
*
*/
private
static
final
long
serialVersionUID = 1L;
private
Integer pageNum;
private
Integer pageSize;
private
Integer startRow;
private
Integer endRow;
private
Long total;
private
Long pages;
public
PageList() {
}
public
PageList(Integer pageNum, Integer pageSize) {
this
.pageNum = pageNum;
this
.pageSize = pageSize;
this
.startRow = pageNum >
0
? (pageNum -
1
) * pageSize :
0
;
this
.endRow = pageNum * pageSize;
}
public
Long getPages() {
return
pages;
}
public
void
setPages(Long pages) {
this
.pages = pages;
}
public
Integer getEndRow() {
return
endRow;
}
public
void
setEndRow(Integer endRow) {
this
.endRow = endRow;
}
public
Integer getPageNum() {
return
pageNum;
}
public
void
setPageNum(Integer pageNum) {
this
.pageNum = pageNum;
}
public
Integer getPageSize() {
return
pageSize;
}
public
void
setPageSize(Integer pageSize) {
this
.pageSize = pageSize;
}
public
Integer getStartRow() {
return
startRow;
}
public
void
setStartRow(Integer startRow) {
this
.startRow = startRow;
}
public
Long getTotal() {
return
total;
}
public
void
setTotal(Long total) {
this
.total = total;
}
@Override
public
String toString() {
return
"Page{"
+
"pageNum="
+ pageNum +
", pageSize="
+ pageSize +
", startRow="
+ startRow +
", endRow="
+ endRow +
", total="
+ total +
", pages="
+ pages +
'}'
;
}
}
Page.java
import
java.io.Serializable;
import
java.util.List;
/**
* @author
* @createdate 2018年01月03日
* */
public
class
Page<T>
implements
Serializable {
private
static
final
long
serialVersionUID = 1L;
private
Integer pageNum;
private
Integer pageSize;
private
Integer startRow;
private
Integer endRow;
private
Long total;
private
Long pages;
private
List<T> list;
public
Page() {
}
public
Page(Integer pageNum, Integer pageSize) {
this
.pageNum = pageNum;
this
.pageSize = pageSize;
this
.startRow = Integer.valueOf(pageNum.intValue() >
0
?(pageNum.intValue() -
1
) * pageSize.intValue():
0
);
this
.endRow = Integer.valueOf(pageNum.intValue() * pageSize.intValue());
}
public
List<T> getList() {
return
this
.list;
}
public
void
setList(List<T> list) {
this
.list = list;
}
public
Long getPages() {
return
this
.pages;
}
public
void
setPages(Long pages) {
this
.pages = pages;
}
public
Integer getEndRow() {
return
this
.endRow;
}
public
void
setEndRow(Integer endRow) {
this
.endRow = endRow;
}
public
Integer getPageNum() {
return
this
.pageNum;
}
public
void
setPageNum(Integer pageNum) {
this
.pageNum = pageNum;
}
public
Integer getPageSize() {
return
this
.pageSize;
}
public
void
setPageSize(Integer pageSize) {
this
.pageSize = pageSize;
}
public
Integer getStartRow() {
return
this
.startRow;
}
public
void
setStartRow(Integer startRow) {
this
.startRow = startRow;
}
public
Long getTotal() {
return
this
.total;
}
public
void
setTotal(Long total) {
this
.total = total;
}
public
String toString() {
return
"Page{pageNum="
+
this
.pageNum +
", pageSize="
+
this
.pageSize +
", startRow="
+
this
.startRow +
", endRow="
+
this
.endRow +
", total="
+
this
.total +
", pages="
+
this
.pages +
'}'
;
}
}
DbContextHolder.java
/**
* Title: AIDP_SMARTOS <br>
* Description: 数据源变量存储处,这里是个线程安全的ThreadLocal的包装<br>
* Date: 2018年01月03日 <br>
* Copyright (c) 2018 AIDP <br>
* @author
*/
public
class
DbContextHolder {
private
static
final
ThreadLocal<String> contextHolder =
new
ThreadLocal<String>();
public
static
void
setDBType(String dbType) {
contextHolder.set(dbType);
}
public
static
String getDBType() {
return
StringKit.isBlank(contextHolder.get()) ?
""
: contextHolder.get();
}
public
static
void
clearDBType() {
contextHolder.remove();
}
}
StringKit.java
/**
* @author
* @createdate 2018年01月03日
* */
public
class
StringKit {
public
static
String javaToDbFieldName(String name) {
StringBuilder result =
new
StringBuilder();
if
(notBlank(name) && name.indexOf(
"_"
) <
0
) {
result.append(name.substring(
0
,
1
).toLowerCase());
for
(
int
i =
1
; i < name.length(); ++i) {
String s = name.substring(i, i +
1
);
if
(s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(
0
))) {
result.append(
"_"
);
}
result.append(s.toLowerCase());
}
return
result.toString();
}
else
{
name = notBlank(name)?name:
""
;
return
name;
}
}
public
static
String dbToJavaFieldName(String name) {
StringBuilder result =
new
StringBuilder();
if
(notBlank(name)) {
name = name.toLowerCase();
for
(
int
i =
0
; i < name.length(); ++i) {
String s = name.substring(i, i +
1
);
if
(s.equals(
"_"
) && i < name.length() -
1
) {
++i;
s = name.substring(i, i +
1
);
result.append(s.toUpperCase());
}
else
{
result.append(s);
}
}
}
return
result.toString();
}
public
static
String firstCharToLowerCase(String str) {
char
firstChar = str.charAt(
0
);
if
(firstChar >=
65
&& firstChar <=
90
) {
char
[] arr = str.toCharArray();
arr[
0
] = (
char
)(arr[
0
] +
32
);
return
new
String(arr);
}
else
{
return
str;
}
}
public
static
String firstCharToUpperCase(String str) {
char
firstChar = str.charAt(
0
);
if
(firstChar >=
97
&& firstChar <=
122
) {
char
[] arr = str.toCharArray();
arr[
0
] = (
char
)(arr[
0
] -
32
);
return
new
String(arr);
}
else
{
return
str;
}
}
public
static
boolean
isBlank(String str) {
return
str ==
null
||
""
.equals(str.trim());
}
public
static
boolean
notBlank(String str) {
return
str !=
null
&& !
""
.equals(str.trim());
}
public
static
boolean
notBlank(String... strings) {
if
(strings ==
null
) {
return
false
;
}
else
{
String[] arr$ = strings;
int
len$ = strings.length;
for
(
int
i$ =
0
; i$ < len$; ++i$) {
String str = arr$[i$];
if
(str ==
null
||
""
.equals(str.trim())) {
return
false
;
}
}
return
true
;
}
}
public
static
boolean
notNull(Object... paras) {
if
(paras ==
null
) {
return
false
;
}
else
{
Object[] arr$ = paras;
int
len$ = paras.length;
for
(
int
i$ =
0
; i$ < len$; ++i$) {
Object obj = arr$[i$];
if
(obj ==
null
) {
return
false
;
}
}
return
true
;
}
}
public
static
String escapeNull(String str) {
return
notBlank(str)?str:
""
;
}
public
static
String addSlash(String path) {
return
path ==
null
?
"/"
:(path.startsWith(
"/"
)?path:
"/"
+ path);
}
}
BaseSvcUtil.java
import
java.util.ArrayList;
/**
* 后台服务统一工具类
* @author
* @since 2018年01月03日
* @history V0.1
*/
public
class
BaseSvcUtil {
public
static
<T> Page<T> getPage(PageList<T> pageList) {
Page<T> page =
new
Page<T>();
page.setPageNum(pageList.getPageNum());
page.setPageSize(pageList.getPageSize());
page.setStartRow(pageList.getStartRow());
page.setEndRow(pageList.getEndRow());
page.setPages(pageList.getPages());
page.setTotal(pageList.getTotal());
page.setList(
new
ArrayList<T>(pageList));
//page.setList(pageList.getList());
return
page;
}
}
eg:
public
Page<PatentVO> queryByNamePage(PatentVO patentVO) {
PageList<PatentVO> pageList = xxxVOMapper.queryByNamePage(patentVO);
if
(pageList!=
null
)
return
BaseSvcUtil.getPage(pageList);
else
return
null
;
}