本文提供一种方法,让MyBatis Generator产生的代码支持分页, 适用于MySQL。html
若是要获取分页信息,使用MySQL语句,咱们须要怎么作呢?java
select * from t_user limit 0 , 2
在MySQL系统中,若是要完成一个分页,咱们须要指定limit的值,也就是须要指定两个数,第一个指定从什么地方开始(示例中为0);另外一个指定须要获取多少条数据(示例中为2)。sql
若是要使得产生的自动产生的代码具有分页功能的话,那么,Mapper对应的XML中,select语句须要多增长两个属性值,好比:apache
- limitStart (指定从什么位置开始查找)
- limitSize (指定找到多少条数据)
上述已经提到须要两个值limitStart和limitSize,那么,咱们须要添加在哪里才能有效果呢?api
以t_news表为例,建立表的SQL语句以下:session
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来完成的。mybatis
List<News> selectByExampleWithBLOBs(NewsExample example); List<News> selectByExample(NewsExample example);
其中,selectByExampleWithBLOBs方法只有当数据表中的某一列须要存储较大内容的时候,才会产生。来看一下判断是否为BLOB列的源代码吧。摘自IntrospectedColumn类。app
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$ }
注意:dom
使用selectByExample方法是不会返回BLOB类型的字段,如t_news新闻表中的content内容字段。若是想返回content的值,那么,须要使用selectByExampleWithBLOBs方法。ide
你们能够来看看以下内容感觉一下。selectByExampleWithBLOBs中包含Blob_Column_List,而selectByExample没有。
<select id="selectByExampleWithBLOBs" parameterType="my.mybatis.generator.auto.entity.NewsExample" resultMap="ResultMapWithBLOBs"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Wed Nov 09 19:01:57 CST 2016. --> select <if test="distinct"> distinct </if> <include refid="Base_Column_List" /> , <include refid="Blob_Column_List" /> from m_news <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null"> order by ${orderByClause} </if> </select> <select id="selectByExample" parameterType="my.mybatis.generator.auto.entity.NewsExample" resultMap="BaseResultMap"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Wed Nov 09 19:01:57 CST 2016. --> select <if test="distinct"> distinct </if> <include refid="Base_Column_List" /> from m_news <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null"> order by ${orderByClause} </if> </select>
从上述简单分析能够看出,limitStart和limitSize添加的地方有两个:
如
<if test="limitStart != null and limitSize>=0"> limit #{limitStart} , #{limitSize} </if>
有了上述的分析以后,咱们须要写什么就很清楚了 。
Example中包含两个字段limitStart和limitSize,并具备Getter和Setter方法,如:
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<CompilationUnit> 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的selectByExample和selectByExampleWithBLOBs方法添加limitStart和limitSize属性。
为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<String> warnings) { return true; } }
修改自动产生代码配置文件generatorConfig.xml中的plugin。
<!-- 配置内置的或者自定义的Plugin --> <plugin type="my.mabatis.example.plugin.MysqlPaginationPlugin" />
自动产生代码,咱们能够看到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; } //省略其它 }
<select id="selectByExampleWithBLOBs" parameterType="my.mybatis.generator.auto.entity.NewsExample" resultMap="ResultMapWithBLOBs"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Wed Nov 09 21:39:59 CST 2016. --> select <if test="distinct"> distinct </if> <include refid="Base_Column_List" /> , <include refid="Blob_Column_List" /> from m_news <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null"> order by ${orderByClause} </if> <if test="limitStart != null and limitSize >= 0"> limit #{limitStart} , #{limitSize} </if> </select> <select id="selectByExample" parameterType="my.mybatis.generator.auto.entity.NewsExample" resultMap="BaseResultMap"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Wed Nov 09 21:39:59 CST 2016. --> select <if test="distinct"> distinct </if> <include refid="Base_Column_List" /> from m_news <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null"> order by ${orderByClause} </if> <if test="limitStart != null and limitSize >= 0"> limit #{limitStart} , #{limitSize} </if> </select>
至此,大功告成。
建立一个用于获取分页列表的方法。
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<User> 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<User> 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:
本篇文章的编写与以前的几篇文章有部分联系,若是有类内容不知道,请参考以前的两篇博文;
也能够直接问我便可。