这期快乐女生,黄英看样子要被PK下去。但我估计会是李霄云诶.- -#
老婆在看快乐女生,本来说陪老婆看今天不弄了,不过还是放心不下,时间太短,只好又打开电脑,把这几天一直在考虑的一件事情给弄了,使ibatis支持数据库物理分页,要不然的话,回头等到东西都弄完后再整更麻烦。
本来想还需要看下ibatis的代码,跟着瞅下中间的实现机制,结果网上Google了下发现,N多的方法,已经有达人解决这个问题了,嘿,看来逻辑分页大家都不喜欢诶,正好,赶时间,直接先copy过来,回头整理的时间再看看能有否扩充没吧。
把代码整个copy过来,大家也可以参考下。(最原始的出处已经不详了,搜索了下,应该出处自:http://blog.csdn.net/duanaiguo/archive/2006/11/23/1408398.aspx此篇文章,但此篇文章已经打不开,博主貌似转到了javaeye了,随后跟进到javaeye,结果很遗憾,javaeye打不开,貌似今天一天都打不开了,但估计原创作者应该是此位duanaiguo,希望大家如有转载能保留以下链接,谢谢!内容不包含对ibatis的源码分析,只列出解决的步骤)
转载自:http://duanaiguo.javaeye.com
作者:duanaiguo
1.覆盖ibatis默认的SQL执行方法,覆盖executeQuery
package com.javaing.dao.ibatis.ext;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.javaing.dao.ibatis.Dialect;
import com.ibatis.sqlmap.engine.execution.SqlExecutor;
import com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback;
import com.ibatis.sqlmap.engine.scope.RequestScope;
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;
}
@Override
public void executeQuery(RequestScope request, 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 = NO_SKIPPED_RESULTS;
maxResults = NO_MAXIMUM_RESULTS;
}
super.executeQuery(request, conn, sql, parameters, skipResults,
maxResults, callback);
}
public boolean supportsLimit() {
if (enableLimit && dialect != null) {
return dialect.supportsLimit();
}
return false;
}
}
2.创建Dialect接口,如果以后需要扩展oracle或者其他,实现此中方法
package com.javaing.dao.ibatis;
public interface Dialect {
public boolean supportsLimit();
public String getLimitString(String sql, boolean hasOffset);
public String getLimitString(String sql, int offset, int limit);
}
3.实现Dialect接口mysql下的实现
package com.javaing.dao.ibatis;
public class JavaingMySQLDialect implements Dialect {
protected static final String SQL_END_DELIMITER = ";";
public String getLimitString(String sql, boolean hasOffset) {
return new StringBuffer(sql.length() + 20).append(trim(sql)).append(
hasOffset ? " limit ?,?" : " limit ?")
.append(SQL_END_DELIMITER).toString();
}
public String getLimitString(String sql, int offset, int limit) {
sql = trim(sql);
StringBuffer sb = new StringBuffer(sql.length() + 20);
sb.append(sql);
if (offset > 0) {
sb.append(" limit ").append(offset).append(',').append(limit)
.append(SQL_END_DELIMITER);
} else {
sb.append(" limit ").append(limit).append(SQL_END_DELIMITER);
}
return sb.toString();
}
public boolean supportsLimit() {
return true;
}
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;
}
}
4.把LimitSqlExecutor注入到Spring中去
package com.javaing.dao.ibatis;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.engine.execution.SqlExecutor;
import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;
import com.javaing.dao.ibatis.ext.LimitSqlExecutor;
public abstract class BaseDaoiBatis extends SqlMapClientDaoSupport {
private SqlExecutor sqlExecutor;
public SqlExecutor getSqlExecutor() {
return sqlExecutor;
}
public void setSqlExecutor(SqlExecutor sqlExecutor) {
this.sqlExecutor = sqlExecutor;
}
public void setEnableLimit(boolean enableLimit) {
if (sqlExecutor instanceof LimitSqlExecutor) {
((LimitSqlExecutor) sqlExecutor).setEnableLimit(enableLimit);
}
}
public void initialize() throws Exception {
if (sqlExecutor != null) {
SqlMapClient sqlMapClient = getSqlMapClientTemplate()
.getSqlMapClient();
if (sqlMapClient instanceof ExtendedSqlMapClient) {
ReflectUtil.setFieldValue(((ExtendedSqlMapClient) sqlMapClient)
.getDelegate(), "sqlExecutor", SqlExecutor.class,
sqlExecutor);
}
}
}
}
5.利用initialize方法执行注入,在spring中配置init就可以了,然后因为sqlExecutor是私有成员,没有set方法此处只能利用反射机制
package com.javaing.dao.ibatis;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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);
}
}
}
}
}
6.配置spring bean
<!-- 父类DAO,所有dao类基于此类 -->
<bean id="baseDao" abstract="true"
class="com.javaing.dao.ibatis.BaseDaoiBatis"
init-method="initialize">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="sqlMapClient">
<ref bean="sqlMapClient" />
</property>
<property name="sqlExecutor">
<ref bean="sqlExecutor" />
</property>
</bean>
OK,就这么多,后面直接使用就可以了,因为以前的DAO都是继承SqlMapClientDaoSupport类的,现在直接继承自BaseDaoiBatis就可以了,使用queryForList方法直接分页查询就可以了,可以debug下看看输出日志,嘿,这下心里爽多了,明天把代码修改下,然后增加上以前的一个分页标记,OK!