1. 程式人生 > >MyBatis Generator系列(三)----修改原始碼實現中文註釋

MyBatis Generator系列(三)----修改原始碼實現中文註釋

1)匯入原始碼

再新建一個Maven專案,然後把mybatis-generator-core-1.3.5解壓,複製org目錄到eclipse中去,完整的專案如下:




此時,專案有可能會報錯,因為有依賴包沒有引入,缺少log4j和ant包,在pom.xml中新增上依賴,順便添加了oracle和mysql的驅動程式

     <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.7</version>
    </dependency>
    <dependency>
        <groupId>org.apache.ant</groupId>
        <artifactId>ant</artifactId>
        <version>1.9.0</version>
    </dependency>
    <dependency>
	 <groupId>com.oracle</groupId>
	 <artifactId>ojdbc6</artifactId>
	 <version>6.0</version>
    </dependency>
    <dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.38</version>
    </dependency>


2)修改原始碼


在原始碼裡找到 org.mybatis.generator.internal.DefaultCommentGenerator類進行修改,DefaultCommentGenerator也是實現了CommentGenerator介面:




裡面主要有以下方法:

addJavaFileComment(CompilationUnit compilationUnit)  Java檔案加註釋
addComment(XmlElement xmlElement)  Mybatis的Mapper.xml檔案裡面的註釋
addRootComment(XmlElement rootElement) 為根元素的第一個子節點添加註釋
addJavadocTag(JavaElement javaElement,boolean markAsDoNotDelete) 新增自定義javadoc標籤
addClassComment(InnerClass innerClass,IntrospectedTable introspectedTable) 類註釋
addModelClassComment(TopLevelClass topLevelClass,IntrospectedTable introspectedTable) 模型類添加註釋
addEnumComment(InnerEnum innerEnum,IntrospectedTable introspectedTable) 列舉註釋
addFieldComment(Field field,IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn)  欄位註釋
addFieldComment(Field field, IntrospectedTable introspectedTable) 欄位註釋
addGeneralMethodComment(Method method,IntrospectedTable introspectedTable) 普通方法註釋,mapper介面中方法
addGetterComment(Method method,IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn) Getter方法註釋
addSetterComment(Method method,IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn) Setter方法註釋
addClassComment(InnerClass innerClass,IntrospectedTable introspectedTable, boolean markAsDoNotDelete) 類註釋

具體修改方式參考了以下一些文章:

我就按照上面的步驟操作,做了一些修改,僅供參考;

1、Mapper.xml空格改成四個空格

修改詳情:

org.mybatis.generator.api.dom.OutputUtilities

OutputUtilities 這個類,它裡面有個 xmlIndent 方法是用來控制生成的 xml 檔案中空格的縮排,預設是兩個空格在 sb.append( "  " ) 裡面增加兩個空格就可以了。 


2、修改dao包下的名稱,由原來的XXXMapper改成XXXDao

修改詳情:


org.mybatis.generator.api.IntrospectedTable

calculateJavaClientAttributes方法(大概1335行)將sb.append("Mapper");註釋掉改成 sb.append("Dao");



3、修改Mybatis生成Model的欄位註釋內容:


1)generatorConfig.xml配置裡面設定成:<property name="suppressAllComments" value="false"/>


程式碼修改詳情:


org.mybatis.generator.internal.DefaultCommentGenerator裡面的addFieldComment方法添加註釋程式碼去掉,改成

        field.addJavaDocLine("/**");
        field.addJavaDocLine(" * @Fields "+field.getName()+" "+introspectedColumn.getRemarks());
        field.addJavaDocLine(" */");



4、修改XXXDao.java(XXXMapper.java)的介面方法的Javadoc註釋

程式碼修改詳情:


搜尋org.mybatis.generator.internal.DefaultCommentGenerator如下方法,並註釋方法裡面內容

public void addGeneralMethodComment(Method method,IntrospectedTable introspectedTable)

