mybatis-generator:自定义插件之分页、序列化、集成lombok
0.需求
在我们使用mybatis-generator的过程中,往往其自带的功能不能够满足我们的需求。
此时我们就需要进行插件开发了。
1.准备工作
新建一个Maven项目,引入依赖 mybatis-generator-core
2.开发分页
在mysql中,我们一般使用limit来实现分页
之前的做法是在mybatis-generator生成完成之后手动在Example中两个属性,offset,rows
然后在xml中添加条件判断,追加limit。
这里我们就通过这个思路在开发分页插件。
import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.PluginAdapter; import org.mybatis.generator.api.dom.java.*; 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 java.util.List; public class LimitPlugin extends PluginAdapter { @Override public boolean validate(List<String> list) { return true; } /** * 为每个Example类添加offset和rows属性已经set、get方法 */ @Override public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { PrimitiveTypeWrapper integerWrapper = FullyQualifiedJavaType.getIntInstance().getPrimitiveTypeWrapper(); Field rows = new Field(); rows.setName("rows"); rows.setVisibility(JavaVisibility.PRIVATE); rows.setType(integerWrapper); topLevelClass.addField(rows); Method setRows = new Method(); setRows.setVisibility(JavaVisibility.PUBLIC); setRows.setName("setRows"); setRows.addParameter(new Parameter(integerWrapper, "rows")); setRows.addBodyLine("this.rows = rows;"); topLevelClass.addMethod(setRows); Method getRows = new Method(); getRows.setVisibility(JavaVisibility.PUBLIC); getRows.setReturnType(integerWrapper); getRows.setName("getRows"); getRows.addBodyLine("return rows;"); topLevelClass.addMethod(getRows); 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", "rows != null")); XmlElement ifOffsetNotNullElement = new XmlElement("if"); ifOffsetNotNullElement.addAttribute(new Attribute("test", "offset != null")); ifOffsetNotNullElement.addElement(new TextElement("limit ${offset}, ${rows}")); ifLimitNotNullElement.addElement(ifOffsetNotNullElement); XmlElement ifOffsetNullElement = new XmlElement("if"); ifOffsetNullElement.addAttribute(new Attribute("test", "offset == null")); ifOffsetNullElement.addElement(new TextElement("limit ${rows}")); ifLimitNotNullElement.addElement(ifOffsetNullElement); element.addElement(ifLimitNotNullElement); return true; } }
3.集成Lombok、序列化
使用lombok可以使代码更简洁
import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.PluginAdapter; import org.mybatis.generator.api.dom.java.*; import java.util.List; public class LombokPlugin extends PluginAdapter { @Override public boolean validate(List<String> warnings) { return true; } @Override public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { // 添加domain的import topLevelClass.addImportedType("lombok.Data"); topLevelClass.addImportedType("lombok.NoArgsConstructor"); topLevelClass.addImportedType("lombok.AllArgsConstructor"); topLevelClass.addImportedType("java.io.Serializable"); // 添加domain的注解 topLevelClass.addAnnotation("@Data"); topLevelClass.addAnnotation("@NoArgsConstructor"); topLevelClass.addAnnotation("@AllArgsConstructor"); // 序列化 generatorDefaultSerialVersionUID(topLevelClass); return true; } // 不生成getter @Override public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) { return false; } // 不生成setter @Override public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) { return false; } /** * 序列化 * * @param topLevelClass */ private void generatorDefaultSerialVersionUID(TopLevelClass topLevelClass) { FullyQualifiedJavaType serializable = new FullyQualifiedJavaType("java.io.Serializable"); topLevelClass.addSuperInterface(serializable); Field field = new Field(); field.setFinal(true); field.setInitializationString("1L"); field.setName("serialVersionUID"); field.setStatic(true); field.setType(new FullyQualifiedJavaType("long")); field.setVisibility(JavaVisibility.PRIVATE); topLevelClass.getFields().add(0, field); } }
4.使用运行
到这里我们就将两个自定义的插件开发完成了。
这里建议是将这两个插件放在一个单独的项目,一是为了方便复用,另一个是我放在同一个项目下的时候,运行好像有点问题。
4.1.打包插件
通过mvn install将我们的插件进行打包,打包为jar包,方便后续使用。
4.2.使用插件
<plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <configuration> <configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile> <overwrite>true</overwrite> </configuration> <dependencies> <dependency> <groupId>com.xxxx</groupId> <artifactId>xxxx</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </plugin>
更改pom.xml,在mybatis-generator的maven插件中引入我们刚刚的项目
<?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> <!--导入属性配置 --> <properties resource="generator/generator.properties"></properties> <!--指定特定数据库的jdbc驱动jar包的位置 location: The full path name of a JAR/ZIP file to add to the classpath, or a directory to add to the classpath. --> <classPathEntry location="${jdbc.driverLocation}"/> <context id="default" targetRuntime="Mybatis3"> <!--使用``包裹mysql关键字--> <property name="autoDelimitKeywords" value="true"/> <property name="beginningDelimiter" value="`"/> <property name="endingDelimiter" value="`"/> <plugin type="com.fdzang.formybatis.config.LombokPlugin"/> <plugin type="com.fdzang.formybatis.config.LimitPlugin"/> <!-- optional,旨在创建class时,去掉注释 --> <commentGenerator> <property name="suppressDate" value="false"/> <property name="suppressAllComments" value="true"/> </commentGenerator> <jdbcConnection driverClass="${jdbc.driver}" connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"> </jdbcConnection> <!-- 非必需,类型处理器,在数据库类型和java类型之间的转换控制--> <javaTypeResolver > <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!--配置实体bean--> <javaModelGenerator targetPackage="com.fdzang.microservice.blog.article.dao.domain" targetProject="src/main/java"> <!-- 是否允许子包,即targetPackage.schemaName.tableName --> <property name="enableSubPackages" value="false"/> <!-- 是否对类CHAR类型的列的数据进行trim操作 --> <property name="trimStrings" value="false"/> </javaModelGenerator> <!-- 配置实体bean的mapper.xml--> <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- 配置实体mapper接口--> <javaClientGenerator targetPackage="com.fdzang.microservice.blog.article.dao.mapper" targetProject="src/main/java" type="XMLMAPPER"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <table tableName="test" domainObjectName="TestDO" mapperName="TestMapper" enableInsert="true" enableUpdateByPrimaryKey="true" enableDeleteByPrimaryKey="true" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false"> </table> </context> </generatorConfiguration>
修改generatorConfig.xml,在<context>中引入插件<plugin>,这里有个注意事项是,plugin放置的顺序,需要在<property>下
4.3.运行效果
import java.io.Serializable; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) public class TestDO implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String test; }
Example,去掉了其他部分。
public class TestDOExample { private Integer rows; private Integer offset; public TestDOExample() { oredCriteria = new ArrayList<Criteria>(); } public void setRows(Integer rows) { this.rows = rows; } public Integer getRows() { return rows; } public void setOffset(Integer offset) { this.offset = offset; } public Integer getOffset() { return offset; } }
Mapper
<select id="selectByExample" parameterType="com.fdzang.microservice.blog.article.dao.domain.TestDOExample" resultMap="BaseResultMap"> select <if test="distinct"> distinct </if> 'false' as QUERYID, <include refid="Base_Column_List" /> from test <if test="_parameter != null"> <include refid="Example_Where_Clause" /> </if> <if test="orderByClause != null"> order by ${orderByClause} </if> <if test="rows != null"> <if test="offset != null"> limit ${offset}, ${rows} </if> <if test="offset == null"> limit ${rows} </if> </if> </select>
5.其他
其实自定义mybatis-generator的插件,主要是通过继承PluginAdapter来实现的。
PluginAdapter中还有很多其他的方法,可以进行自定义修改,大家可以根据需要进行自定义改造。
参考:
http://xxgblog.com/2016/05/06/mybatis-generator-mysql-pagination/
https://www.jianshu.com/p/b243f3ec8419