MyBatis学习(八)- 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

[html]  view plain copy
  1. <?xml version="1.0"?>  
  2. <project  
  3.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"  
  4.     xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  
  5.     <modelVersion>4.0.0</modelVersion>  
  6.   
  7.     <groupId>org.ygy.demo</groupId>  
  8.     <artifactId>mybatis-parent</artifactId>  
  9.     <version>0.0.1-SNAPSHOT</version>  
  10.     <packaging>pom</packaging>  
  11.   
  12.   
  13.     <name>mybatis-parent</name>  
  14.     <url>http://maven.apache.org</url>  
  15.   
  16.     <dependencyManagement>  
  17.         <dependencies>  
  18.             <dependency>  
  19.                 <groupId>junit</groupId>  
  20.                 <artifactId>junit</artifactId>  
  21.                 <version>4.10</version>  
  22.                 <scope>test</scope>  
  23.             </dependency>   
  24.   
  25.             <dependency>  
  26.                 <groupId>org.mybatis</groupId>  
  27.                 <artifactId>mybatis</artifactId>  
  28.                 <version>3.1.1</version>  
  29.             </dependency>  
  30.   
  31.             <dependency>  
  32.                 <groupId>org.projectlombok</groupId>  
  33.                 <artifactId>lombok</artifactId>  
  34.                 <version>0.12.0</version>  
  35.             </dependency>  
  36.   
  37.             <dependency>  
  38.                 <groupId>com.oracle</groupId>  
  39.                 <artifactId>ojdbc14</artifactId>  
  40.                 <version>10.2.0.4.0</version>  
  41.             </dependency>  
  42.   
  43.             <dependency>  
  44.                 <groupId>log4j</groupId>  
  45.                 <artifactId>log4j</artifactId>  
  46.                 <version>1.2.17</version>  
  47.             </dependency>  
  48.   
  49.         </dependencies>  
  50.     </dependencyManagement>  
  51.   
  52.     <dependencies>  
  53.         <dependency>  
  54.             <groupId>junit</groupId>  
  55.             <artifactId>junit</artifactId>  
  56.         </dependency>  
  57.   
  58.         <dependency>  
  59.             <groupId>org.mybatis</groupId>  
  60.             <artifactId>mybatis</artifactId>  
  61.         </dependency>  
  62.   
  63.         <dependency>  
  64.             <groupId>org.projectlombok</groupId>  
  65.             <artifactId>lombok</artifactId>  
  66.         </dependency>  
  67.   
  68.         <dependency>  
  69.             <groupId>com.oracle</groupId>  
  70.             <artifactId>ojdbc14</artifactId>  
  71.         </dependency>  
  72.   
  73.         <dependency>  
  74.             <groupId>log4j</groupId>  
  75.             <artifactId>log4j</artifactId>  
  76.         </dependency>  
  77.     </dependencies>  
  78.   
  79.     <build>  
  80.         <plugins>  
  81.             <plugin>  
  82.                 <groupId>org.apache.maven.plugins</groupId>  
  83.                 <artifactId>maven-compiler-plugin</artifactId>  
  84.                 <configuration>  
  85.                     <source>1.6</source>  
  86.                     <target>1.6</target>  
  87.                 </configuration>  
  88.             </plugin>  
  89.         </plugins>  
  90.     </build>  
  91.   
  92.     <modules>  
  93.         <module>mybatis-hello</module>  
  94.         <module>mybatis-relevance</module>  
  95.         <module>mybatis-common</module>  
  96.         <module>mybatis-page</module>  
  97.     </modules>  
  98. </project>  

自身项目 mybatis-page的pom没有特殊配置

在使用Maven,引入Oracle依赖的时候,挺纠结的,需要费点事,详情可以搜一下,以后可能会分享下

MyBatisUtil类

[java]  view plain copy
  1. package org.ygy.demo.mybatis.common.util;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5.   
  6. import org.apache.ibatis.io.Resources;  
  7. import org.apache.ibatis.session.SqlSession;  
  8. import org.apache.ibatis.session.SqlSessionFactory;  
  9. import org.apache.ibatis.session.SqlSessionFactoryBuilder;  
  10.   
  11. public class MyBatisUtil {  
  12.   
  13.     private static SqlSessionFactory factory = null;  
  14.   
  15.     private static void initialFactory() {  
  16.         String resource = "mybatis-config.xml";  
  17.         try {  
  18.             InputStream in = Resources.getResourceAsStream(resource);  
  19.             factory = new SqlSessionFactoryBuilder().build(in);  
  20.         } catch (IOException e) {  
  21.             e.printStackTrace();  
  22.         }  
  23.   
  24.     }  
  25.   
  26.     public static SqlSession getSession() {  
  27.         if (factory == null) {  
  28.             initialFactory();  
  29.         }  
  30.   
  31.         return factory.openSession();  
  32.     }  
  33. }  