改成:

        if (suppressAllComments) {
            return;
        }
		
		        StringBuilder sb = new StringBuilder();
        method.addJavaDocLine("/**"); 
        sb.append(" * ");
        if (method.isConstructor()) {
            sb.append(" 構造查詢條件");
        }
        String method_name = method.getName();
        if ("setOrderByClause".equals(method_name)) {
            sb.append(" 設定排序欄位");
        } else if ("setDistinct".equals(method_name)) {
            sb.append(" 設定過濾重複資料");
        } else if ("getOredCriteria".equals(method_name)) {
            sb.append(" 獲取當前的查詢條件例項");
        } else if ("isDistinct".equals(method_name)) {
            sb.append(" 是否過濾重複資料");
        } else if ("getOrderByClause".equals(method_name)) {
            sb.append(" 獲取排序欄位");
        } else if ("createCriteria".equals(method_name)) {
            sb.append(" 建立一個查詢條件");
        } else if ("createCriteriaInternal".equals(method_name)) {
            sb.append(" 內部構建查詢條件物件");
        } else if ("clear".equals(method_name)) {
            sb.append(" 清除查詢條件");
        } else if ("countByExample".equals(method_name)) {
            sb.append(" 根據指定的條件獲取資料庫記錄數");
        } else if ("deleteByExample".equals(method_name)) {
            sb.append(" 根據指定的條件刪除資料庫符合條件的記錄");
        } else if ("deleteByPrimaryKey".equals(method_name)) {
            sb.append(" 根據主鍵刪除資料庫的記錄");
        } else if ("insert".equals(method_name)) {
            sb.append(" 新寫入資料庫記錄");
        } else if ("insertSelective".equals(method_name)) {
            sb.append(" 動態欄位,寫入資料庫記錄");
        } else if ("selectByExample".equals(method_name)) {
            sb.append(" 根據指定的條件查詢符合條件的資料庫記錄");
        } else if ("selectByPrimaryKey".equals(method_name)) {
            sb.append(" 根據指定主鍵獲取一條資料庫記錄");
        } else if ("updateByExampleSelective".equals(method_name)) {
            sb.append(" 動態根據指定的條件來更新符合條件的資料庫記錄");
        } else if ("updateByExample".equals(method_name)) {
            sb.append(" 根據指定的條件來更新符合條件的資料庫記錄");
        } else if ("updateByPrimaryKeySelective".equals(method_name)) {
            sb.append(" 動態欄位,根據主鍵來更新符合條件的資料庫記錄");
        } else if ("updateByPrimaryKey".equals(method_name)) {
            sb.append(" 根據主鍵來更新符合條件的資料庫記錄");
        }
        sb.append(":");
        sb.append(introspectedTable.getFullyQualifiedTable());
        method.addJavaDocLine(sb.toString());

        final List<Parameter> parameterList = method.getParameters();
        if (!parameterList.isEmpty()) {
            method.addJavaDocLine(" *");
            if ("or".equals(method_name)) {
                sb.append(" 增加或者的查詢條件,用於構建或者查詢");
            }
        } else {
            if ("or".equals(method_name)) {
                sb.append(" 建立一個新的或者查詢條件");
            }
        }
        String paramterName;
        for (Parameter parameter : parameterList) {
            sb.setLength(0);
            sb.append(" * @param "); //$NON-NLS-1$
            paramterName = parameter.getName();
            sb.append(paramterName);
            if ("orderByClause".equals(paramterName)) {
                sb.append(" 排序欄位"); //$NON-NLS-1$
            } else if ("distinct".equals(paramterName)) {
                sb.append(" 是否過濾重複資料");
            } else if ("criteria".equals(paramterName)) {
                sb.append(" 過濾條件例項");
            }
            method.addJavaDocLine(sb.toString());
        }

        method.addJavaDocLine(" */"); 


5、修改Model裡面Getter和Setter方法的註釋

程式碼修改詳情:

搜尋org.mybatis.generator.internal.DefaultCommentGenerator修改其中的addGetterComment,addSetterComment方法

addGetterComment修改成如下:

      StringBuilder sb = new StringBuilder();
      method.addJavaDocLine("/**"); //$NON-NLS-1$
      sb.append(" * 獲取 "); //$NON-NLS-1$
      sb.append(introspectedColumn.getRemarks()).append(" 欄位:");
      sb.append(introspectedTable.getFullyQualifiedTable());
      sb.append('.');
      sb.append(introspectedColumn.getActualColumnName());
      method.addJavaDocLine(sb.toString());
      method.addJavaDocLine(" *"); //$NON-NLS-1$
      sb.setLength(0);
      sb.append(" * @return "); //$NON-NLS-1$
      sb.append(introspectedTable.getFullyQualifiedTable());
      sb.append('.');
      sb.append(introspectedColumn.getActualColumnName());
      sb.append(", ");
      sb.append(introspectedColumn.getRemarks());
      method.addJavaDocLine(sb.toString());
      method.addJavaDocLine(" */"); //$NON-NLS-1$

