mybatis-generator如何自定義注釋生成
前言
本文寫于2016.2,是基于mybatis-generator 1.3.2版本來(lái)完成的.
目前正式版的mybatis-generator已更新至1.3.5版本,本文同樣適用于1.3.3~1.3.5,不過(guò)CommentGenerator接口中新增一些方法需要額外實(shí)現(xiàn),這點(diǎn)在使用本文提供的代碼示例時(shí)需要注意下,畢竟本文是實(shí)現(xiàn)的1.3.2的接口.
理論上以后mybatis-generator即便是再有更新,只要接口不變架構(gòu)不變,那么本文依舊適用,畢竟原理是一樣的.
需要注意的是,從1.3.3版本開始在commentGenerator標(biāo)簽下新增了addRemarkComments屬性(詳情請(qǐng)見commentGenerator),某種程度下可替代本文的一些功能,可以先試下效果再來(lái)決定是否來(lái)自己實(shí)現(xiàn)注釋生成.
-- 2016.08.27
完善了一些細(xì)節(jié).對(duì)4.1出現(xiàn)的問(wèn)題補(bǔ)充了新的解決方案.感謝評(píng)論區(qū)@Armeng 的提示.
-- 2016.09.28
之前第三步提供的運(yùn)行方法只有maven方式,而java方式的放在了4.1中,對(duì)很多讀者造成了不便,主要對(duì)此進(jìn)行了調(diào)整(調(diào)整后3.1為java方式、3.2為maven方式),順帶完善了下java方式運(yùn)行的示例代碼.
-- 2018.12.26
正文
mybatis-generator 自動(dòng)生成的代碼注釋是很反人類的,通常我們?cè)谑褂玫臅r(shí)候都是按照如下設(shè)置關(guān)閉注釋:
<commentGenerator> <!-- 關(guān)閉自動(dòng)生成的注釋 --> <property name="suppressAllComments" value="true" /> </commentGenerator>
不過(guò)在mybatis-generator官方文檔中commentGenerator一節(jié)中有這么一段說(shuō)明:
The default implementation is org.mybatis.generator.internal.DefaultCommentGenerator. The default implementation is designed for extensibility if you only want to modify certain behaviors.
既然是可擴(kuò)展的,那么該如何做呢?文檔中也有說(shuō)明,只需要實(shí)現(xiàn) org.mybatis.generator.api.CommentGenerator接口,同時(shí)有一個(gè)public的構(gòu)造函數(shù),然后為commentGenerator添加屬性type,并將其值設(shè)置為實(shí)現(xiàn)類的全路徑即可.
好吧,文檔里面是這么說(shuō)明的,來(lái)看看具體怎么做吧.
事先聲明我用的是Eclipse+Maven來(lái)構(gòu)建的.
1.實(shí)現(xiàn)CommentGenerator接口
當(dāng)然首先你的工程中要有mybatis-generator-core這個(gè)jar包.相關(guān)pom如下:
<dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <!-- 注意版本.示例代碼使用的是1.3.2.采用更高版本自行再實(shí)現(xiàn)下新加的接口即可. --> <version>1.3.2</version> </dependency>
正文,實(shí)現(xiàn)CommentGenerator接口,當(dāng)然繼承默認(rèn)的實(shí)現(xiàn)DefaultCommentGenerator也行.然后實(shí)現(xiàn)或者是重寫自己需要的方法.過(guò)程中最好是參照著DefaultCommentGenerator里面的代碼來(lái)做.
沒什么要多說(shuō)的,下文是我的實(shí)現(xiàn).
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.運(yùn)行
MBG(注: 即 MyBatis Generator 的英文縮寫)支持多種方式運(yùn)行,本文只羅列兩種(java方式及maven方式)
如果需要以命令行或其他方式運(yùn)行參照官網(wǎng)文檔:
方法1. java方式(個(gè)人推薦)
直接以main方法運(yùn)行,主要是省事不易出錯(cuò).代碼如下:
public static void main(String[] args) { // 執(zhí)行中的異常信息會(huì)保存在warnings中 List<String> warnings = new ArrayList<String>(); try { // true:生成的文件覆蓋之前的 boolean overwrite = true; // 讀取配置,構(gòu)造 Configuration 對(duì)象. // 如果不想使用配置文件的話,也可以直接來(lái) new Configuration(),然后給相應(yīng)屬性賦值. 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庫(kù)中,類似如下:
<dependency> <groupId>com.saddestmoon</groupId> <artifactId>MyCommentGenerator</artifactId> <version>0.1.SNAPSHOT</version> </dependency>
mybatis-generator-maven-plugin插件添加相關(guān)依賴:
<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,填寫相關(guān)參數(shù),運(yùn)行mybatis generator.
最后自動(dòng)生成的代碼應(yīng)該是類似如下:
/** * 文件代碼 */ private String fileCd; /** * 文件代碼 * @return FILE_CD 文件代碼 */ public String getFileCd() { return fileCd; } /** * 文件代碼 * @param fileCd 文件代碼 */ public void setFileCd(String fileCd) { this.fileCd = fileCd; }
4.可能出現(xiàn)的問(wèn)題
大多數(shù)情況下,到第三步就算是結(jié)束了.下面的,都是踩的坑.
4.1 提示找不到MyCommentGenerator
這個(gè)一般是使用Maven命令運(yùn)行MBG時(shí)才會(huì)出現(xiàn)的錯(cuò)誤.
原因是mybatis-generator-core與MyCommentGenerator不在同一個(gè)ClassPath下,解決方法如下:
參照第3.2,一定要打包生成jar,然后在pom文件mybatis-generator-maven-plugin插件中添加相關(guān)依賴.
使用Java方式(參照3.1)運(yùn)行MBG可以避免該問(wèn)題,也不用打包成jar:
4.2 獲取不到字段注釋
沒錯(cuò),就是introspectedColumn.getRemarks()獲取不到字段的注釋,生成的javabean里面應(yīng)該顯示字段注釋的地方顯示的是null.
配置文件中我們對(duì)<jdbcConnection>做如下修改即可:
<jdbcConnection driverClass="${driver}" connectionURL="{url}" userId="${username}" password="${password}"> <!-- 針對(duì)oracle數(shù)據(jù)庫(kù) --> <property name="remarksReporting" value="true"></property> <!-- 針對(duì)mysql數(shù)據(jù)庫(kù) --> <property name="useInformationSchema" value="true"></property> </jdbcConnection>
問(wèn)題解決
關(guān)于此問(wèn)題的詳細(xì)解決思路,參見另一篇文章 Mybatis Generator 獲取不到字段注釋.如果你用的不是Oracle或Mysql,那么最好看下.
4.3生成的javabean中字段注釋中文亂碼
這個(gè)需要手動(dòng)設(shè)置生成文件的編碼.
在官方文檔<context>一節(jié)中<Property >有相關(guān)說(shuō)明,如下.
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>下的子元素是必須按照規(guī)定順序來(lái)的,否則運(yùn)行會(huì)報(bào)錯(cuò)!
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
IDEA 自帶的數(shù)據(jù)庫(kù)工具真的很牛(收藏版)
這篇文章主要介紹了IDEA 自帶的數(shù)據(jù)庫(kù)工具真的很牛(收藏版),本文以 IntelliJ IDEA/ Mac 版本作為演示,其他版本的應(yīng)該也差距不大,需要的朋友可以參考下2021-04-04java web實(shí)現(xiàn)用戶權(quán)限管理
這篇文章主要介紹了java web實(shí)現(xiàn)用戶權(quán)限管理,設(shè)計(jì)并實(shí)現(xiàn)一套簡(jiǎn)單的權(quán)限管理功能,感興趣的小伙伴們可以參考一下2015-11-11解決MyBatis @param注解參數(shù)類型錯(cuò)誤異常的問(wèn)題
這篇文章主要介紹了解決MyBatis @param注解參數(shù)類型錯(cuò)誤異常的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02Java算法之BFS,DFS,動(dòng)態(tài)規(guī)劃和貪心算法的實(shí)現(xiàn)
廣度優(yōu)先搜索(BFS)和深度優(yōu)先搜索(DFS)是圖遍歷算法中最常見的兩種算法,主要用于解決搜索和遍歷問(wèn)題。動(dòng)態(tài)規(guī)劃和貪心算法則用來(lái)解決優(yōu)化問(wèn)題。本文就來(lái)看看這些算法的具體實(shí)現(xiàn)吧2023-04-04