spring3.2+ibatis2.3.4.726 不改jar实现物理分页机制,不影响其他查询。

由于项目组要换技术,初来乍到,第一次接触ibatis,使用过程中发现ibatis的分页机制不是太好,是把该表的所有数据全部load出来然后通过java去把传的页数截出来return出来。这样会影响一些查询性能,通过看了ibatis执行sql的类是SqlExecutor,但它没有实现任何接口,这样是有点硬伤了,接下来我们使用spring注入方法的方式来实现hibernate方言机制物理分页。

第一个类:Dialect 接口,实现各种数据库分页方式,用Oracle做例子

public interface Dialect {
 /**
  * 是否分页
  * @return 
  * @author lim
  */
 public boolean supportsLimit();
 /**
  * 从什么位置开始
  * @param sql
  * @param hasOffset
  * @return 
  * @author lim
  */
 public String getLimitString(String sql, boolean hasOffset);
 /**
  * 实现物理分页
  * @param sql
  * @param offset 开始
  * @param limit 结束
  * @return sql
  * @author lim
  */
 public String getLimitString(String sql, int offset, int limit);
}


 

第二个类:OracleDialect 用Oracle做例子,MySql的话可以自己继承Dialect进行扩展

public class OracleDialect implements Dialect {
 protected static final String SQL_END_DELIMITER = ";";
 /**
  * sql组装分页
  * @param sql
  * @param offset
  * @param limit
  * @return 
  */
 public String getLimitString(String sql, int offset, int limit) {
  sql = trim(sql);
  StringBuffer sb = new StringBuffer(sql.length() + 20);
  sb.append("select * from ( select sq.*, rownum as rn from (");
  sb.append(this.trim(sql));
  sb.append(") sq)row_limit where row_limit.rn between ");
  sb.append(limit * (offset-1) + 1);
  sb.append(" and ");
  sb.append(limit * offset);
  return sb.toString();
 }
 public boolean supportsLimit() {
  return true;
 }
 
 /**
  * 去掉分号
  * @param sql
  * @return 
  * @author lim
  */
 private String trim(String sql) {
  sql = sql.trim();
  if (sql.endsWith(SQL_END_DELIMITER)) {
   sql = sql.substring(0, sql.length() - 1
     - SQL_END_DELIMITER.length());
  }
  return sql;
 }
}


 

接下来,我们使用一个类继承SqlExecutor覆盖他的executeQuery方法进行物理分页

import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.ibatis.sqlmap.engine.execution.SqlExecutor;
import com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback;
import com.ibatis.sqlmap.engine.scope.StatementScope;
 
public class LimitSqlExecutor extends SqlExecutor {
 
 private static final Log logger = LogFactory.getLog(LimitSqlExecutor.class);
 private Dialect dialect;
 private boolean enableLimit = true;
 public Dialect getDialect() {
  return dialect;
 }
 public void setDialect(Dialect dialect) {
  this.dialect = dialect;
 }
 public boolean isEnableLimit() {
  return enableLimit;
 }
 public void setEnableLimit(boolean enableLimit) {
  this.enableLimit = enableLimit;
 }
 
 /**
  * 重写ibatis执行sql方法
  * @param statementScope
  * @param conn
  * @param sql
  * @param parameters
  * @param skipResults
  * @param maxResults
  * @param callback
  * @throws SQLException 
  * @see com.ibatis.sqlmap.engine.execution.SqlExecutor#executeQuery(com.ibatis.sqlmap.engine.scope.StatementScope, java.sql.Connection, java.lang.String, java.lang.Object[], int, int, com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback)
  */
 public void executeQuery(StatementScope statementScope, Connection conn,
   String sql, Object[] parameters, int skipResults, int maxResults,
   RowHandlerCallback callback) throws SQLException {
  if ((skipResults != NO_SKIPPED_RESULTS || maxResults != NO_MAXIMUM_RESULTS) && supportsLimit()) {
   sql = dialect.getLimitString(sql, skipResults, maxResults);
   if (logger.isDebugEnabled()) {
    logger.debug(sql);
   }
   /** 设置skipResults为SqlExecutor不分页   设置maxResults为SqlExecutor不分页 */
   skipResults = NO_SKIPPED_RESULTS;
   maxResults = NO_MAXIMUM_RESULTS;
   System.out.println(sql);
  }
  super.executeQuery(statementScope, conn, sql, parameters, skipResults,
    maxResults, callback);
 }
 /**
  * @return 
  * @author lim
  */
 public boolean supportsLimit() {
  if (enableLimit && dialect != null) {
   return dialect.supportsLimit();
  }
  return false;
 }
}


