起因,在我日常开发中总是会遇到一些问题,公司自己封装的框架需要有一套自己对数据库的CURD操作。就以我公司的来说,前端需要显示一个列表(基本上每一个在前端显示的表数据都是以一个列表的形式展现的),这就意味着后端对数据库需要有一个getPage操作。而每一个表都需要添加getPage操作。我觉得总是去写重复的操作总是有一些麻烦。于是就有了自己折腾出来的自定义插件(公司也有自己的mybatis-generatro插件,可是功能满足不了)。于是就研究了一下怎么自定义插件,去解决一些重复性的工作。
1) 自定义类注释生成
2) 自定义插件
3) 使用Velocity生成service controller层等
4) 使用自己的插件
5)调试插件
1) 自定义类注释生成
通过查找资料可以找出,我们要给类添加表的注释,有俩种方式。把表,列的注释映射到java类上面
a) 实现org.mybatis.generator.api.CommentGenerator接口。
b) 继承org.mybatis.generator.internal.DefaultCommentGenerator类,重写它的方法。这个是他的默认现实类,我们生成的java对象的注释就是由这个类定义的。mybatis-generator默认就是使用的这个。我们需要完全自己定义自己的注释,所以我们直接实现CommentGenerator接口。
我们先来看一下CommentGenerator接口的方法
看到方法名的瞬间是不是知道自己要做什么了?
我们可以先写一个空的CommentGenerator实现。然后继承我们自己空的CommentGenerator,再去重写自己需要的方法。这样子我们就可以实现自己的自定义注解。
贴上我的CommentGenerator
package com.dgbiztech.generator.plugin.comment;
import com.dgbiztech.generator.utils.StringUtils;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
public class CommentGenerator extends EmptyCommentGenerator {
private Properties properties;
public CommentGenerator() {
properties =new Properties();
}
@Override
public void addConfigurationProperties(Properties properties) {
// 获取自定义的 properties
this.properties.putAll(properties);
}
@Override
public void addModelClassComment(TopLevelClass topLevelClass,IntrospectedTable introspectedTable) {
String author =properties.getProperty("author");
String dateFormat =properties.getProperty("dateFormat","yyyy-MM-dd");
String baseModel =properties.getProperty("interface","false");
if (baseModel.equals("true")){
String baseClass =properties.getProperty("classpath","x");
if (baseClass.equals("x")){
throw new RuntimeException("classpath路径不存在!");
}
topLevelClass.addImportedType(baseClass);
topLevelClass.addSuperInterface(new FullyQualifiedJavaType(baseClass.substring(baseClass.lastIndexOf(".")+1,baseClass.length())));
}
SimpleDateFormat dateFormatter =new SimpleDateFormat(dateFormat);
// 获取表注释
String remarks =introspectedTable.getRemarks();
topLevelClass.addJavaDocLine("/**");
topLevelClass.addJavaDocLine(" * " + remarks);
topLevelClass.addJavaDocLine(" * @author " + author);
topLevelClass.addJavaDocLine(" * @date " + dateFormatter.format(new Date()));
topLevelClass.addJavaDocLine(" */");
}
@Override
public void addFieldComment(Field field,IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn) {
// 获取列注释
String remarks =introspectedColumn.getRemarks();
field.addJavaDocLine("/**");
field.addJavaDocLine(" * " +(StringUtils.isEmpty(remarks)?introspectedColumn.getActualColumnName():remarks));
field.addJavaDocLine(" */");
}
@Override
public void addGetterComment(Method method,IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
method.addJavaDocLine("/**");
StringBuilder sb =new StringBuilder();
sb.append(" * ");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString().replace("\n"," "));
sb.setLength(0);
sb.append(" * @return ");
sb.append(introspectedColumn.getActualColumnName());
sb.append(" ");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString().replace("\n"," "));
method.addJavaDocLine(" */");
}
@Override
public void addSetterComment(Method method,IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
method.addJavaDocLine("/**");
StringBuilder sb =new StringBuilder();
sb.append(" * ");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString().replace("\n"," "));
Parameter parm =method.getParameters().get(0);
sb.setLength(0);
sb.append(" * @param ");
sb.append(parm.getName());
sb.append(" ");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString().replace("\n"," "));
method.addJavaDocLine(" */");
}
}
2) 自定义插件
自定义插件我们需要继承org.mybatis.generator.api.PluginAdapter类
先上代码
package com.dgbiztech.generator.plugin;
import com.dgbiztech.generator.utils.SqlMapperGeneratorTool;
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.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
import java.util.List;
public class GetPagePlugin extends PluginAdapter {
private final static String GET_PAGE ="getPage";
private Boolean likequery;
@Override
public boolean validate(List
warnings) { return true;
}
/**
* 方法对应的xml节点在这里添加
* @param document
* @param introspectedTable
* @return
*/
@Override
public boolean sqlMapDocumentGenerated(Document document,IntrospectedTable introspectedTable) {
if (introspectedTable.getTargetRuntime().equals(IntrospectedTable.TargetRuntime.MYBATIS3)) {
addSqlMapper(document,introspectedTable);
}
return super.sqlMapDocumentGenerated(document,introspectedTable);
}
public void addSqlMapper(Document document,IntrospectedTable introspectedTable) {
likequery =Boolean.valueOf(properties.getProperty("likequery","false"));
String tableName =introspectedTable.getFullyQualifiedTableNameAtRuntime();
List
columnList =introspectedTable.getAllColumns(); //model的包路径
String baseRecordType =introspectedTable.getBaseRecordType();
//primaryKey的JDBC名字
String primaryKeyName =introspectedTable.getPrimaryKeyColumns().get(0).getActualColumnName();
//primaryKey的JAVA变量
String primaryKeyParameterClause =MyBatis3FormattingUtilities.getParameterClause(introspectedTable.getPrimaryKeyColumns().get(0),"item.");
//primaryKey的JAVA名字
String primaryKeyJavaName =introspectedTable.getPrimaryKeyColumns().get(0).getJavaProperty();
//构建一个xml节点,
XmlElement getPageXmlElement =SqlMapperGeneratorTool.baseElementGenerator(SqlMapperGeneratorTool.SELECT,
GET_PAGE,
new FullyQualifiedJavaType(baseRecordType),
new FullyQualifiedJavaType("com.dgbiztech.core.dto.MapDto"));
getPageXmlElement.addElement(new TextElement(String.format("SELECT * FROM %s ",tableName)));
XmlElement whereElement =new XmlElement("where");
getPageXmlElement.addElement(whereElement);
for (int i =0; i < columnList.size(); i++) {
IntrospectedColumn introspectedColumn = columnList.get(i);
String columnName = introspectedColumn.getActualColumnName();
String columnJavaTypeName = introspectedColumn.getJavaProperty();
String parameterClause =MyBatis3FormattingUtilities.getParameterClause(introspectedColumn);
String ifSql;
if(likequery) {
ifSql =String.format("AND %s LIKE %s || ",columnName,parameterClause);
ifSql+=" '%' ";
}else {
ifSql =String.format("AND %s = %s ",columnName,parameterClause);
}
XmlElement ifElement =SqlMapperGeneratorTool.baseIfJudgeElementGen(columnJavaTypeName, ifSql, introspectedColumn);
whereElement.addElement(ifElement);
}
document.getRootElement().addElement(getPageXmlElement);
}
}
如果我们需要在xml文件里面自己自定义一个节点,那么我们需要重写sqlMapDocumentGenerated方法
里面有两个参数,Document document 和 IntrospectedTable introspectedTable
document代表的就是整个xml文件。introspectedTable就是当前表的信息。(每一个表都会运行插件)
在introspectedTable里面可以获取到我们需要的表的信息,例如表名,列名,生成java类的属性等等。我们就可以自己拼接自己的节点。
通过document.getRootElement().addElement(自己的节点);我们就可以把自己的节点添加到xml文件。
3) 使用Velocity生成service controller层等
对应的插件是com.dgbiztech.generator.plugin.ServiceControllerPlugin
原理就是通过使用Velocity模板文件(*.vm),把表的数据写入到模板当中,然后写出到文件夹。
4) 使用自己的插件
a)先把我们的自定义插件install一次(mvn命令),这里使用的是mybatis-generator的maven插件。
然后把我们的插件添加到mybatis-generator的maven插件的依赖里面。
然后我们在generatorConfig.xml里面配置我们的插件就可以了。
5)调试插件
开发插件的时候我们使用junit4来调试插件
package com.dgbiztech.generator.plugin;
import org.junit.Before;
import org.junit.Test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class ServiceControllerPluginTest {
private File configFile;
@Before
public void before() {
//读取mybatis参数
configFile =new File("D:\\repo-git\\mybatis-generator\\mybatis-generator\\src\\main\\resources\\generatorConfig.xml");
// configFile = new File("/Users/zhangsiyuan/Documents/MybatisFun/Mybatis-Chapter9-GeneratorPlugin/src/main/resources/mybatisConfig.xml");
}
@Test
public void test() throws Exception{
List
warnings =new ArrayList (); boolean overwrite =true;
ConfigurationParser cp =new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback =new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator =new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
}
本文源码:
mybatis-generator自定义插件
参考:
Mybatis Generator生成数据库自带的中文注释
图形化MBG,内置丰富插件,可生成Service、Controller、View,配置简单。 A powerful GUI tool for MyBatisGenerator(MBG)
Velocity初探小结--velocity使用语法详解
PS:源码里面的数据大都是我根据公司自己的要求制定出来的。比如增加一些baseclass之类的。