addSetterComment方法修改成如下:
        StringBuilder sb = new StringBuilder();
        method.addJavaDocLine("/**"); //$NON-NLS-1$
        sb.append(" * 設定 ");  //$NON-NLS-1$
        sb.append(introspectedColumn.getRemarks()).append(" 欄位:");
        sb.append(introspectedTable.getFullyQualifiedTable());
        sb.append('.');
        sb.append(introspectedColumn.getActualColumnName());
        method.addJavaDocLine(sb.toString());
        method.addJavaDocLine(" *"); //$NON-NLS-1$
        Parameter parm = method.getParameters().get(0);
        sb.setLength(0);
        sb.append(" * @param "); //$NON-NLS-1$
        sb.append(parm.getName());
        sb.append(" the value for "); //$NON-NLS-1$
        sb.append(introspectedTable.getFullyQualifiedTable());
        sb.append('.');
        sb.append(introspectedColumn.getActualColumnName());
        sb.append(", ");
        sb.append(introspectedColumn.getRemarks());
        method.addJavaDocLine(sb.toString());
        method.addJavaDocLine(" */"); //$NON-NLS-1$

6、註釋掉Mapper.xml裡面的<!-- 註釋 -->,實際使用未用到

程式碼修改詳情:

搜尋org.mybatis.generator.internal.DefaultCommentGenerator如下方法:

public void addComment(XmlElement xmlElement) 

全部註釋掉


7、XML裡面每個SQL增加一個換行

程式碼修改詳情:

org.mybatis.generator.api.dom.xml.XmlElement裡面getFormattedContent裡面加上:

if(indentLevel == 1) {
    //每個insert/update/select之間插入一個空行
    OutputUtilities.newLine(sb);
}


8、修改mybatis的mapper.xml檔案裡面insert和update不根據欄位判斷的非動態SQL

程式碼修改詳情:

org.mybatis.generator.codegen.mybatis3.xmlmapper.XMLMapperGenerator

裡面的getSqlMapElement方法

註釋掉:

addInsertElement(answer);
addUpdateByPrimaryKeyWithoutBLOBsElement(answer);




對應的是mapper.xml裡面的
<insert id="insert" parameterType="xxx" ></insert>
<update id="updateByPrimaryKey" parameterType="xxx" ></update>

9、新增Java檔案註釋,版權資訊

程式碼修改詳情:

找到

org.mybatis.generator.internal.DefaultCommentGenerator

修改addJavaFileComment方法,修改成如下:
    	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
    	compilationUnit.addFileCommentLine("/*");
    	compilationUnit.addFileCommentLine("* "+compilationUnit.getType().getShortName()+".java");
    	compilationUnit.addFileCommentLine("* Copyright(C) 2017-2020 fendo公司");
    	compilationUnit.addFileCommentLine("* @date "+sdf.format(new Date())+"");
    	compilationUnit.addFileCommentLine("*/");

10、新增類註釋

org.mybatis.generator.internal.DefaultCommentGenerator

修改addClassComment方法,修改成如下:
    	innerClass.addJavaDocLine("/**");
    	innerClass.addJavaDocLine(" * @Title "+introspectedTable.getFullyQualifiedTable()+"表的實體類");
    	innerClass.addJavaDocLine(" * @Description "+introspectedTable.getFullyQualifiedTable().getRemarks());
    	innerClass.addJavaDocLine(" * @version 1.0");
    	innerClass.addJavaDocLine(" * @Author fendo");
    	innerClass.addJavaDocLine(" * @Date " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    	innerClass.addJavaDocLine(" */");

其中getRemarks()是獲取資料庫表註釋的方法,需要單獨在org.mybatis.generator.api.FullyQualifiedTable類中新增一個remarks欄位,然後建立好get,set方法。


然後修改org.mybatis.generator.internal.db.DatabaseIntrospector的calculateIntrospectedTables方法新增以下程式碼

//設定資料庫表的備註資訊
   Statement stmt = this.databaseMetaData.getConnection().createStatement();
            ResultSet rs = stmt.executeQuery(new StringBuilder().append("SHOW TABLE STATUS LIKE '").append(atn.getTableName()).append("'").toString());
            while (rs.next())
            //將資料庫表得備註資訊設定到remark欄位
                table.setRemark(rs.getString("COMMENT"));

 closeResultSet(rs);


完整的DefaultCommentGenerator檔案如下:


3)測試

