@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class MybatisPageInterceptor implements Interceptor, LogUtils {
private static final String DELEGATE_ROW_BOUNDS_LIMIT = "delegate.rowBounds.limit";
private static final String DELEGATE_ROW_BOUNDS_OFFSET = "delegate.rowBounds.offset";
private static final String DELEGATE_BOUND_SQL_SQL = "delegate.boundSql.sql";
private static final String DELEGATE_MAPPED_STATEMENT = "delegate.mappedStatement";
private static final DefaultObjectFactory DEF_OBJECT_FACTORY = new DefaultObjectFactory();
private static final DefaultObjectWrapperFactory DEF_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
private static final String SQL_SELECT_REGEX = "(?is)^\\s*SELECT.*$";
private static final String pageMapper = ".*WithPage$";
private static final String SQL_LIKE_ESCAPE_REGEX = "[likeLIKE]+ +\\?";
private IDialect dialect;
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation
.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
MetaObject metaStatementHandler = MetaObject.forObject(
statementHandler, DEF_OBJECT_FACTORY,
DEF_OBJECT_WRAPPER_FACTORY);
MappedStatement mappedStatement = (MappedStatement) metaStatementHandler
.getValue(DELEGATE_MAPPED_STATEMENT);
String originalSql = boundSql.getSql();
originalSql = originalSql.replaceAll(SQL_LIKE_ESCAPE_REGEX, "like ? escape '/'");
// 从线程变量中获取分页信息
PageInfo page = ThreadContext.get().getPageInfo();
try {
// 如果没有分页参数,不分页
if (StringUtils.isBlank(originalSql) || null == page
|| null == page.getCount()) {
metaStatementHandler.setValue(DELEGATE_BOUND_SQL_SQL,originalSql);
return invocation.proceed();
}
// 如果非查询方法,且不以“WithPage”结尾
if (!originalSql.matches(SQL_SELECT_REGEX)
|| !mappedStatement.getId().matches(pageMapper)) {
return invocation.proceed();
}
metaStatementHandler.setValue(DELEGATE_BOUND_SQL_SQL, dialect
.getPageSql(originalSql, page.getStart().intValue(), page
.getLimit().intValue()));
metaStatementHandler.setValue(DELEGATE_ROW_BOUNDS_OFFSET,
RowBounds.NO_ROW_OFFSET);
metaStatementHandler.setValue(DELEGATE_ROW_BOUNDS_LIMIT,
RowBounds.NO_ROW_LIMIT);
if (LOG.isDebugEnabled()) {
LOG.debug("生成分页SQL:\n{}", boundSql.getSql());
}
return invocation.proceed();
} catch (Exception e) {
throw new BusinessException(CommonConstants.ERROR_DB, e);
}
}
@Override
public Object plugin(Object arg0) {
return Plugin.wrap(arg0, this);
}
@Override
public void setProperties(Properties arg0) {
// TODO Auto-generated method stub
}
public IDialect getDialect() {
return dialect;
}
public void setDialect(IDialect dialect) {
this.dialect = dialect;
}
}