MyBatis分页实现 - Oracle
最近学习了一下,怎样使用MyBatis实现分页。
同样的参考了很多博客:
http://haohaoxuexi.iteye.com/blog/1851081
http://xdwangiflytek.iteye.com/blog/1750641
自己总结如下:
1.准备
要实现分页,首先要有MyBatis的基本环境:Mybatis的jar包,配置文件,映射文件,Oracle驱动包......
在练习时,使用Maven,附上pom文件
mybatis-parent的pom.xml
4.0.0 org.ygy.demo mybatis-parent 0.0.1-SNAPSHOT pom mybatis-parent http://maven.apache.org junit junit 4.10 test org.mybatis mybatis 3.1.1 org.projectlombok lombok 0.12.0 com.oracle ojdbc14 10.2.0.4.0 log4j log4j 1.2.17 junit junit org.mybatis mybatis org.projectlombok lombok com.oracle ojdbc14 log4j log4j org.apache.maven.plugins maven-compiler-plugin 1.6 1.6 mybatis-hello mybatis-relevance mybatis-common mybatis-page
自身项目 mybatis-page的pom没有特殊配置
在使用Maven,引入Oracle依赖的时候,挺纠结的,需要费点事,详情可以搜一下,以后可能会分享下
MyBatisUtil类
package org.ygy.demo.mybatis.common.util;import java.io.IOException;
import java.io.InputStream;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class MyBatisUtil {private static SqlSessionFactory factory = null;private static void initialFactory() {String resource = "mybatis-config.xml";try {InputStream in = Resources.getResourceAsStream(resource);factory = new SqlSessionFactoryBuilder().build(in);} catch (IOException e) {e.printStackTrace();}}public static SqlSession getSession() {if (factory == null) {initialFactory();}return factory.openSession();}
}
2.实现分页
使用MyBatis实现分页的一种方法是使用拦截器,自定义一个拦截器插件,然后,将SQL语句转换成3层嵌套的SQL语句.
一下代码参考上面的博客,自己加了注释,
主要是实现一个拦截器插件:
package org.ygy.demo.mybatis.page.dialect;import java.sql.Connection;
import java.util.Properties;import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
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.session.Configuration;
import org.apache.ibatis.session.RowBounds;/*** * @author yuguiyang* @description 然后就是实现mybatis提供的拦截器接口,编写我们自己的分页实现,原理就是拦截底层JDBC操作相关的Statement对象,* 把前端的分页参数如当前记录索引和每页大小通过拦截器注入到sql语句中* ,即在sql执行之前通过分页参数重新生成分页sql,而具体的分页sql实现是分离到Dialect接口中去。* @time 2013-8-23* @version V1.0*/
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PageInterceptor implements Interceptor {private final static Log log = LogFactory.getLog(PageInterceptor.class);@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler = (StatementHandler) invocation.getTarget();BoundSql boundSql = statementHandler.getBoundSql();//元数据MetaObject metaObject = MetaObject.forObject(statementHandler);//分页参数RowBounds rowBounds = (RowBounds) metaObject.getValue("delegate.rowBounds");if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {//如果没有提供RowBounds的,则不做操作} else {//获取配置文件参数Configuration configuration = (Configuration) metaObject.getValue("delegate.configuration");//读取配置文件中的配置,确认是什么分页实现Dialect dialect = DialectFactory.createDialect(configuration.getVariables().getProperty("dialect"));String originalSql = (String) metaObject.getValue("delegate.boundSql.sql");metaObject.setValue("delegate.boundSql.sql",dialect.changeToPageSql(originalSql, rowBounds.getOffset(), rowBounds.getLimit()));metaObject.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);metaObject.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);//输出日志if (log.isDebugEnabled()) {log.debug("生成分页SQL : " + boundSql.getSql());}}return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}}
package org.ygy.demo.mybatis.page.dialect;/*** * @author yuguiyang* @description Oracle的分页实现* @time 2013-8-26* @version V1.0*/
public class OracleDialect implements Dialect {@Overridepublic String changeToPageSql(String sql, int start, int pageSize) {//去除SQL手尾的空格sql = sql.trim();boolean isForUpdate = false;if (sql.toLowerCase().endsWith(" for update")) {sql = sql.substring(0, sql.length() - 11);isForUpdate = true;}//将SQL构造为分页SQLStringBuffer pageSql = new StringBuffer(sql.length() + 100);pageSql.append("select * from ( select row_.*, rownum rownum_ from ( ");pageSql.append(sql);pageSql.append(" ) row_ ) where rownum_ > " + start + " and rownum_ <= " + (start + pageSize));if (isForUpdate) {pageSql.append(" for update");}return pageSql.toString();}}
接下来是配置文件:
注意:上面的拦截器在实现的时候,使用的是RowBounds来分页查询,所以实现时:
@Overridepublic List queryWithPage(RowBounds rowBounds) {SqlSession session = MyBatisUtil.getSession();List blogs = session.selectList(NAMESPACE + ".queryWithPage" , null , rowBounds);session.commit();session.close();return blogs;}
也需要传递RowBounds
测试:
@Testpublic void testQueryWithPage() { RowBounds rowBounds = new RowBounds(0 , 2);List blogs = blogDao.queryWithPage(rowBounds);for(BlogEntity blog : blogs) {System.out.println("--blog:" + blog);}}
在实现拦截器时,还有另一种方法,道理是一样的,会在一篇博客中简单说一下。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