第四个类:ReflectUtil 用于spring方法注入util

public class ReflectUtil {
 private static final Log logger = LogFactory.getLog(ReflectUtil.class);
 public static void setFieldValue(Object target, String fname, Class ftype,
   Object fvalue) {
  if (target == null
    || fname == null
    || "".equals(fname)
    || (fvalue != null && !ftype
      .isAssignableFrom(fvalue.getClass()))) {
   return;
  }
  Class clazz = target.getClass();
  try {
   Method method = clazz.getDeclaredMethod("set"
     + Character.toUpperCase(fname.charAt(0))
     + fname.substring(1), ftype);
   if (!Modifier.isPublic(method.getModifiers())) {
    method.setAccessible(true);
   }
   method.invoke(target, fvalue);
  } catch (Exception me) {
   if (logger.isDebugEnabled()) {
    logger.debug(me);
   }
   try {
    Field field = clazz.getDeclaredField(fname);
    if (!Modifier.isPublic(field.getModifiers())) {
     field.setAccessible(true);
    }
    field.set(target, fvalue);
   } catch (Exception fe) {
    if (logger.isDebugEnabled()) {
     logger.debug(fe);
    }
   }
  }
 }
 public static Object getFieldValue(Object target, String fname) {
  Object reslut = null;
  if (target == null || fname == null || "".equals(fname)) {
   return null;
  }
  Class clazz = target.getClass();
  try {
   Field field = clazz.getDeclaredField(fname);
   reslut = field.get(fname);
  } catch (Exception me) {
   if (logger.isDebugEnabled()) {
    logger.debug(me);
   }
  }
  return reslut;
 }
}


 

 

第五个类:BaseDaoiBatis

public abstract class BaseDaoiBatis {
 
 /** ibatis执行sql类 */
 @Resource
 private SqlExecutor sqlExecutor;
 
 /**  */
 @Resource
 protected SqlMapClient sqlMapClient;
 
 /**
  * 把dialect注入到ibatis的sqlExecutor
  * @throws Exception 
  * @author lim
  */
 @PostConstruct
 public void initialize() throws Exception {
  if (sqlExecutor != null) {
   if (sqlMapClient instanceof ExtendedSqlMapClient) {
    ReflectUtil.setFieldValue(((ExtendedSqlMapClient) sqlMapClient)
      .getDelegate(), "sqlExecutor", SqlExecutor.class,
      sqlExecutor);
   }
  }
 }
 
 public void setEnableLimit(boolean enableLimit) {
  if (sqlExecutor instanceof LimitSqlExecutor) {
   ((LimitSqlExecutor) sqlExecutor).setEnableLimit(enableLimit);
  }
 }
}


 

好了,这样启动的时候调用BaseDaoIBatis的initialize()方法将我们的SqlExecutor注入到ibatis就可以了会自动覆盖ibatis的executeQuery方法

接下来是spring的注入

 

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="configLocation" value="classpath:config/deploy/ibatis-conf.xml" />
  <property name="dataSource" ref="dataSource" />
 </bean>
 <bean id="sqlExecutor" class="cn.com.topinfo.exam.code.ibatis.LimitSqlExecutor">
  <property name="dialect">
   <bean class="cn.com.topinfo.exam.code.ibatis.OracleDialect" />
  </property>
 </bean>


 

用的时候我们的BaseDaoImpl只需要继承BaseDaoIBatis就可以了,用sqlMapClient去实现对数据库的操作


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值