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.0modelVersion>  
  6.   
  7.     <groupId>org.ygy.demogroupId>  
  8.     <artifactId>mybatis-parentartifactId>  
  9.     <version>0.0.1-SNAPSHOTversion>  
  10.     <packaging>pompackaging>  
  11.   
  12.   
  13.     <name>mybatis-parentname>  
  14.     <url>http://maven.apache.orgurl>  
  15.   
  16.     <dependencyManagement>  
  17.         <dependencies>  
  18.             <dependency>  
  19.                 <groupId>junitgroupId>  
  20.                 <artifactId>junitartifactId>  
  21.                 <version>4.10version>  
  22.                 <scope>testscope>  
  23.             dependency>   
  24.   
  25.             <dependency>  
  26.                 <groupId>org.mybatisgroupId>  
  27.                 <artifactId>mybatisartifactId>  
  28.                 <version>3.1.1version>  
  29.             dependency>  
  30.   
  31.             <dependency>  
  32.                 <groupId>org.projectlombokgroupId>  
  33.                 <artifactId>lombokartifactId>  
  34.                 <version>0.12.0version>  
  35.             dependency>  
  36.   
  37.             <dependency>  
  38.                 <groupId>com.oraclegroupId>  
  39.                 <artifactId>ojdbc14artifactId>  
  40.                 <version>10.2.0.4.0version>  
  41.             dependency>  
  42.   
  43.             <dependency>  
  44.                 <groupId>log4jgroupId>  
  45.                 <artifactId>log4jartifactId>  
  46.                 <version>1.2.17version>  
  47.             dependency>  
  48.   
  49.         dependencies>  
  50.     dependencyManagement>  
  51.   
  52.     <dependencies>  
  53.         <dependency>  
  54.             <groupId>junitgroupId>  
  55.             <artifactId>junitartifactId>  
  56.         dependency>  
  57.   
  58.         <dependency>  
  59.             <groupId>org.mybatisgroupId>  
  60.             <artifactId>mybatisartifactId>  
  61.         dependency>  
  62.   
  63.         <dependency>  
  64.             <groupId>org.projectlombokgroupId>  
  65.             <artifactId>lombokartifactId>  
  66.         dependency>  
  67.   
  68.         <dependency>  
  69.             <groupId>com.oraclegroupId>  
  70.             <artifactId>ojdbc14artifactId>  
  71.         dependency>  
  72.   
  73.         <dependency>  
  74.             <groupId>log4jgroupId>  
  75.             <artifactId>log4jartifactId>  
  76.         dependency>  
  77.     dependencies>  
  78.   
  79.     <build>  
  80.         <plugins>  
  81.             <plugin>  
  82.                 <groupId>org.apache.maven.pluginsgroupId>  
  83.                 <artifactId>maven-compiler-pluginartifactId>  
  84.                 <configuration>  
  85.                     <source>1.6source>  
  86.                     <target>1.6target>  
  87.                 configuration>  
  88.             plugin>  
  89.         plugins>  
  90.     build>  
  91.   
  92.     <modules>  
  93.         <module>mybatis-hellomodule>  
  94.         <module>mybatis-relevancemodule>  
  95.         <module>mybatis-commonmodule>  
  96.         <module>mybatis-pagemodule>  
  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.   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
  4.   "http://mybatis.org/dtd/mybatis-3-config.dtd">  
  5.       
  6. <configuration>  
  7.   
  8.       
  9.     <properties>    
  10.         <property name="dialect" value="oracle" />   
  11.         <property name="databaseType" value="oracle">property>   
  12.     properties>    
  13.         
  14.       
  15.     <typeAliases>    
  16.          <typeAlias type="org.ygy.demo.mybatis.entity.PersonEntity" alias="PersonEntity">typeAlias>  
  17.          <typeAlias type="org.ygy.demo.mybatis.entity.BlogEntity" alias="BlogEntity">typeAlias>  
  18.     typeAliases>   
  19.       
  20.       
  21.     <plugins>  
  22.           
  23.          
  24.     <mappers>  
  25.          <mapper resource="org/ygy/demo/mybatis/mapper/blog-mapper.xml">mapper>  
  26.     mappers>  
  27.       
  28. configuration>  

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

[java]  view plain copy
  1. @Override  
  2.     public List queryWithPage(RowBounds rowBounds) {  
  3.         SqlSession session = MyBatisUtil.getSession();  
  4.         List 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 blogs = blogDao.queryWithPage(rowBounds);  
  6.           
  7.         for(BlogEntity blog : blogs) {  
  8.             System.out.println("--blog:" + blog);  
  9.         }  
  10.     }  

在实现拦截器时,还有另一种方法,道理是一样的,会在一篇博客中简单说一下。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部