MyBatis Generator实现MySQL分页插件
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命令可以成功生成代码。
使用生成的代码分页
xxExample example = new XxxExample(); ... example.setLimit(10); // page size limit example.setOffset(20); // offset List<Xxx> list = xxxMapper.selectByExample(example);
以上代码运行时执行的SQL是:select ... limit 20, 10。
XxxExample example = new XxxExample(); ... example.setLimit(10); // limit List<Xxx> list = xxxMapper.selectByExample(example);
以上代码运行时执行的SQL是:select ... limit 10。
MyBatis Generator实现MySQL分页插件的更多相关文章
- SpringBoot 添加mybatis generator 自动生成代码插件
自动生成数据层代码,提高开发效率 1.pom添加插件,并指定配置文件路径 <!-- mybatis generator 自动生成代码插件 --> <plugin> <gr ...
- Eclipse MyBatis generator 1.3.7插件的核心包(中文注释)
一.最近刚搭建一个项目框架,使用springboot + mybatis,但是在使用Eclipse开发时发现开发mybatis的Dao.mapper.xml和entity时特别不方便,手工去写肯定是不 ...
- MyBatis学习总结_17_Mybatis分页插件PageHelper
如果你也在用Mybatis,建议尝试该分页插件,这一定是最方便使用的分页插件. 分页插件支持任何复杂的单表.多表分页,部分特殊情况请看重要提示. 想要使用分页插件?请看如何使用分页插件. 物理分页 该 ...
- SpringBoot+MyBatis多数据源使用分页插件PageHelper
之前只用过单数据源下的分页插件,而且几乎不用配置.一个静态方法就能搞定. PageHelper.startPage(pageNum, pageSize); 后来使用了多数据源(不同的数据库),Page ...
- Springboot集成mybatis通用Mapper与分页插件PageHelper
插件介绍 通用 Mapper 是一个可以实现任意 MyBatis 通用方法的框架,项目提供了常规的增删改查操作以及 Example 相关的单表操作.通用 Mapper 是为了解决 MyBatis 使用 ...
- Mybatis generator 数据库反向生成插件的使用
直接上干货: 可生成数据库表对应的po mpper接口文件 mapper.xml文件.文件中自动配置了部分常用的dao层方法.用于快速快发. 1.pom中引入插件: <plugin> & ...
- SpringMVC+Mybatis实现的Mysql分页数据查询
周末这天手痒,正好没事干,想着写一个分页的例子出来给大家分享一下. 这个案例分前端和后台两部分,前端使用面向对象的方式写的,里面用到了一些回调函数和事件代理,有兴趣的朋友可以研究一下.后台的实现技术是 ...
- MyBatis拦截器自定义分页插件实现
MyBaits是一个开源的优秀的持久层框架,SQL语句与代码分离,面向配置的编程,良好支持复杂数据映射,动态SQL;MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyB ...
- mybatis三剑客之mybatis-pagehelper分页插件
这是pom.xml里的依赖: 后续再讲具体的使用
随机推荐
- 设置idea快速生成doc comment
在eclipse中快速生成方法的doc comment快捷键是Alt+Shift+J, 而在idea中没有对应的快捷键,但是能实现相似的功能. 1.在方法上面输入/** 然后回车就可以生成注释了. 2 ...
- 零基础到架构师 不花钱学JavaEE(基础篇)- 概述
Java简单来说是一门语言,Java能干什么? 网站:开发大,中,小型网站. 服务器端程序:企业级程序开发. APP:Android的APP基本使用Java开发. 云:Hadoop就是使用Java语言 ...
- 从一行代码开始,浅谈python字符串格式化
今天看到了一行这样的代码: boundary = '%.32x' % random.randint(0, 256**16) 我知道这是一个生成格式化字符串的语句,它将随机生成的一个32位16进制数,将 ...
- 转载 - Python里面关于 模块 和 包 和 __init__.py 的一些事
出处:http://www.cnblogs.com/tqsummer/archive/2011/01/24/1943273.html python中的Module是比较重要的概念.常见的情况是,事先写 ...
- 【NJU749D】triple(莫比乌斯反演)
题意: cas<=100 n<=10^5 思路:与两个数的没什么区别 F(d)=(n div d)*(n div d-1)*(n div d-2) div 6 再加上喜闻乐见的下底函数分块 ...
- 创建SharePoint 2010 Timer Job
好久没有写博客了. 近期在使用SharePoint 2010中Timer Job的功能,有了一点心得,分享一下. 我个人觉得SharePoint Timer Job和Windows Service或者 ...
- 用C++实现一个Quaternion类
提要 四元素是游戏开发中经常使用的用于处理旋转的数学工具,以下就用C++来实现一个四元素类.參考Unity中四元素的接口. 假设没有看之前的 彻底搞懂四元数. 建议先看一下. 代码清单 Quatern ...
- Codeforces Round #273 (Div. 2)D. Red-Green Towers DP
D. Red-Green Towers There are r red and g green blocks for construction of the red-green tower. Re ...
- Java中去除字符串中的空格
1.去掉首尾的空格 String.trim() trim()是去掉首尾空格 2.去掉所有的空格 str.replace(" ", ""); 去掉所有空格,包括 ...
- 排列(permutation) 用1,2,3,…,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要 求abc:def:ghi=1:2:3。按照“abc def ghi”的格式输出所有解,每行一个解。
#include <stdio.h> #include <math.h> // 算法竞赛的目标是编程对任意输入均得到正确的结果. // 请先独立完成,如果有困难可以翻阅本书代码 ...