mybatis-generator如何自定义注释生成
作者:一头磕在键盘上
前言
本文写于2016.2,是基于mybatis-generator 1.3.2版本来完成的.
目前正式版的mybatis-generator已更新至1.3.5版本,本文同样适用于1.3.3~1.3.5,不过CommentGenerator接口中新增一些方法需要额外实现,这点在使用本文提供的代码示例时需要注意下,毕竟本文是实现的1.3.2的接口.
理论上以后mybatis-generator即便是再有更新,只要接口不变架构不变,那么本文依旧适用,毕竟原理是一样的.
需要注意的是,从1.3.3版本开始在commentGenerator标签下新增了addRemarkComments属性(详情请见commentGenerator),某种程度下可替代本文的一些功能,可以先试下效果再来决定是否来自己实现注释生成.
-- 2016.08.27
完善了一些细节.对4.1出现的问题补充了新的解决方案.感谢评论区@Armeng 的提示.
-- 2016.09.28
之前第三步提供的运行方法只有maven方式,而java方式的放在了4.1中,对很多读者造成了不便,主要对此进行了调整(调整后3.1为java方式、3.2为maven方式),顺带完善了下java方式运行的示例代码.
-- 2018.12.26
正文
mybatis-generator 自动生成的代码注释是很反人类的,通常我们在使用的时候都是按照如下设置关闭注释:
<commentGenerator> <!-- 关闭自动生成的注释 --> <property name="suppressAllComments" value="true" /> </commentGenerator>
不过在mybatis-generator官方文档中commentGenerator一节中有这么一段说明:
The default implementation is org.mybatis.generator.internal.DefaultCommentGenerator. The default implementation is designed for extensibility if you only want to modify certain behaviors.
既然是可扩展的,那么该如何做呢?文档中也有说明,只需要实现 org.mybatis.generator.api.CommentGenerator接口,同时有一个public的构造函数,然后为commentGenerator添加属性type,并将其值设置为实现类的全路径即可.
好吧,文档里面是这么说明的,来看看具体怎么做吧.
事先声明我用的是Eclipse+Maven来构建的.
1.实现CommentGenerator接口
当然首先你的工程中要有mybatis-generator-core这个jar包.相关pom如下:
<dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <!-- 注意版本.示例代码使用的是1.3.2.采用更高版本自行再实现下新加的接口即可. --> <version>1.3.2</version> </dependency>
正文,实现CommentGenerator接口,当然继承默认的实现DefaultCommentGenerator也行.然后实现或者是重写自己需要的方法.过程中最好是参照着DefaultCommentGenerator里面的代码来做.
没什么要多说的,下文是我的实现.
import static org.mybatis.generator.internal.util.StringUtility.isTrue; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Properties; import org.mybatis.generator.api.CommentGenerator; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.dom.java.CompilationUnit; import org.mybatis.generator.api.dom.java.Field; import org.mybatis.generator.api.dom.java.InnerClass; import org.mybatis.generator.api.dom.java.InnerEnum; import org.mybatis.generator.api.dom.java.JavaElement; import org.mybatis.generator.api.dom.java.Method; import org.mybatis.generator.api.dom.java.Parameter; import org.mybatis.generator.api.dom.xml.XmlElement; import org.mybatis.generator.config.MergeConstants; import org.mybatis.generator.config.PropertyRegistry; /** * mybatis generator 自定义comment生成器. * 基于MBG 1.3.2. * @author ZhangAY 2016-02-19 * */ public class MyCommentGenerator implements CommentGenerator { private Properties properties; private Properties systemPro; private boolean suppressDate; private boolean suppressAllComments; private String currentDateStr; public MyCommentGenerator() { super(); properties = new Properties(); systemPro = System.getProperties(); suppressDate = false; suppressAllComments = false; currentDateStr = (new SimpleDateFormat("yyyy-MM-dd")).format(new Date()); } public void addJavaFileComment(CompilationUnit compilationUnit) { // add no file level comments by default return; } /** * Adds a suitable comment to warn users that the element was generated, and * when it was generated. */ public void addComment(XmlElement xmlElement) { return; } public void addRootComment(XmlElement rootElement) { // add no document level comments by default return; } public void addConfigurationProperties(Properties properties) { this.properties.putAll(properties); suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE)); suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS)); } /** * This method adds the custom javadoc tag for. You may do nothing if you do * not wish to include the Javadoc tag - however, if you do not include the * Javadoc tag then the Java merge capability of the eclipse plugin will * break. * * @param javaElement * the java element */ protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) { javaElement.addJavaDocLine(" *"); StringBuilder sb = new StringBuilder(); sb.append(" * "); sb.append(MergeConstants.NEW_ELEMENT_TAG); if (markAsDoNotDelete) { sb.append(" do_not_delete_during_merge"); } String s = getDateString(); if (s != null) { sb.append(' '); sb.append(s); } javaElement.addJavaDocLine(sb.toString()); } /** * This method returns a formated date string to include in the Javadoc tag * and XML comments. You may return null if you do not want the date in * these documentation elements. * * @return a string representing the current timestamp, or null */ protected String getDateString() { String result = null; if (!suppressDate) { result = currentDateStr; } return result; } public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) { if (suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); innerClass.addJavaDocLine("/**"); sb.append(" * "); sb.append(introspectedTable.getFullyQualifiedTable()); sb.append(" "); sb.append(getDateString()); innerClass.addJavaDocLine(sb.toString()); innerClass.addJavaDocLine(" */"); } public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) { if (suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); innerEnum.addJavaDocLine("/**"); // addJavadocTag(innerEnum, false); sb.append(" * "); sb.append(introspectedTable.getFullyQualifiedTable()); innerEnum.addJavaDocLine(sb.toString()); innerEnum.addJavaDocLine(" */"); } public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); field.addJavaDocLine("/**"); sb.append(" * "); sb.append(introspectedColumn.getRemarks()); field.addJavaDocLine(sb.toString()); // addJavadocTag(field, false); field.addJavaDocLine(" */"); } public void addFieldComment(Field field, IntrospectedTable introspectedTable) { if (suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); field.addJavaDocLine("/**"); sb.append(" * "); sb.append(introspectedTable.getFullyQualifiedTable()); field.addJavaDocLine(sb.toString()); field.addJavaDocLine(" */"); } public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) { if (suppressAllComments) { return; } // method.addJavaDocLine("/**"); // addJavadocTag(method, false); // method.addJavaDocLine(" */"); } public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (suppressAllComments) { return; } method.addJavaDocLine("/**"); StringBuilder sb = new StringBuilder(); sb.append(" * "); sb.append(introspectedColumn.getRemarks()); method.addJavaDocLine(sb.toString()); sb.setLength(0); sb.append(" * @return "); sb.append(introspectedColumn.getActualColumnName()); sb.append(" "); sb.append(introspectedColumn.getRemarks()); method.addJavaDocLine(sb.toString()); // addJavadocTag(method, false); method.addJavaDocLine(" */"); } public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (suppressAllComments) { return; } method.addJavaDocLine("/**"); StringBuilder sb = new StringBuilder(); sb.append(" * "); sb.append(introspectedColumn.getRemarks()); method.addJavaDocLine(sb.toString()); 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()); // addJavadocTag(method, false); method.addJavaDocLine(" */"); } public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) { if (suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); innerClass.addJavaDocLine("/**"); sb.append(" * "); sb.append(introspectedTable.getFullyQualifiedTable()); innerClass.addJavaDocLine(sb.toString()); sb.setLength(0); sb.append(" * @author "); sb.append(systemPro.getProperty("user.name")); sb.append(" "); sb.append(currentDateStr); // addJavadocTag(innerClass, markAsDoNotDelete); innerClass.addJavaDocLine(" */"); }
2.配置generator.xml
按照如下配置即可,注意type的值为 MyCommentGenerator类的全路径.
<commentGenerator type="MyCommentGenerator"> </commentGenerator>
3.运行
MBG(注: 即 MyBatis Generator 的英文缩写)支持多种方式运行,本文只罗列两种(java方式及maven方式)
如果需要以命令行或其他方式运行参照官网文档:
方法1. java方式(个人推荐)
直接以main方法运行,主要是省事不易出错.代码如下:
public static void main(String[] args) { // 执行中的异常信息会保存在warnings中 List<String> warnings = new ArrayList<String>(); try { // true:生成的文件覆盖之前的 boolean overwrite = true; // 读取配置,构造 Configuration 对象. // 如果不想使用配置文件的话,也可以直接来 new Configuration(),然后给相应属性赋值. File configFile = new File("generatorConfig.xml"); 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); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (InvalidConfigurationException e) { e.printStackTrace(); } catch (XMLParserException e) { e.printStackTrace(); } for (String warning : warnings){ System.out.println(warning); } }
方法2. maven方式
将MyCommentGenerator类打包生成jar,添加到maven库中,类似如下:
<dependency> <groupId>com.saddestmoon</groupId> <artifactId>MyCommentGenerator</artifactId> <version>0.1.SNAPSHOT</version> </dependency>
mybatis-generator-maven-plugin插件添加相关依赖:
<plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <dependencies> <dependency> <groupId>com.saddestmoon</groupId> <artifactId>MyCommentGenerator</artifactId> <version>0.1.SNAPSHOT</version> </dependency> </dependencies> </plugin>
然后工程右键,run as -->maven,填写相关参数,运行mybatis generator.
最后自动生成的代码应该是类似如下:
/** * 文件代码 */ private String fileCd; /** * 文件代码 * @return FILE_CD 文件代码 */ public String getFileCd() { return fileCd; } /** * 文件代码 * @param fileCd 文件代码 */ public void setFileCd(String fileCd) { this.fileCd = fileCd; }
4.可能出现的问题
大多数情况下,到第三步就算是结束了.下面的,都是踩的坑.
4.1 提示找不到MyCommentGenerator
这个一般是使用Maven命令运行MBG时才会出现的错误.
原因是mybatis-generator-core与MyCommentGenerator不在同一个ClassPath下,解决方法如下:
参照第3.2,一定要打包生成jar,然后在pom文件mybatis-generator-maven-plugin插件中添加相关依赖.
使用Java方式(参照3.1)运行MBG可以避免该问题,也不用打包成jar:
4.2 获取不到字段注释
没错,就是introspectedColumn.getRemarks()获取不到字段的注释,生成的javabean里面应该显示字段注释的地方显示的是null.
配置文件中我们对<jdbcConnection>做如下修改即可:
<jdbcConnection driverClass="${driver}" connectionURL="{url}" userId="${username}" password="${password}"> <!-- 针对oracle数据库 --> <property name="remarksReporting" value="true"></property> <!-- 针对mysql数据库 --> <property name="useInformationSchema" value="true"></property> </jdbcConnection>
问题解决
关于此问题的详细解决思路,参见另一篇文章 Mybatis Generator 获取不到字段注释.如果你用的不是Oracle或Mysql,那么最好看下.
4.3生成的javabean中字段注释中文乱码
这个需要手动设置生成文件的编码.
在官方文档<context>一节中<Property >有相关说明,如下.
javaFileEncoding Use this property to specify an encoding to use when working with Java files. Newly generated Java files will be written to the file system in this encoding, and existing Java files will be read with this encoding when performing a merge. If not specified, then the platform default encoding will be used.
所以在配置文件<context>中添加如下子元素即可:
<property name="javaFileEncoding" value="UTF-8"/>
注意:<context>下的子元素是必须按照规定顺序来的,否则运行会报错!
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。