Mybatis Generator外掛自動生成xml對映檔案追加與覆蓋的問題
參考:
使用Mybatis Generator可以快速根據資料庫中已經建立好的表來建立mybatis程式碼,但是一旦資料庫的表結構發生變動,就要重新執行Mybatis Generator外掛。每次執行都會在已經生成的xml後追加一遍所有的內容(包括原來已經生成的程式碼,相當於一個xml中定義了兩次老程式碼)。而po類檔案和java介面檔案會被完全覆蓋。
首先,你可以在每次重新生成之前,手動刪除原來所有的檔案,這樣可以解決追加重複內容的問題。但是如果你要實現一些自定義的資料庫操作方法,那如果每次刪除xml豈不是每次都要重新寫自定義的方法?
那現在我希望的是,既可以不用每次都手動刪除,又可以保留之前自定義的內容。
自定義MybatisGenerator外掛解決重複追加內容的問題
在pom.xml引入jar包的依賴
<!-- mybatis 整合--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.7</version> </dependency>
然後自定義外掛
public class OverwriteXmlPlugin extends PluginAdapter { @Override public boolean validate(List<String> warnings) { return true; } @Override public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) { sqlMap.setMergeable(false); return super.sqlMapGenerated(sqlMap, introspectedTable); } }
很簡單,只要把Mergeable這個預設是true的值給設定成false就可以了。
將這個類放入到我們的專案中,然後在Gegerator的配置檔案中進行配置(要在context節點下新增)
<!-- 覆蓋xml檔案 -->
<plugin type="com.springapp.mvc.dao.OverwriteXmlPlugin"></plugin>
然後執行generator外掛,報錯
Failed to execute goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.7:generate (default-cli) on project RemoteMonitoringJava: Execution default-cli of goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.7:generate failed: Cannot instantiate object of type com.springapp.mvc.dao.OverwriteXmlPlugin -> [Help 1]
由於沒有詳細資訊,這時候在maven後新增-e -X再試一下,檢視詳細報錯
mybatis-generator:generate -e -X
Caused by: java.lang.RuntimeException: Cannot instantiate object of type com.springapp.mvc.dao.OverwriteXmlPlugin
at org.mybatis.generator.internal.ObjectFactory.createInternalObject(ObjectFactory.java:182)
at org.mybatis.generator.internal.ObjectFactory.createPlugin(ObjectFactory.java:219)
at org.mybatis.generator.config.Context.generateFiles(Context.java:500)
at org.mybatis.generator.api.MyBatisGenerator.generate(MyBatisGenerator.java:269)
at org.mybatis.generator.api.MyBatisGenerator.generate(MyBatisGenerator.java:189)
at org.mybatis.generator.maven.MyBatisGeneratorMojo.execute(MyBatisGeneratorMojo.java:229)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
... 26 more
發現在ObjectFactory中,通過反射生成物件的時候找不到類,看一下原始碼,發現這裡使用
Thread.currentThread().getContextClassLoader()獲取的classloader載入類例項,那我們這個自定義的外掛類也沒有被這個classloader載入啊,所以肯定是無法生成例項的。
檢視一下網上關於自定義外掛的教程。
首先,將剛才自定義的外掛,提取出來,新建一個Java專案,然後將上面寫的依賴也匯入,再將剛才外掛類放入專案中。
使用itellij或是eclipse的功能將專案打成jar包。
使用maven命令將這個jar包釋出到本地的maven庫中。
install:install-file -Dfile=f:/overwritexml.jar -DgroupId=com.ryan -DartifactId=overwritexml -Dversion=0.0.1-SNAPSHOT -Dpackaging=jar
紅色字型根據自己的情況調整。
釋出成功後,在pom.xml配置mybatisGenerator外掛的地方新增對這個jar包的依賴:
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<dependencies>
<dependency>
<groupId>com.ryan</groupId>
<artifactId>overwritexml</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<configuration>
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
Dependencies節點下的內容是新加的。
然後再試一次就可以啦,注意下面的這個包名要調整一下,和jar包中的保持一致。但是現在這個十分依賴本地的環境,如果是公司協同開發的話,可以考慮將這個jar包釋出到公司搭建的私有maven倉庫中。
<!-- 覆蓋xml檔案 -->
<plugin type="com.ryan.overwritexml.OverwriteXmlPlugin"></plugin>
解決覆蓋自定義xml中內容的問題
現在每次執行外掛就不用了 每次刪除原有的xml檔案了。但是我自己新定義的方法也被完全覆蓋掉了。
這時候,我一般會使用一個方法(不一定是最合適最正確的,但我自己使用沒什麼問題,可以作為一個參考的方法)。
比如有個使用者表UserTable,通過generator會生成三個檔案,一個mapper對映檔案,UserMapper.xml;一個Po類檔案,User.java;一個Java interface的mapper介面檔案,UserMapper.java.
此時再UserMapper.xml中,mapper節點namespace屬性的值是UserMapper.java的包名+類名。
這時我如果想新加入一個查詢註冊時間在2018年且性別為男性所有使用者的方法,如果還是在UserMapper.xml和UserMapper.java直接加程式碼,下次再用generator生成檔案的時候就會把我們自定義的內容覆蓋掉。
那這時我可以新建一個ExUserMapper.java的介面類,然後定義一個新的方法getUsers(String gender,long startTimestamp,long endTimestamp),然後和UserMapper.java放在相同的包下。
再定義一個ExUserMapper.xml,從UserMapper.xml複製過來resultMap標籤下的內容,然後將namespace的值從UserMapper介面類的全路徑改成ExUserMapper介面類的全路徑,並新增一個id為getUsers的select查詢。
在程式碼裡可以完全使用ExUserMapper.java來生命物件並使用,因為ExUserMapper.java繼承了UserMapper.java,所以UserMapper中提供的基本操作用ExUserMapper也可以獲取到。
唯一的問題就是,如果表結構發生改變了,別忘了把ExUserMapper.xml中的ResultMap同步更新一下。