MyBatis Generator实现MySQL分页插件
来源:互联网 发布:js调用android代码 编辑:程序博客网 时间:2024/04/19 23:06
MyBatis Generator是一个非常方便的代码生成工具,它能够根据表结构生成CRUD代码,可以满足大部分需求。但是唯一让人不爽的是,生成的代码中的数据库查询没有分页功能。本文介绍如何让MyBatis Generator生成的代码具有分页功能。
MyBatis Generator结合Maven的配置和使用
在实现分页之前,首先简单介绍MyBatis Generator如何使用。
MyBatis Generator配置文件
MyBatis Generator通常会有一个xml配置文件,用来指定连接的数据库、哪些表、如何生成代码。详情可以参考官方文档:http://www.mybatis.org/generator/configreference/xmlconfig.html 。下面给出一份简单的配置,文件命名为generatorConfig.xml:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration> <context id="mysqlgenerator" targetRuntime="MyBatis3"> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/yourdb?useUnicode=true&characterEncoding=UTF-8" userId="user" password="password" /> <javaModelGenerator targetPackage="com.xxg.bean" targetProject="src/main/java" /> <sqlMapGenerator targetPackage="com.xxg.mapper" targetProject="src/main/resources" /> <javaClientGenerator type="XMLMAPPER" targetPackage="com.xxg.mapper" targetProject="src/main/java" /> <table tableName="table_a" /> <table tableName="table_b" /> <table tableName="table_c" /> <table tableName="table_d" /> </context></generatorConfiguration>
Maven配置
官网文档中提供了四种MyBatis Generator生成代码的运行方式:命令行、使用Ant、使用Maven、Java编码。本文采用Maven插件mybatis-generator-maven-plugin来运行MyBatis Generator,详细配置同样可以参考官方文档:http://www.mybatis.org/generator/running/runningWithMaven.html 。下面给出一份简单的pom.xml的配置:
<build> <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> </dependency> </dependencies> <configuration> <overwrite>true</overwrite> </configuration> </plugin> </plugins></build>
以上配置完成后,可以通过运行mvn mybatis-generator:generate
命令来生成代码。当然,如果只有上面的这些配置,生成的代码是不支持分页的。
RowBoundsPlugin
MyBatis Generator可以通过插件机制来扩展其功能,其中RowBoundsPlugin是MyBatis Generator中自带的一个分页插件。可以在MyBatis Generator配置文件generatorConfig.xml中添加这个插件:
<context id="mysqlgenerator" targetRuntime="MyBatis3"> <plugin type="org.mybatis.generator.plugins.RowBoundsPlugin"></plugin> ...</context>
再次运行mvn mybatis-generator:generate
生成代码,此时会发现生成的Mapper中会加入一个新的方法:selectByExampleWithRowbounds(XxxExample example, RowBounds rowBounds)
,可以在代码中调用这个方法来实现分页:
int offset = 100;int limit = 25;RowBounds rowBounds = new RowBounds(offset, limit);List<Xxx> list = xxxMapper.selectByExampleWithRowbounds(example, rowBounds);
RowBounds的构造方法new RowBounds(offset, limit)
中的offset、limit参数就相当于MySQL的select语句limit后的offset和rows。如果此时仔细观察一下日志打出来的SQL语句或者看下生成的XxxMapper.xml文件中的selectByExampleWithRowbounds元素,可以发现select语句并没有使用limit。实际上RowBounds原理是通过ResultSet的游标来实现分页,也就是并不是用select语句的limit分页而是用Java代码分页,查询语句的结果集会包含符合查询条件的所有数据,使用不慎会导致性能问题,所以并不推荐使用RowBoundsPlugin来实现分页。
limit分页插件实现
在实现MySQL分页时更推荐使用select语句的limit来实现分页,然而MyBatis Generator目前并没有提供这样的插件。好在MyBatis Generator支持插件扩展,我们可以自己实现一个基于limit来分页的插件。如何实现一个插件可以参考官方文档:http://www.mybatis.org/generator/reference/pluggingIn.html 。
实现思路
在生成的XxxExample中加入两个属性limit和offset,同时加上set和get方法。也就是需要生成以下代码:
private Integer limit;private Integer offset;public void setLimit(Integer limit) { this.limit = limit;}public Integer getLimit() { return limit;}public void setOffset(Integer offset) { this.offset = offset;}public Integer getOffset() { return offset;}
XxxMapper.xml中在通过selectByExample查询时,添加limit:
<select id="selectByExample" parameterType="com.xxg.bean.XxxExample" resultMap="BaseResultMap"> ... <if test="limit != null"> <if test="offset != null"> limit ${offset}, ${limit} </if> <if test="offset == null"> limit ${limit} </if> </if></select>
插件实现代码
package com.xxg.mybatis.plugins;import java.util.List;import org.mybatis.generator.api.IntrospectedTable;import org.mybatis.generator.api.PluginAdapter;import org.mybatis.generator.api.dom.java.Field;import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;import org.mybatis.generator.api.dom.java.JavaVisibility;import org.mybatis.generator.api.dom.java.Method;import org.mybatis.generator.api.dom.java.Parameter;import org.mybatis.generator.api.dom.java.PrimitiveTypeWrapper;import org.mybatis.generator.api.dom.java.TopLevelClass;import org.mybatis.generator.api.dom.xml.Attribute;import org.mybatis.generator.api.dom.xml.TextElement;import org.mybatis.generator.api.dom.xml.XmlElement;public class MySQLLimitPlugin extends PluginAdapter { @Override public boolean validate(List<String> list) { return true; } /** * 为每个Example类添加limit和offset属性已经set、get方法 */ @Override public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper(); Field limit = new Field(); limit.setName("limit"); limit.setVisibility(JavaVisibility.PRIVATE); limit.setType(integerWrapper); topLevelClass.addField(limit); Method setLimit = new Method(); setLimit.setVisibility(JavaVisibility.PUBLIC); setLimit.setName("setLimit"); setLimit.addParameter(new Parameter(integerWrapper, "limit")); setLimit.addBodyLine("this.limit = limit;"); topLevelClass.addMethod(setLimit); Method getLimit = new Method(); getLimit.setVisibility(JavaVisibility.PUBLIC); getLimit.setReturnType(integerWrapper); getLimit.setName("getLimit"); getLimit.addBodyLine("return limit;"); topLevelClass.addMethod(getLimit); Field offset = new Field(); offset.setName("offset"); offset.setVisibility(JavaVisibility.PRIVATE); offset.setType(integerWrapper); topLevelClass.addField(offset); Method setOffset = new Method(); setOffset.setVisibility(JavaVisibility.PUBLIC); setOffset.setName("setOffset"); setOffset.addParameter(new Parameter(integerWrapper, "offset")); setOffset.addBodyLine("this.offset = offset;"); topLevelClass.addMethod(setOffset); Method getOffset = new Method(); getOffset.setVisibility(JavaVisibility.PUBLIC); getOffset.setReturnType(integerWrapper); getOffset.setName("getOffset"); getOffset.addBodyLine("return offset;"); topLevelClass.addMethod(getOffset); return true; } /** * 为Mapper.xml的selectByExample添加limit */ @Override public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(XmlElement element, IntrospectedTable introspectedTable) { XmlElement ifLimitNotNullElement = new XmlElement("if"); ifLimitNotNullElement.addAttribute(new Attribute("test", "limit != null")); XmlElement ifOffsetNotNullElement = new XmlElement("if"); ifOffsetNotNullElement.addAttribute(new Attribute("test", "offset != null")); ifOffsetNotNullElement.addElement(new TextElement("limit ${offset}, ${limit}")); ifLimitNotNullElement.addElement(ifOffsetNotNullElement); XmlElement ifOffsetNullElement = new XmlElement("if"); ifOffsetNullElement.addAttribute(new Attribute("test", "offset == null")); ifOffsetNullElement.addElement(new TextElement("limit ${limit}")); ifLimitNotNullElement.addElement(ifOffsetNullElement); element.addElement(ifLimitNotNullElement); return true; }}
插件的使用
在MyBatis Generator配置文件中配置plugin:
<context id="mysqlgenerator" targetRuntime="MyBatis3"> <plugin type="com.xxg.mybatis.plugins.MySQLLimitPlugin"></plugin> ...</context>
如果直接加上以上配置运行mvn mybatis-generator:generate
肯定会出现找不到这个插件的错误:
java.lang.ClassNotFoundException: com.xxg.mybatis.plugins.MySQLLimitPlugin
为了方便大家的使用,我已经把插件打包上传到GitHub,可以在pom.xml直接依赖使用:
<pluginRepositories> <pluginRepository> <id>mybatis-generator-limit-plugin-mvn-repo</id> <url>https://raw.github.com/wucao/mybatis-generator-limit-plugin/mvn-repo/</url> </pluginRepository></pluginRepositories><build> <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> </dependency> <dependency> <groupId>com.xxg</groupId> <artifactId>mybatis-generator-plugin</artifactId> <version>1.0.0</version> </dependency> </dependencies> <configuration> <overwrite>true</overwrite> </configuration> </plugin> </plugins></build>
此时运行mvn mybatis-generator:generate
命令可以成功生成代码。
使用生成的代码分页
XxxExample example = new XxxExample();...example.setLimit(10); // page size limitexample.setOffset(20); // offsetList<Xxx> list = xxxMapper.selectByExample(example);
以上代码运行时执行的SQL是:select ... limit 20, 10
。
XxxExample example = new XxxExample();...example.setLimit(10); // limitList<Xxx> list = xxxMapper.selectByExample(example);
以上代码运行时执行的SQL是:select ... limit 10
。
GitHub
如果你对插件的实现原理不感兴趣,只想直接使用这个插件,那么可以在我的GitHub上查看使用文档,另外源代码也在里面:
https://github.com/wucao/mybatis-generator-limit-plugin
- MyBatis Generator实现MySQL分页插件
- MyBatis Generator实现MySQL分页插件
- MyBatis Generator实现分页插件
- mybatis generator 分页插件
- Mybatis3分页, 基于Mybatis Generator插件生成MYSQL分页语句
- MyBatis Generator 以及 Generator 分页插件
- Mybatis Generator实现分页功能
- Mybatis Generator实现分页功能
- Mybatis Generator实现分页功能
- MyBatis+Mysql实现分页插件PageInfo
- MyBatis+Mysql实现分页插件PageInfo
- MyBatis插件实现分页
- Mybatis 分页插件实现
- mybatis (Ibatis ibator) generator - 1 mysql 分页插件(page/paging/pagination plugin)
- mybatis分页插件实现分页
- Mybatis3分页, 基于Mybatis Generator插件生成分页语句
- MyBatis Generator(MBG)实现插件
- mybatis实现分页插件PageHelper
- 用git提交修改和新增的代码到github
- 知道这20个正则表达式,能让你少写1,000行代码
- 安卓动画(Animation)总结
- 爬取京东商品价格和评论数
- VMware Workstation环境下的Linux网络设置
- MyBatis Generator实现MySQL分页插件
- 幂次方
- iOS UIWindow:获取屏幕最上层的窗口
- codeforce 22#div2E
- sublime 下使用快捷键
- andorid 数据存储方式
- 服务器上没有你的文件的解决办法
- storm安装配置
- android dalvik和art的区别