博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
让MyBatis Generator产生的代码支持分页
阅读量:6659 次
发布时间:2019-06-25

本文共 15607 字,大约阅读时间需要 52 分钟。

hot3.png

本文提供一种方法,让MyBatis Generator产生的代码支持分页,  适用于MySQL。

分析

如果要获取分页信息,使用MySQL语句,我们需要怎么做呢?

select * from t_user limit 0 , 2

在MySQL系统中,如果要完成一个分页,我们需要指定limit的值,也就是需要指定两个数,第一个指定从什么地方开始(示例中为0);另一个指定需要获取多少条数据(示例中为2)。

问题转化

如果要使得产生的自动产生的代码具备分页功能的话,那么,Mapper对应的XML中select语句需要多增加两个属性值,比如:

  • limitStart (指定从什么位置开始查找)
  • limitSize (指定找到多少条数据)

何处添加

上述已经提到需要两个值limitStartlimitSize,那么,我们需要添加在哪里才能有效果呢

以t_news表为例,创建表的SQL语句如下:

CREATE TABLE `t_news` (  `news_id` int(11) NOT NULL AUTO_INCREMENT,  `title` varchar(150) NOT NULL,  `content` text NOT NULL,  `brief_intro` varchar(255) DEFAULT NULL,  `pic_url` varchar(255) DEFAULT NULL,  `news_from` varchar(100) DEFAULT NULL,  `news_author` varchar(50) DEFAULT NULL,  `news_url` varchar(255) DEFAULT NULL,  `keywords` varchar(150) DEFAULT NULL,  `meta_desc` varchar(150) DEFAULT NULL,  `create_time` datetime DEFAULT NULL,  PRIMARY KEY (`news_id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

那么,我们可以看到NewsMapper.java中查找列表数据都是通过Example来完成的。

​    List
selectByExampleWithBLOBs(NewsExample example); List
selectByExample(NewsExample example);​

其中,selectByExampleWithBLOBs方法只有当数据表中的某一列需要存储较大内容的时候,才会产生。来看一下判断是否为BLOB列的源代码吧。摘自IntrospectedColumn类。

public boolean isBLOBColumn() {        String typeName = getJdbcTypeName();        return "BINARY".equals(typeName) || "BLOB".equals(typeName) //$NON-NLS-1$ //$NON-NLS-2$                || "CLOB".equals(typeName) || "LONGVARBINARY".equals(typeName) //$NON-NLS-1$ //$NON-NLS-2$                || "LONGVARCHAR".equals(typeName) || "VARBINARY".equals(typeName); //$NON-NLS-1$ //$NON-NLS-2$    }

注意:

使用selectByExample方法是不会返回BLOB类型的字段,如t_news新闻表中的content内容字段。如果想返回content的值,那么,需要使用selectByExampleWithBLOBs方法。

大家可以来看看如下内容感受一下。selectByExampleWithBLOBs中包含Blob_Column_List,而selectByExample没有。

  

从上述简单分析可以看出,limitStartlimitSize添加的地方有两个:

  • 实体类对应的Example中需要添加。
  • XML文件中,selectByExampleselectByExampleWithBLOBs配置需要添加limitStartlimitSize属性。

limit #{limitStart} , #{limitSize}

有了上述的分析之后,我们需要写什么就很清楚了 。

编码

Example类具备分页属性

Example中包含两个字段limitStartlimitSize,并具有GetterSetter方法,如:

public class NewsExample {    protected Integer limitStart;      protected Integer limitSize;    public void setLimitStart(Integer limitStart) {        this.limitStart = limitStart;    }    public Integer getLimitStart() {        return limitStart;    }    public void setLimitSize(Integer limitSize) {        this.limitSize = limitSize;    }    public Integer getLimitSize() {        return limitSize;    }    //省略其它}

增加一个私有方法addLimit用于在Example中创建字段并生成Getter和Setter方法:

private void addLimit(TopLevelClass topLevelClass,			IntrospectedTable introspectedTable, String name) {				CommentGenerator commentGenerator = context.getCommentGenerator();				/**		 * 创建成员变量		 * 如protected Integer limitStart;		 */		Field field = new Field();		field.setVisibility(JavaVisibility.PROTECTED);		field.setType(PrimitiveTypeWrapper.getIntegerInstance());		field.setName(name);		commentGenerator.addFieldComment(field, introspectedTable);		topLevelClass.addField(field);		/**		 * 首字母大写		 */		char c = name.charAt(0);		String camel = Character.toUpperCase(c) + name.substring(1);		/**		 * 添加Setter方法		 */		Method method = new Method();		method.setVisibility(JavaVisibility.PUBLIC);		method.setName("set" + camel);		method.addParameter(new Parameter(PrimitiveTypeWrapper				.getIntegerInstance(), name));		StringBuilder sb = new StringBuilder();		sb.append("this.");		sb.append(name);		sb.append(" = ");		sb.append(name);		sb.append(";");		/**		 * 如 this.limitStart = limitStart;		 */		method.addBodyLine(sb.toString());		commentGenerator.addGeneralMethodComment(method, introspectedTable);		topLevelClass.addMethod(method);		/**		 * 添加Getter Method 直接调用AbstractJavaGenerator的getGetter方法		 */		Method getterMethod = AbstractJavaGenerator.getGetter(field);		commentGenerator.addGeneralMethodComment(getterMethod,				introspectedTable);		topLevelClass.addMethod(getterMethod);	}

 

其实,产生上述的代码并不难,因为MyBatis Generator本身就是在为生成的实体类添加变量和Getter Setter方法。

如:

AbstractJavaGenerator抽象类本身就有产生Getter方法的函数,直接调用即可。

public abstract class AbstractJavaGenerator extends AbstractGenerator {    public abstract List
getCompilationUnits(); public static Method getGetter(Field field) { Method method = new Method(); method.setName(getGetterMethodName(field.getName(), field .getType())); method.setReturnType(field.getType()); method.setVisibility(JavaVisibility.PUBLIC); StringBuilder sb = new StringBuilder(); sb.append("return "); //$NON-NLS-1$ sb.append(field.getName()); sb.append(';'); method.addBodyLine(sb.toString()); return method; }}

另外, Setter方法的实现,可以参考AbstractJavaGenerator抽象类的getJavaBeansSetter方法,如:

public Method getJavaBeansSetter(IntrospectedColumn introspectedColumn) {        FullyQualifiedJavaType fqjt = introspectedColumn                .getFullyQualifiedJavaType();        String property = introspectedColumn.getJavaProperty();        Method method = new Method();        method.setVisibility(JavaVisibility.PUBLIC);        method.setName(getSetterMethodName(property));        method.addParameter(new Parameter(fqjt, property));        context.getCommentGenerator().addSetterComment(method,                introspectedTable, introspectedColumn);        StringBuilder sb = new StringBuilder();        if (isTrimStringsEnabled() && introspectedColumn.isStringColumn()) {            sb.append("this."); //$NON-NLS-1$            sb.append(property);            sb.append(" = "); //$NON-NLS-1$            sb.append(property);            sb.append(" == null ? null : "); //$NON-NLS-1$            sb.append(property);            sb.append(".trim();"); //$NON-NLS-1$            method.addBodyLine(sb.toString());        } else {            sb.append("this."); //$NON-NLS-1$            sb.append(property);            sb.append(" = "); //$NON-NLS-1$            sb.append(property);            sb.append(';');            method.addBodyLine(sb.toString());        }        return method;    }

然后,重写modelExampleClassGenerated产生的方法,如:

@Override	public boolean modelExampleClassGenerated(TopLevelClass topLevelClass,			IntrospectedTable introspectedTable) {		addLimit(topLevelClass, introspectedTable, "limitStart");		addLimit(topLevelClass, introspectedTable, "limitSize");		return super.modelExampleClassGenerated(topLevelClass,				introspectedTable);	}

这样,Example改变就完成了。

XML文件支持分页

接下来,我们需要对产生的XML的selectByExampleselectByExampleWithBLOBs方法添加limitStartlimitSize属性。

为selectByExample添加limitStart和limitSize

/**	 * 为selectByExample添加limitStart和limitSize	 */	@Override	public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(			XmlElement element, IntrospectedTable introspectedTable) {		XmlElement isNotNullElement = new XmlElement("if");		isNotNullElement.addAttribute(new Attribute("test",				"limitStart != null and limitSize >= 0"));		isNotNullElement.addElement(new TextElement(				"limit #{limitStart} , #{limitSize}"));		element.addElement(isNotNullElement);		return super.sqlMapSelectByExampleWithoutBLOBsElementGenerated(element,				introspectedTable);	}

为selectByExampleWithBLOBs添加limitStart和limitSize

/**	 * 为selectByExampleWithBLOBs添加limitStart和limitSize	 */	@Override	public boolean sqlMapSelectByExampleWithBLOBsElementGenerated(			XmlElement element, IntrospectedTable introspectedTable) {		XmlElement isNotNullElement = new XmlElement("if");		isNotNullElement.addAttribute(new Attribute("test",				"limitStart != null and limitSize >= 0"));		isNotNullElement.addElement(new TextElement(				"limit #{limitStart} , #{limitSize}"));		element.addElement(isNotNullElement);		return super.sqlMapSelectByExampleWithBLOBsElementGenerated(element,				introspectedTable);	}

MysqlPaginationPlugin类完整代码

package my.mabatis.example.plugin;import java.util.List;import org.mybatis.generator.api.CommentGenerator;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.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;import org.mybatis.generator.codegen.AbstractJavaGenerator;/** * MyBatis MySQL自动生成带分页插件 *  * @author wangmengjun * */public class MysqlPaginationPlugin extends PluginAdapter {	@Override	public boolean modelExampleClassGenerated(TopLevelClass topLevelClass,			IntrospectedTable introspectedTable) {		addLimit(topLevelClass, introspectedTable, "limitStart");		addLimit(topLevelClass, introspectedTable, "limitSize");		return super.modelExampleClassGenerated(topLevelClass,				introspectedTable);	}	/**	 * 为selectByExample添加limitStart和limitSize	 */	@Override	public boolean sqlMapSelectByExampleWithoutBLOBsElementGenerated(			XmlElement element, IntrospectedTable introspectedTable) {		XmlElement isNotNullElement = new XmlElement("if");		isNotNullElement.addAttribute(new Attribute("test",				"limitStart != null and limitSize >= 0"));		isNotNullElement.addElement(new TextElement(				"limit #{limitStart} , #{limitSize}"));		element.addElement(isNotNullElement);		return super.sqlMapSelectByExampleWithoutBLOBsElementGenerated(element,				introspectedTable);	}	/**	 * 为selectByExampleWithBLOBs添加limitStart和limitSize	 */	@Override	public boolean sqlMapSelectByExampleWithBLOBsElementGenerated(			XmlElement element, IntrospectedTable introspectedTable) {		XmlElement isNotNullElement = new XmlElement("if");		isNotNullElement.addAttribute(new Attribute("test",				"limitStart != null and limitSize >= 0"));		isNotNullElement.addElement(new TextElement(				"limit #{limitStart} , #{limitSize}"));		element.addElement(isNotNullElement);		return super.sqlMapSelectByExampleWithBLOBsElementGenerated(element,				introspectedTable);	}	private void addLimit(TopLevelClass topLevelClass,			IntrospectedTable introspectedTable, String name) {		CommentGenerator commentGenerator = context.getCommentGenerator();		/**		 * 创建类成员变量 如protected Integer limitStart;		 */		Field field = new Field();		field.setVisibility(JavaVisibility.PROTECTED);		field.setType(PrimitiveTypeWrapper.getIntegerInstance());		field.setName(name);		commentGenerator.addFieldComment(field, introspectedTable);		topLevelClass.addField(field);		/**		 * 首字母大写		 */		char c = name.charAt(0);		String camel = Character.toUpperCase(c) + name.substring(1);		/**		 * 添加Setter方法		 */		Method method = new Method();		method.setVisibility(JavaVisibility.PUBLIC);		method.setName("set" + camel);		method.addParameter(new Parameter(PrimitiveTypeWrapper				.getIntegerInstance(), name));		StringBuilder sb = new StringBuilder();		sb.append("this.");		sb.append(name);		sb.append(" = ");		sb.append(name);		sb.append(";");		/**		 * 如 this.limitStart = limitStart;		 */		method.addBodyLine(sb.toString());		commentGenerator.addGeneralMethodComment(method, introspectedTable);		topLevelClass.addMethod(method);		/**		 * 添加Getter Method 直接调用AbstractJavaGenerator的getGetter方法		 */		Method getterMethod = AbstractJavaGenerator.getGetter(field);		commentGenerator.addGeneralMethodComment(getterMethod,				introspectedTable);		topLevelClass.addMethod(getterMethod);	}	public boolean validate(List
warnings) { return true; }}

修改自动产生代码配置文件generatorConfig.xml中的plugin。

自动产生代码,我们可以看到NewsExample.java以及NewsMapper.xml都具有limitStart和limitSize, 可以支持分页。部分相关代码如下:

package my.mybatis.generator.auto.entity;import java.util.ArrayList;import java.util.Date;import java.util.List;public class NewsExample {    /**     * This field was generated by MyBatis Generator.     * This field corresponds to the database table m_news     *     * @mbggenerated Wed Nov 09 21:39:59 CST 2016     */    protected Integer limitStart;    /**     * This field was generated by MyBatis Generator.     * This field corresponds to the database table m_news     *     * @mbggenerated Wed Nov 09 21:39:59 CST 2016     */    protected Integer limitSize;    /**     * This method was generated by MyBatis Generator.     * This method corresponds to the database table m_news     *     * @mbggenerated Wed Nov 09 21:39:59 CST 2016     */    public void setLimitStart(Integer limitStart) {        this.limitStart = limitStart;    }    /**     * This method was generated by MyBatis Generator.     * This method corresponds to the database table m_news     *     * @mbggenerated Wed Nov 09 21:39:59 CST 2016     */    public Integer getLimitStart() {        return limitStart;    }    /**     * This method was generated by MyBatis Generator.     * This method corresponds to the database table m_news     *     * @mbggenerated Wed Nov 09 21:39:59 CST 2016     */    public void setLimitSize(Integer limitSize) {        this.limitSize = limitSize;    }    /**     * This method was generated by MyBatis Generator.     * This method corresponds to the database table m_news     *     * @mbggenerated Wed Nov 09 21:39:59 CST 2016     */    public Integer getLimitSize() {        return limitSize;    }    //省略其它}
  

至此,大功告成。

测试验证

创建一个用于获取分页列表的方法。

package my.mabatis.example.service;import java.util.List;import my.mabatis.example.util.MyBatisUtil;import my.mybatis.generator.auto.dao.UserMapper;import my.mybatis.generator.auto.entity.User;import my.mybatis.generator.auto.entity.UserExample;import my.mybatis.generator.auto.entity.UserExample.Criteria;import org.apache.ibatis.session.SqlSession;/** *  * @author wangmengjun * */public class UserService {	/**	 * 查找分页列表	 */	public List
selectNewsByPage(int pageNo, int pageSize) { SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory() .openSession(); try { UserMapper userDao = sqlSession.getMapper(UserMapper.class); /** * 使用Example来操作 */ UserExample example = new UserExample(); /** * 设置limitStart和limitSize */ example.setLimitStart((pageNo - 1) * pageSize); example.setLimitSize(pageSize); return userDao.selectByExample(example); } finally { sqlSession.close(); } }}

写一个测试类,获取第一页数据,一页5条。

package my.mabatis.example.runner;import java.util.List;import my.mabatis.example.service.UserService;import my.mybatis.generator.auto.entity.User;public class Test {	public static void main(String[] args) {		UserService userService = new UserService();		/**		 * 获取第一页的数据, 一页5条数据		 */		List
users = userService.selectNewsByPage(1, 5); System.out.println(users.size()); }}

测试数据一共有三条,所以返回结果是正确的。

log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory).log4j:WARN Please initialize the log4j system properly.log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.3

如有疑问

Note:

本篇文章的编写与之前的几篇文章有部分联系,如果有类内容不知道,请参考之前的两篇博文;

也可以直接问我即可。

转载于:https://my.oschina.net/wangmengjun/blog/785306

你可能感兴趣的文章
HDU 4523 湫秋系列故事——安排座位【组合dp】【好题】【思维题】
查看>>
普通运维人员是秋后的蚂蚱?
查看>>
windows 2008 DHCP服务搭建——windows 2008系列教程
查看>>
linux目录只给写入不给删除
查看>>
linux下安装mysql
查看>>
KVM虚拟化开源高可用方案(五)总结
查看>>
final关键字,static关键字
查看>>
高效电邮撰写(Write Effective Email)
查看>>
Remove Linked List Elements
查看>>
掌握“核心技术”,珍爱生命,不该用的不用,不该学的不学
查看>>
DJ舞曲-抓钱舞音乐播放器
查看>>
DataTable 除去列中重复值
查看>>
学习日志---集合框架基础实现(MyVector,MySet)
查看>>
刘宇凡:站长,你曾有过这样的感觉吗?
查看>>
react native遇到的坑
查看>>
NOI2019仍有高校现场签约 现场招生规则发布(附各省队名单)!
查看>>
upx壳的一些简单脱壳,望大牛勿喷。
查看>>
如何设置系统的最大连接数ulimit -a
查看>>
我的友情链接
查看>>
Python基础(二)
查看>>