新建測試類StartUp

package com.fendo.test;


import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;

/**   
 * @Title: StartUp.java 
 * @Package com.fendo.mybatis_generator_plus 
 * @Description: TODO
 * @author fendo
 * @date 2017年10月5日 下午3:53:17 
 * @version V1.0   
*/
public class StartUp {

	public static void main(String[] args) throws URISyntaxException {
        try {
        	System.out.println("--------------------start generator-------------------");
            List<String> warnings = new ArrayList<String>();
            boolean overwrite = true;
            ClassLoader classloader = Thread.currentThread().getContextClassLoader();
            InputStream is = classloader.getResourceAsStream("generatorConfig.xml");
            ConfigurationParser cp = new ConfigurationParser(warnings);
            Configuration config = cp.parseConfiguration(is);
            DefaultShellCallback callback = new DefaultShellCallback(overwrite);
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
            myBatisGenerator.generate(null);
        	System.out.println("--------------------end generator-------------------");
        } 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();
        }
    }
}

附上配置檔案
<?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> 

	<!-- 引入配置檔案 --> 
	<!-- 指定資料連線驅動jar地址 --> 
	<classPathEntry location="D:\MavenRepository\mysql\mysql-connector-java\5.1.38\mysql-connector-java-5.1.38.jar" /> 
	
	<context id="DB2Tables"  targetRuntime="MyBatis3">
	    <!-- 設定編碼為UTF-8 -->
	    <property name="javaFileEncoding" value="UTF-8"/>
	    <!--配置生成註釋,預設註釋已經修改 -->
	    <property name="suppressAllComments" value="false"/>
         <!--資料庫連結URL,使用者名稱、密碼 -->   
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test" userId="root" password="root">  
        </jdbcConnection>  
        <javaTypeResolver>  
            <property name="forceBigDecimals" value="false"/>  
        </javaTypeResolver>  
        <!-- 生成模型的包名和位置-->  
        <javaModelGenerator targetPackage="com.fendo.test" targetProject="src/main/java">  
            <property name="enableSubPackages" value="true"/>  
            <property name="trimStrings" value="true"/>  
        </javaModelGenerator>  
        <!-- 生成對映檔案的包名和位置-->  
        <sqlMapGenerator targetPackage="com.fendo.test" targetProject="src/main/java">  
            <property name="enableSubPackages" value="true"/>  
        </sqlMapGenerator>  
        <!-- 生成DAO的包名和位置-->  
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.fendo.test" targetProject="src/main/java">  
            <property name="enableSubPackages" value="true"/>  
        </javaClientGenerator>  
        <!-- 要生成的表 tableName是資料庫中的表名或檢視名 domainObjectName是實體類名-->  
        <table tableName="test" domainObjectName="Test" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
    </context>  
</generatorConfiguration>

執行StartUp生成的檔案如下:


Test檔案


Dao檔案


Mapper檔案


4)打包

在POM.XML檔案中加入以下依賴:

	    <plugin>
              <!-- 因為專案中使用了依賴包,所以要使用maven-assembly-plugin來構建,會把依賴包同時打進jar包中 -->
              <artifactId>maven-assembly-plugin</artifactId>
              <version>2.6</version>
              <configuration>
                  <!-- 這裡不指定為false打包會生成兩個jar包,我們要用的那個jar包命名很亂,後面加了
                  jar-with-dependencies,不喜歡,直接禁用掉 -->
                  <appendAssemblyId>false</appendAssemblyId>
                  <archive>
                      <manifest>
                          <!-- 指定類的全路徑  否則執行會報找不到main class的錯誤-->
                          <mainClass>org.mybatis.generator.api.ShellRunner</mainClass>
                      </manifest>
                  </archive>
                  <descriptorRefs>
                      <descriptorRef>jar-with-dependencies</descriptorRef>
                  </descriptorRefs>
              </configuration>
              <executions>
                  <execution>
                      <id>make-assembly</id>
                      <phase>package</phase>
                      <goals>
                          <goal>single</goal>
                      </goals>
                  </execution>
              </executions>
        </plugin>

