zoukankan      html  css  js  c++  java
  • Mybatis分页-利用Mybatis Generator插件生成基于数据库方言的分页语句,统计记录总数 (转)

    众所周知,Mybatis本身没有提供基于数据库方言的分页功能,而是基于JDBC的游标分页,很容易出现性能问题。网上有很多分页的解决方案,不外乎是基于Mybatis本机的插件机制,通过拦截Sql做分页。但是在像Oracle这样的数据库上,拦截器生成的Sql语句没有变量绑定,而且每次语句的都要去拦截,感觉有点浪费性能。

    Mybatis Generator是Mybatis的代码生成工具,可以生成大部分的查询语句。

    本文提供的分页解决方案是新增Mybatis Generator插件,在用Mybatis Generator生成Mybatis代码时,直接生成基于数据库方言的Sql语句,解决Oralce等数据库的变量绑定,且无需使用Mybatis拦截器去拦截语句判断分页。

    一、编写Mybatis Generator Dialect插件

     

    Java代码  收藏代码
    1. 2011 Tgwoo Inc.  
    2. //www.tgwoo.com/  
    3. package com.tgwoo.core.dao.plugin;  
    4. import java.util.List;  
    5. import org.mybatis.generator.api.CommentGenerator;  
    6. import org.mybatis.generator.api.IntrospectedTable;  
    7. import org.mybatis.generator.api.PluginAdapter;  
    8. import org.mybatis.generator.api.dom.java.Field;  
    9. import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;  
    10. import org.mybatis.generator.api.dom.java.JavaVisibility;  
    11. import org.mybatis.generator.api.dom.java.Method;  
    12. import org.mybatis.generator.api.dom.java.Parameter;  
    13. import org.mybatis.generator.api.dom.java.TopLevelClass;  
    14. import org.mybatis.generator.api.dom.xml.Attribute;  
    15. import org.mybatis.generator.api.dom.xml.Document;  
    16. import org.mybatis.generator.api.dom.xml.TextElement;  
    17. import org.mybatis.generator.api.dom.xml.XmlElement;  
    18. /** 
    19.  * @author pan.wei 
    20.  * @date 2011-11-30 下午08:36:11 
    21.  */  
    22. public class OraclePaginationPlugin extends PluginAdapter {  
    23.     @Override  
    24. public boolean modelExampleClassGenerated(TopLevelClass topLevelClass,  
    25.         // add field, getter, setter for limit clause  
    26. "page");  
    27. return super.modelExampleClassGenerated(topLevelClass,  
    28.     }  
    29.     @Override  
    30. public boolean sqlMapDocumentGenerated(Document document,  
    31.         XmlElement parentElement = document.getRootElement();  
    32.         // 产生分页语句前半部分  
    33. new XmlElement("sql");  
    34. new Attribute("id",  
    35. "OracleDialectPrefix"));  
    36. new XmlElement("if");  
    37. new Attribute("test", "page != null"));  
    38. new TextElement(  
    39. "select * from ( select row_.*, rownum rownum_ from ( "));  
    40.         parentElement.addElement(paginationPrefixElement);  
    41.         // 产生分页语句后半部分  
    42. new XmlElement("sql");  
    43. new Attribute("id",  
    44. "OracleDialectSuffix"));  
    45. new XmlElement("if");  
    46. new Attribute("test", "page != null"));  
    47. new TextElement(  
    48. "<![CDATA[ ) row_ ) where rownum_ > #{page.begin} and rownum_ <= #{page.end} ]]>"));  
    49.         parentElement.addElement(paginationSuffixElement);  
    50.         return super.sqlMapDocumentGenerated(document, introspectedTable);  
    51.   
    52. @Override  
    53. public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(  
    54.   
    55. new XmlElement("include"); //$NON-NLS-1$     
    56. new Attribute("refid", "OracleDialectPrefix"));  
    57. 0, pageStart);  
    58.         XmlElement isNotNullElement = new XmlElement("include"); //$NON-NLS-1$     
    59. new Attribute("refid",  
    60. "OracleDialectSuffix"));  
    61.   
    62. return super.sqlMapUpdateByExampleWithoutBLOBsElementGenerated(element,  
    63.     }  
    64.     /** 
    65.      * @param topLevelClass 
    66.      * @param introspectedTable 
    67.      * @param name 
    68.      */  
    69. private void addPage(TopLevelClass topLevelClass,  
    70.         topLevelClass.addImportedType(new FullyQualifiedJavaType(  
    71. "com.tgwoo.core.dao.pojo.Page"));  
    72.         Field field = new Field();  
    73.         field.setType(new FullyQualifiedJavaType("com.tgwoo.core.dao.pojo.Page"));  
    74.         commentGenerator.addFieldComment(field, introspectedTable);  
    75.         char c = name.charAt(0);  
    76. 1);  
    77. new Method();  
    78.         method.setName("set" + camel);  
    79. new Parameter(new FullyQualifiedJavaType(  
    80. "com.tgwoo.core.dao.pojo.Page"), name));  
    81. "this." + name + "=" + name + ";");  
    82.         topLevelClass.addMethod(method);  
    83. new Method();  
    84.         method.setReturnType(new FullyQualifiedJavaType(  
    85. "com.tgwoo.core.dao.pojo.Page"));  
    86. "get" + camel);  
    87. "return " + name + ";");  
    88.         topLevelClass.addMethod(method);  
    89.   
    90. /** 
    91.      * This plugin is always valid - no properties are required 
    92.      */  
    93. public boolean validate(List<String> warnings) {  
    94. return true;  
    95. }  

     

    二、增加插件到Mybatis Generator配置文件中

     

    Xml代码  收藏代码
    1. >  
    2. <generatorConfiguration >  
    3. <classPathEntry location="E:workeclipseWorkspacemyEclipseCTSPMTSWebRootWEB-INFlibojdbc14.jar" />  
    4.     <context id="oracle" >  
    5. <plugin type="org.mybatis.generator.plugins.CaseInsensitiveLikePlugin"></plugin>  
    6. <plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>  
    7. <!-- Pagination -->  
    8. <plugin type="com.tgwoo.core.dao.plugin.OraclePaginationPlugin"></plugin>  
    9.         <commentGenerator>    
    10. <property name="suppressDate" value="true" />    
    11. <property name="suppressAllComments" value="true" />  
    12. </commentGenerator>    
    13.         <jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver" connectionURL="jdbc:oracle:thin:@192.168.0.2:1521:ctspmt" userId="ctspmt" password="ctspmt123" />  
    14. <javaModelGenerator targetPackage="com.tgwoo.ctspmt.model" targetProject="CTSPMTS/src" />  
    15. <sqlMapGenerator targetPackage="com.tgwoo.ctspmt.data" targetProject="CTSPMTS/src" />  
    16. <javaClientGenerator targetPackage="com.tgwoo.ctspmt.data" targetProject="CTSPMTS/src" type="XMLMAPPER" /><!-- 
    17.        
    18.         <table schema="ctspmt" tableName="mt_e_interface_log"/> 
    19.         --><!--  
    20. <table schema="ctspmt" tableName="mt_e_msg" />  
    21. <table schema="ctspmt" tableName="mt_e_msg_log" />  
    22. <table schema="ctspmt" tableName="mt_e_msg_receiver" />  
    23. <table schema="ctspmt" tableName="st_e_org" />  
    24. <table schema="ctspmt" tableName="st_e_role" />  
    25. <table schema="ctspmt" tableName="st_e_user" />  
    26. <table schema="ctspmt" tableName="mt_e_user_msg_conf" />  
    27. <table schema="ctspmt" tableName="mt_j_user_device" />  
    28. <table schema="ctspmt" tableName="st_j_user_role" />  
    29. <table schema="ctspmt" tableName="ST_E_UNIQUE_KEY" />       
    30. ><table schema="ctspmt" tableName="mt_v_msg_item" />  
    31. </context>  
    32. </generatorConfiguration>  

     

     

    三、示例

     

    Java代码  收藏代码
    1. 2011 Tgwoo Inc.  
    2. //www.tgwoo.com/  
    3. package com.tgwoo.ctspmt.test;  
    4. import com.tgwoo.core.config.SpringBeanProxy;  
    5. import com.tgwoo.core.dao.pojo.Page;  
    6. import com.tgwoo.ctspmt.data.MtVMsgItemMapper;  
    7. import com.tgwoo.ctspmt.model.MtVMsgItemExample;  
    8. /** 
    9.  * @author pan.wei 
    10.  * @date 2011-11-25 下午01:26:17 
    11.  */  
    12. public class Test {  
    13. /** 
    14.      * @param args 
    15.      */  
    16. public static void main(String[] args) {  
    17. //get spring mapper instance   
    18.                 MtVMsgItemMapper.class);  
    19. new MtVMsgItemExample();  
    20. new Page(0, 10);  
    21.         ex.createCriteria().andMsgCodeEqualTo("222");  
    22. // set count,up to you  
    23.         int row = mapper.selectByExample(ex).size();  
    24. "============row:" + row + "================");  
    25.   
    26. }  

     

    四、分页类

     

    Java代码  收藏代码
    1. package com.tgwoo.core.dao.pojo;  
    2. /** 
    3.  * @author pan.wei 
    4.  * @date 2011-12-1 上午11:36:12 
    5.  */  
    6. public class Page {  
    7. // 分页查询开始记录位置  
    8. private int begin;  
    9. // 分页查看下结束位置  
    10. private int end;  
    11. // 每页显示记录数  
    12. private int length;  
    13. // 查询结果总记录数  
    14. private int count;  
    15. // 当前页码  
    16. private int current;  
    17. // 总共页数  
    18. private int total;  
    19.     public Page() {  
    20.   
    21. /** 
    22.      * 构造函数 
    23.      *  
    24.      * @param begin 
    25.      * @param length 
    26.      */  
    27. public Page(int begin, int length) {  
    28. this.begin = begin;  
    29. this.length = length;  
    30. this.end = this.begin + this.length;  
    31. this.current = (int) Math.floor((this.begin * 1.0d) / this.length) + 1;  
    32.   
    33. /** 
    34.      * @param begin 
    35.      * @param length 
    36.      * @param count 
    37.      */  
    38. public Page(int begin, int length, int count) {  
    39. this(begin, length);  
    40. this.count = count;  
    41.   
    42. /** 
    43.      * @return the begin 
    44.      */  
    45. public int getBegin() {  
    46. return begin;  
    47.   
    48. /** 
    49.      * @return the end 
    50.      */  
    51. public int getEnd() {  
    52. return end;  
    53.   
    54. /** 
    55.      * @param end 
    56.      *            the end to set 
    57.      */  
    58. public void setEnd(int end) {  
    59. this.end = end;  
    60.   
    61. /** 
    62.      * @param begin 
    63.      *            the begin to set 
    64.      */  
    65. public void setBegin(int begin) {  
    66. this.begin = begin;  
    67. if (this.length != 0) {  
    68. this.current = (int) Math.floor((this.begin * 1.0d) / this.length) + 1;  
    69.     }  
    70.     /** 
    71.      * @return the length 
    72.      */  
    73. public int getLength() {  
    74. return length;  
    75.   
    76. /** 
    77.      * @param length 
    78.      *            the length to set 
    79.      */  
    80. public void setLength(int length) {  
    81. this.length = length;  
    82. if (this.begin != 0) {  
    83. this.current = (int) Math.floor((this.begin * 1.0d) / this.length) + 1;  
    84.     }  
    85.     /** 
    86.      * @return the count 
    87.      */  
    88. public int getCount() {  
    89. return count;  
    90.   
    91. /** 
    92.      * @param count 
    93.      *            the count to set 
    94.      */  
    95. public void setCount(int count) {  
    96. this.count = count;  
    97. this.total = (int) Math.floor((this.count * 1.0d) / this.length);  
    98. if (this.count % this.length != 0) {  
    99. this.total++;  
    100.     }  
    101.     /** 
    102.      * @return the current 
    103.      */  
    104. public int getCurrent() {  
    105. return current;  
    106.   
    107. /** 
    108.      * @param current 
    109.      *            the current to set 
    110.      */  
    111. public void setCurrent(int current) {  
    112. this.current = current;  
    113.   
    114. /** 
    115.      * @return the total 
    116.      */  
    117. public int getTotal() {  
    118. if (total == 0) {  
    119. return 1;  
    120.         return total;  
    121.   
    122. /** 
    123.      * @param total 
    124.      *            the total to set 
    125.      */  
    126. public void setTotal(int total) {  
    127. this.total = total;  
    128.   
    129. }  

     五、生成后的代码

    1、Example代码

     

     

    Java代码  收藏代码
    1. package com.tgwoo.ctspmt.model;  
    2. import com.tgwoo.core.dao.pojo.Page;  
    3. import java.math.BigDecimal;  
    4. import java.util.ArrayList;  
    5. import java.util.Date;  
    6. import java.util.Iterator;  
    7. import java.util.List;  
    8. public class MtVMsgItemExample {  
    9. protected String orderByClause;  
    10.     protected boolean distinct;  
    11.     protected List<Criteria> oredCriteria;  
    12.     protected Page page;  
    13.     ...  

     2、mapper.xml

     

    Xml代码  收藏代码
    1.  <select id="selectByExample" resultMap="BaseResultMap" parameterType="com.tgwoo.ctspmt.model.MtVMsgItemExample" >  
    2. <include refid="OracleDialectPrefix" />  
    3.     <if test="distinct" >  
    4.     </if>  
    5. <include refid="Base_Column_List" />  
    6.     <if test="_parameter != null" >  
    7. <include refid="Example_Where_Clause" />  
    8. </if>  
    9. <if test="orderByClause != null" >  
    10.     </if>  
    11. <include refid="OracleDialectSuffix" />  
    12. </select>  
    13.   <sql id="OracleDialectPrefix" >  
    14. <if test="page != null" >  
    15.     </if>  
    16. </sql>  
    17. <sql id="OracleDialectSuffix" >  
    18. <if test="page != null" >  
    19. <![CDATA[ ) row_ ) where rownum_ > #{page.begin} and rownum_ <= #{page.end} ]]>  
    20. </if>  
    21. </sql>  
    22. ...  

     

     

    附件是Mybatis Generatorjar包。

    其他数据库的方言可以按照Oracle的去改写,有写好的希望能共享下。

     

     

    -------------------------------------------------------------------------------------------------------

    maven管理:

    1、pom.xml

     

    Xml代码  收藏代码
    1. <build>  
    2. <plugins>  
    3. <plugin>  
    4. <groupId>org.mybatis.generator</groupId>  
    5. <artifactId>mybatis-generator-maven-plugin</artifactId>  
    6. <version>1.3.1</version>  
    7. <executions>  
    8. <execution>  
    9. <id>Generate MyBatis Artifacts</id>  
    10. <goals>  
    11. <goal>generate</goal>  
    12. </goals>  
    13. </execution>  
    14. </executions>  
    15. <dependencies>  
    16. <dependency>  
    17. <groupId>com.oracle</groupId>  
    18. <artifactId>ojdbc14</artifactId>  
    19. <version>10.2.0.4.0</version>  
    20. </dependency>  
    21. </dependencies>  
    22. </plugin>  
    23. </plugins>  
    24. </build>  

     

     

    Xml代码  收藏代码
    1.   

     

     2、generatorConfig.xml

     

    Xml代码  收藏代码
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2.   PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"  
    3. >  
    4. <generatorConfiguration>  
    5. <context id="oracleGenerator" targetRuntime="MyBatis3">  
    6. <plugin type="org.mybatis.generator.plugins.CaseInsensitiveLikePlugin"></plugin>  
    7. <plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>  
    8. <!-- Pagination -->  
    9. <plugin  
    10. type="com.tgwoo.test.core.dao.mybatis.generator.plugin.pagination.OraclePaginationPlugin"></plugin>  
    11.         <!-- 取消注释 -->  
    12. <commentGenerator>  
    13. <property name="suppressDate" value="true" />  
    14. <property name="suppressAllComments" value="true" />  
    15. </commentGenerator>  
    16. <!-- 配置连接数据信息 -->  
    17. <jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver"  
    18. connectionURL="jdbc:oracle:thin:@192.168.0.2:1521:test" userId="test"  
    19. password="test123" />  
    20. <javaTypeResolver>  
    21. <property name="forceBigDecimals" value="false" />  
    22. </javaTypeResolver>  
    23.         <!-- 配置自动生成的Model的保存路径与其它参数 -->  
    24. <javaModelGenerator targetPackage="com.tgwoo.test.dao.model"  
    25. targetProject=".srcmainjava">  
    26. <property name="enableSubPackages" value="false" />  
    27. <property name="trimStrings" value="true" />  
    28. </javaModelGenerator>  
    29.         <!-- 配置自动生成的Mappper.xml映射的保存路径与其它参数 -->  
    30. <sqlMapGenerator targetPackage="com.tgwoo.test.dao"  
    31. targetProject=".srcmain esources">  
    32. <property name="enableSubPackages" value="false" />  
    33. </sqlMapGenerator>  
    34.         <!-- 配置自动生成的Mappper.java接口的保存路径与其它参数 -->  
    35. <javaClientGenerator type="XMLMAPPER"  
    36. targetPackage="com.tgwoo.test.dao" targetProject=".srcmainjava">  
    37. <property name="enableSubPackages" value="false" />  
    38. </javaClientGenerator>  
    39.         <!-- 生成表对应的操作与实体对象 -->  
    40. <table schema="test" tableName="testTable">  
    41. <columnOverride column="id" javaType="Long" />  
    42. </table>  
    43. </context>  
    44. </generatorConfiguration>  

     

     3、run

    Goals:mybatis-generator:generate

     

    4、注意事项

    报插件无法找到或者无法实例化的一般是分页插件和maven插件不在同一classloader下引起的,需要在mybatis-generator-maven-plugin的dependencies中增加dependency。

  • 相关阅读:
    Json字符串转换为java对象的各种实现方法【json_lib框架、Gson、org.json】
    告别无止境的增删改查--Java代码生成器
    Java线程监听,意外退出线程后自动重启
    【技术贴】解决Program Files文件夹消失
    【技术贴】破解Myeclipse10.7
    【技术贴】解决Mysql ERROR 1045 (28000): Access denied for
    【技术贴】关闭CMD错误提示声音
    【技术贴】解决QQ空间发表文章手机不显示换行
    【技术贴】Eclipse 右键打开当前文件所在文件夹
    有趣的代码注释
  • 原文地址:https://www.cnblogs.com/fibonaccixue/p/6506211.html
Copyright © 2011-2022 走看看