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) { } }