package org.quickbundle.third.mybatis;
import java.sql.Connection;
import java.util.Properties;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
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.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.RowBounds;
import org.quickbundle.third.mybatis.dialect.DB2Dialect;
import org.quickbundle.third.mybatis.dialect.Dialect;
import org.quickbundle.third.mybatis.dialect.H2Dialect;
import org.quickbundle.third.mybatis.dialect.MySql5Dialect;
import org.quickbundle.third.mybatis.dialect.OracleDialect;
import org.quickbundle.third.mybatis.dialect.PostgreSQLDialect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class ScrollableStatementHandlerInterceptor implements Interceptor {
private final static Logger log = LoggerFactory.getLogger(ScrollableStatementHandlerInterceptor.class);
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, new DefaultObjectFactory(), new DefaultObjectWrapperFactory());
RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
if (rowBounds == null || rowBounds == RowBounds.DEFAULT || rowBounds.getOffset() < 0 || rowBounds.getLimit() < 0) {
return invocation.proceed();
}
Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration");
Dialect.Type databaseType = null;
try {
databaseType = Dialect.Type.valueOf(configuration.getVariables().getProperty("dialect").toUpperCase());
} catch (Exception e) {
// ignore
}
if (databaseType == null) {
throw new RuntimeException("the value of the dialect property in configuration.xml is not defined : "
+ configuration.getVariables().getProperty("dialect"));
}
Dialect dialect = null;
switch (databaseType) {
//TODO 新的数据库支持
case MYSQL:
dialect = new MySql5Dialect();
break;
case POSTGRESQL:
dialect = new PostgreSQLDialect();
break;
case H2:
dialect = new H2Dialect();
break;
case ORACLE:
dialect = new OracleDialect();
break;
case DB2:
dialect = new DB2Dialect();
break;
}
String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
metaStatementHandler.setValue("delegate.boundSql.sql", dialect.getLimitString(originalSql, rowBounds.getOffset(), rowBounds.getLimit()));
metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
if (log.isDebugEnabled()) {
log.debug("Generating scrollable SQL : " + boundSql.getSql());
}
return invocation.proceed();
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
}
}