2.实现分页

使用MyBatis实现分页的一种方法是使用拦截器,自定义一个拦截器插件,然后,将SQL语句转换成3层嵌套的SQL语句.

一下代码参考上面的博客,自己加了注释,

主要是实现一个拦截器插件:

[java]  view plain copy
  1. package org.ygy.demo.mybatis.page.dialect;  
  2.   
  3. import java.sql.Connection;  
  4. import java.util.Properties;  
  5.   
  6. import org.apache.ibatis.executor.statement.StatementHandler;  
  7. import org.apache.ibatis.logging.Log;  
  8. import org.apache.ibatis.logging.LogFactory;  
  9. import org.apache.ibatis.mapping.BoundSql;  
  10. import org.apache.ibatis.plugin.Interceptor;  
  11. import org.apache.ibatis.plugin.Intercepts;  
  12. import org.apache.ibatis.plugin.Invocation;  
  13. import org.apache.ibatis.plugin.Plugin;  
  14. import org.apache.ibatis.plugin.Signature;  
  15. import org.apache.ibatis.reflection.MetaObject;  
  16. import org.apache.ibatis.session.Configuration;  
  17. import org.apache.ibatis.session.RowBounds;  
  18.   
  19. /** 
  20.  *  
  21.  * @author yuguiyang 
  22.  * @description 然后就是实现mybatis提供的拦截器接口,编写我们自己的分页实现,原理就是拦截底层JDBC操作相关的Statement对象, 
  23.  *              把前端的分页参数如当前记录索引和每页大小通过拦截器注入到sql语句中 
  24.  *              ,即在sql执行之前通过分页参数重新生成分页sql,而具体的分页sql实现是分离到Dialect接口中去。 
  25.  * @time 2013-8-23 
  26.  * @version V1.0 
  27.  */  
  28. @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })  
  29. public class PageInterceptor implements Interceptor {  
  30.   
  31.     private final static Log log = LogFactory.getLog(PageInterceptor.class);  
  32.   
  33.     @Override  
  34.     public Object intercept(Invocation invocation) throws Throwable {  
  35.         StatementHandler statementHandler = (StatementHandler) invocation.getTarget();  
  36.         BoundSql boundSql = statementHandler.getBoundSql();  
  37.   
  38.         //元数据  
  39.         MetaObject metaObject = MetaObject.forObject(statementHandler);  
  40.         //分页参数  
  41.         RowBounds rowBounds = (RowBounds) metaObject.getValue("delegate.rowBounds");  
  42.         if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {  
  43.             //如果没有提供RowBounds的,则不做操作  
  44.         } else {  
  45.             //获取配置文件参数  
  46.             Configuration configuration = (Configuration) metaObject.getValue("delegate.configuration");  
  47.             //读取配置文件中的配置,确认是什么分页实现  
  48.             Dialect dialect = DialectFactory.createDialect(configuration.getVariables().getProperty("dialect"));  
  49.   
  50.             String originalSql = (String) metaObject.getValue("delegate.boundSql.sql");  
  51.             metaObject.setValue("delegate.boundSql.sql",  
  52.                     dialect.changeToPageSql(originalSql, rowBounds.getOffset(), rowBounds.getLimit()));  
  53.             metaObject.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);  
  54.             metaObject.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);  
  55.   
  56.             //输出日志  
  57.             if (log.isDebugEnabled()) {  
  58.                 log.debug("生成分页SQL : " + boundSql.getSql());  
  59.             }  
  60.         }  
  61.           
  62.         return invocation.proceed();  
  63.           
  64.     }  
  65.   
  66.     @Override  
  67.     public Object plugin(Object target) {  
  68.         return Plugin.wrap(target, this);  
  69.     }  
  70.   
  71.     @Override  
  72.     public void setProperties(Properties properties) {  
  73.   
  74.     }  
  75.   
  76. }  