然後在檔案中執行打包命令:
mvn clean package

執行成功會得到一個jar包


然後複製到一個檔案下,測試下


可以自己新建cmd命令,或通過以下命令執行:

   java -jar mybatis-generator-plus.jar -configfile generatorConfig.xml
   java -jar mybatis-generator-plus.jar -configfile generatorConfig.xml -overwrite
   java -cp mybatis-generator-plus.jar org.mybatis.generator.api.ShellRunner -configfile generatorConfig.xml
   java -cp mybatis-generator-plus.jar org.mybatis.generator.api.ShellRunner -configfile generatorConfig.xml -overwrite


完整專案:

有時會報莫名其妙的錯誤如下:

java.net.MalformedURLException
        at java.net.URL.<init>(URL.java:627)
        at java.net.URL.<init>(URL.java:490)
        at java.net.URL.<init>(URL.java:439)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:620)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1304)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startDTDEntity(XMLEntityManager.java:1270)
        at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.setInputSource(XMLDTDScannerImpl.java:264)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(XMLDocumentScannerImpl.java:1161)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(XMLDocumentScannerImpl.java:1045)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:959)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
        at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
        at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
        at org.mybatis.generator.config.xml.ConfigurationParser.parseConfiguration(ConfigurationParser.java:140)
        at org.mybatis.generator.config.xml.ConfigurationParser.parseConfiguration(ConfigurationParser.java:113)
        at org.mybatis.generator.config.xml.ConfigurationParser.parseConfiguration(ConfigurationParser.java:105)
        at org.mybatis.generator.api.ShellRunner.main(ShellRunner.java:107)
Caused by: java.lang.NullPointerException
        at java.net.URL.<init>(URL.java:532)
        ... 20 more

這是由於在編譯的時候,沒有把以下兩個檔案編譯進來,所有會提示上面的錯誤,debug了半天才發現了問題所在:

解決方法就是在POM.XML中加入以下內容:

    <finalName>mybatis-generator-plus</finalName>
    <resources>  
        <resource>  
            <directory>src/main/resources</directory>  
            <includes>  
                <include>**/*.properties</include>  
                <include>**/*.xml</include>  
                <include>**/*.tld</include> 
                <include>**/*.dtd</include>  
            </includes>  
            <filtering>false</filtering>  
        </resource>  
        <resource>  
            <directory>src/main/java</directory>  
            <includes>  
                <include>**/*.properties</include>  
                <include>**/*.xml</include>  
                <include>**/*.tld</include>  
                <include>**/*.dtd</include>  
            </includes>  
            <filtering>false</filtering>  
        </resource>  
    </resources> 


5)注意

1、Mybatis Generator 獲取不到欄位註釋

Oracle 資料庫

<jdbcConnection driverClass="${driver}"
    connectionURL="{url}" userId="${username}" password="${password}">
    <!-- 針對oracle資料庫 -->
    <property name="remarksReporting" value="true"></property>
</jdbcConnection>

MySql 資料庫

方法1

<jdbcConnection driverClass="${driver}"
    connectionURL="{url}" userId="${username}" password="${password}">
    <!-- 針對mysql資料庫 -->
    <property name="useInformationSchema" value="true"></property>
</jdbcConnection>

方法2

mysql的connectionURL中新增 useInformationSchema=true.大體上就是:
connectionURL="jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&useInformationSchema=true"


2、mybatis generator 不能生成類註釋

在原始碼裡找到 org.mybatis.generator.internal.DefaultCommentGenerator類,這個類中addClassComment這個方法 是標註中文註釋的。為了使addClassComment生效,還得找到org.mybatis.generator.codegen.mybatis3.model.BaseRecordGenerator類,在大約60行的地方,在

commentGenerator.addJavaFileComment(topLevelClass);

後加一句:

commentGenerator.addClassComment(topLevelClass, introspectedTable,false);

這樣方法就呼叫到了。