[java]  view plain copy
  1. package org.ygy.demo.mybatis.page.dialect;  
  2.   
  3. /** 
  4.  *  
  5.  * @author yuguiyang 
  6.  * @description Oracle的分页实现 
  7.  * @time 2013-8-26 
  8.  * @version V1.0 
  9.  */  
  10. public class OracleDialect implements Dialect {  
  11.   
  12.     @Override  
  13.     public String changeToPageSql(String sql, int start, int pageSize) {  
  14.         //去除SQL手尾的空格  
  15.         sql = sql.trim();  
  16.           
  17.         boolean isForUpdate = false;  
  18.           
  19.         if (sql.toLowerCase().endsWith(" for update")) {  
  20.             sql = sql.substring(0, sql.length() - 11);  
  21.             isForUpdate = true;  
  22.         }  
  23.           
  24.         //将SQL构造为分页SQL  
  25.         StringBuffer pageSql = new StringBuffer(sql.length() + 100);  
  26.         pageSql.append("select * from ( select row_.*, rownum rownum_ from ( ");  
  27.         pageSql.append(sql);  
  28.         pageSql.append(" ) row_ ) where rownum_ > " + start + " and rownum_ <= " + (start + pageSize));  
  29.           
  30.         if (isForUpdate) {  
  31.             pageSql.append(" for update");  
  32.         }  
  33.           
  34.         return pageSql.toString();  
  35.     }  
  36.   
  37. }  

接下来是配置文件:

[html]  view plain copy
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2.   
  3. <!DOCTYPE configuration  
  4.   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
  5.   "http://mybatis.org/dtd/mybatis-3-config.dtd">  
  6.       
  7. <configuration>  
  8.   
  9.     <!-- 配置数据库分页的实现 -->  
  10.     <properties>    
  11.         <property name="dialect" value="oracle" />   
  12.         <property name="databaseType" value="oracle"></property>   
  13.     </properties>    
  14.         
  15.     <!-- 全局别名设置,在映射文件中只需写别名,而不必写出整个类路径  -->  
  16.     <typeAliases>    
  17.          <typeAlias type="org.ygy.demo.mybatis.entity.PersonEntity" alias="PersonEntity"></typeAlias>  
  18.          <typeAlias type="org.ygy.demo.mybatis.entity.BlogEntity" alias="BlogEntity"></typeAlias>  
  19.     </typeAliases>   
  20.       
  21.     <!-- 配置插件 -->  
  22.     <plugins>  
  23.         <!-- 配置拦截器插件 -->  
  24.        <!--  <plugin interceptor="org.ygy.demo.mybatis.page.dialect.PageInterceptor"></plugin>  
  25.         <plugin interceptor="org.ygy.demo.mybatis.interceptor.SimpleInterceptor"></plugin> -->  
  26.         <plugin interceptor="org.ygy.demo.mybatis.interceptor.PageInterceptor"></plugin>    
  27.     </plugins>    
  28.       
  29.     <environments default="development">  
  30.         <environment id="development">  
  31.             <transactionManager type="JDBC" />  
  32.             <dataSource type="POOLED">  
  33.                 <property name="driver" value="oracle.jdbc.OracleDriver" />  
  34.                 <property name="url" value="jdbc:oracle:thin:@192.168.17.254:1521:dpweb" />  
  35.                 <property name="username" value="dptest" />  
  36.                 <property name="password" value="dptest" />  
  37.             </dataSource>  
  38.         </environment>  
  39.     </environments>  
  40.   
  41.     <!-- 配置映射文件地址 -->  
  42.     <mappers>  
  43.          <mapper resource="org/ygy/demo/mybatis/mapper/blog-mapper.xml"></mapper>  
  44.     </mappers>  
  45.       
  46. </configuration>  

注意:上面的拦截器在实现的时候,使用的是RowBounds来分页查询,所以实现时:

[java]  view plain copy
  1. @Override  
  2.     public List<BlogEntity> queryWithPage(RowBounds rowBounds) {  
  3.         SqlSession session = MyBatisUtil.getSession();  
  4.         List<BlogEntity> blogs = session.selectList(NAMESPACE + ".queryWithPage" , null , rowBounds);  
  5.           
  6.         session.commit();  
  7.         session.close();  
  8.           
  9.         return blogs;  
  10.     }  

也需要传递RowBounds

测试:

[java]  view plain copy
  1. @Test  
  2.     public void testQueryWithPage() {   
  3.         RowBounds rowBounds = new RowBounds(0 , 2);  
  4.           
  5.         List<BlogEntity> blogs = blogDao.queryWithPage(rowBounds);  
  6.           
  7.         for(BlogEntity blog : blogs) {  
  8.             System.out.println("--blog:" + blog);  
  9.         }  
  10.     }  

在实现拦截器时,还有另一种方法,道理是一样的,会在一篇博客中简单说一下。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值