自定義Mybatis逆向工程Maven外掛
我的一篇部落格介紹了基於Java Config形式的Mybatis逆向工程,通過定義幾個java變數,然後執行main方法可以執行逆向工程,這篇部落格就是將那個工程改造成一個Maven外掛。
開發Maven外掛,首先需要建立一個Maven Plugin專案,我是基於IDEA開發的。IDEA如何建立Maven外掛專案自行百度,這裡就不說了。
建立好Mojo專案後,需要修改器Pom.xml檔案,指定packaging型別為maven-plugin,同時新增開發外掛的依賴:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns ="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bob</groupId>
<artifactId> plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<properties>
<maven.version>3.5.2</maven.version>
<plugin-annotations.version>3.3</plugin-annotations.version>
<mybatis-generator >1.3.5</mybatis-generator>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>${plugin-annotations.version}</version>
</dependency>
<!-- Mybatis 逆向工程 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>${mybatis-generator}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
@Mojo():定義外掛目標,一個外掛可以有多個目標,也就是有 多個@Mojo標識的AbstractMojo子類,繫結外掛時可以自由選擇將哪個目標繫結到Maven生命週期的某個階段。
下一步你需要有一個類去繼承AbstractMojo,重寫其execute方法,外掛在執行時會呼叫此方法,也就是說此方法是外掛的入口。外掛在啟動時會例項化一個AbstractMojo的子類,具體例項化誰需要看@Mojo註解在哪層子類上,所以此處我定義了兩個類直接或間接繼承AbstractMojo,MybatisGeneratorConfig作為配置類,MybatisGenerator是實際執行逆向工程的工具類,MybatisGenerator 繼承MybatisGeneratorConfig,將@Mojo標識在MybatisGenerator上。這樣MybatisGenerator在執行execute方法時能夠獲取到MybatisGeneratorConfig裡的配置資訊。
/**
* Mybatis逆向工程解析器
* 基於Mybatis Generator 1.3.5 Release
*
* @author wb-jjb318191
* @create 2017-09-28 17:08
*/
public abstract class MybatisGenerator extends AbstractMojo {
/**
* 指定要生成的Table
*/
@Parameter(required = true)
protected List<String> tables;
/**
* 連線資料庫驅動包,預設地址字首是"targetModule"模組下的resources路徑
*/
@Parameter(defaultValue = "mysql-connector-java-5.1.44-bin.jar")
protected String driverPath;
/**
* 指定生成java檔案的編碼格式
*/
@Parameter(defaultValue = "UTF-8")
protected String fileEncoding;
/**
* 指定JDBC資訊
*/
@Parameter(defaultValue = "com.mysql.jdbc.Driver")
protected String driverClass;
/**
* 指定連線資料庫的地址
*/
@Parameter(defaultValue = "jdbc:mysql://localhost:3306/project")
protected String connectionUrl;
/**
* 使用者名稱
*/
@Parameter(defaultValue = "root")
protected String userName;
/**
* 密碼
*/
@Parameter(defaultValue = "lanboal")
protected String password;
/**
* 指定專案根目錄
*/
@Parameter(property = "user.dir")
private String projectRootPath;
/**
* 指定檔案生成的模組
*/
@Parameter(defaultValue = "")
private String targetModule;
/**
* java根路徑
*/
@Parameter(defaultValue = "\\src\\main\\java")
private String javaPath;
/**
* 資源根路徑
*/
@Parameter(defaultValue = "\\src\\main\\resources")
private String resuorcesPath;
/**
* 指定Java Model生成位置
*/
protected String javaModelTargetProject;
/**
* java實體類包名
*/
@Parameter(defaultValue = "com.bob.project.mvc.entity.model")
protected String javaModelPackage;
/**
* 指定Java DAO介面生成位置
*/
protected String javaMapperTargetProject;
/**
* Mapper介面包名
*/
@Parameter(defaultValue = "com.bob.project.mvc.mapper")
protected String javaMapperPackage;
/**
* 指定Mapper.xml生成位置
*/
protected String sqlmapTargetproject;
/**
* Mapper.xml檔案路徑
*/
@Parameter(defaultValue = "com.bob.project.mvc.mapper", required = false)
protected String sqlMapperPackage;
/**
* 初始化引數
*/
protected void initParameter() {
if (!"".equals(targetModule)) {
targetModule = "\\" + targetModule;
}
String pathPrefix = projectRootPath + targetModule;
javaModelTargetProject = pathPrefix + javaPath;
javaMapperTargetProject = pathPrefix + javaPath;
sqlmapTargetproject = pathPrefix + resuorcesPath;
//獲取驅動Jar包的路徑,若不是本地地址,則加上專案字首
if (!driverPath.contains(":")) {
driverPath = sqlmapTargetproject + "\\" + driverPath;
}
}
protected void printParameters() {
System.out.println("列印逆向工程列印引數");
System.out.println("tables :" + tables.toString());
System.out.println("fileEncoding :" + fileEncoding.toString());
System.out.println("driverPath :" + driverPath.toString());
System.out.println("driverClass :" + driverClass.toString());
System.out.println("connectionUrl :" + connectionUrl.toString());
System.out.println("userName :" + userName.toString());
System.out.println("password :" + password.toString());
System.out.println("targetModule :" + targetModule.toString());
System.out.println("projectRootPath :" + projectRootPath.toString());
System.out.println("javaModelTargetProject :" + javaModelTargetProject.toString());
System.out.println("javaMapperTargetProject :" + javaMapperTargetProject.toString());
System.out.println("sqlmapTargetproject :" + sqlmapTargetproject.toString());
}
}
/**
* Mybatis逆向工程基於Java形式的配置類
*
* @author wb-jjb318191
* @create 2017-09-30 9:17
*/
@Mojo(name = "mybatisGenerate")
public class MybatisGenerator extends MybatisGeneratorConfig {
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
initParameter();
printParameters();
try {
Configuration config = configMybatisGenerator();
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, new DefaultShellCallback(true), new ArrayList<String>());
myBatisGenerator.generate(null);
} catch (Exception e) {
System.out.println("逆向工程執行失敗");
e.printStackTrace();
}
}
public Configuration configMybatisGenerator() {
Configuration configuration = new Configuration();
configuration.addClasspathEntry(driverPath);
Context context = new Context(null);
context.setTargetRuntime("MyBatis3");
context.setId("wb-jjb318191");
context.addProperty("javaFileEncoding", fileEncoding);
//設定註解生成器
context.setCommentGeneratorConfiguration(generateCommentConfiguration());
//設定JDBC連線配置
context.setJdbcConnectionConfiguration(generateJDBCConnectionConfiguration());
//設定JDBC Type 與Java Type之間的對映解析器
context.setJavaTypeResolverConfiguration(generateJavaTypeResolverConfiguration());
//設定Java Model生成配置
context.setJavaModelGeneratorConfiguration(generateJavaModelGeneratorConfiguration());
//設定DAO層的生成配置
context.setSqlMapGeneratorConfiguration(generateSqlMapGeneratorConfiguration());
//設定Mapper.xml生成
context.setJavaClientGeneratorConfiguration(generateJavaClientGeneratorConfiguration());
//設定需要生成的Table及生成形式
for (TableConfiguration tableConfiguration : generateTableConfigurations(context)) {
context.addTableConfiguration(tableConfiguration);
}
configuration.addContext(context);
return configuration;
}
/**
* 配置註解生成器
*
* @return
*/
private CommentGeneratorConfiguration generateCommentConfiguration() {
CommentGeneratorConfiguration configuration = new CommentGeneratorConfiguration();
configuration.setConfigurationType(GeneralCommentGenerator.class.getName());
//是否去除自動生成的註釋 true:是 : false:否
configuration.addProperty("suppressAllComments", "false");
configuration.addProperty("addRemarkComments", "true");
return configuration;
}
/**
* 設定資料庫連線的資訊:驅動類、連線地址、使用者名稱、密碼
*
* @return
*/
private JDBCConnectionConfiguration generateJDBCConnectionConfiguration() {
JDBCConnectionConfiguration configuration = new JDBCConnectionConfiguration();
configuration.setDriverClass(driverClass);
String jdbcSuffix = "?useUnicode=true&characterEncoding=UTF8&useSSL=false";
configuration.setConnectionURL(connectionUrl + jdbcSuffix);
configuration.setUserId(userName);
configuration.setPassword(password);
return configuration;
}
/**
* 設定JDBC Type 與Java Type之間的對映解析器
*
* @return
*/
private JavaTypeResolverConfiguration generateJavaTypeResolverConfiguration() {
JavaTypeResolverConfiguration configuration = new JavaTypeResolverConfiguration();
//可自定義型別對映解析器
configuration.setConfigurationType(null);
//預設false,把JDBC DECIMAL 和 NUMERIC 型別解析為 Integer,為 true時把JDBC DECIMAL 和 NUMERIC 型別解析為java.math.BigDecimal
configuration.addProperty("forceBigDecimals", "true");
return configuration;
}
/**
* 配置Java Model生成
*
* @return
*/
private JavaModelGeneratorConfiguration generateJavaModelGeneratorConfiguration() {
JavaModelGeneratorConfiguration configuration = new JavaModelGeneratorConfiguration();
configuration.setTargetProject(javaModelTargetProject);
configuration.setTargetPackage(javaModelPackage);
//是否讓schema作為包的字尾
configuration.addProperty("enableSubPackages", "false");
//從資料庫返回的值被清理前後的空格
configuration.addProperty("trimStrings", "true");
return configuration;
}
/**
* 配置Mapper.xml生成
*
* @return
*/
private SqlMapGeneratorConfiguration generateSqlMapGeneratorConfiguration() {
SqlMapGeneratorConfiguration configuration = new SqlMapGeneratorConfiguration();
configuration.setTargetProject(sqlmapTargetproject);
configuration.setTargetPackage(sqlMapperPackage);
//是否讓schema作為包的字尾
configuration.addProperty("enableSubPackages", "false");
return configuration;
}
/**
* 設定DAO生成
*
* @return
*/
private JavaClientGeneratorConfiguration generateJavaClientGeneratorConfiguration() {
JavaClientGeneratorConfiguration configuration = new JavaClientGeneratorConfiguration();
configuration.setConfigurationType("XMLMAPPER");
configuration.setTargetProject(javaMapperTargetProject);
configuration.setTargetPackage(javaMapperPackage);
//是否讓schema作為包的字尾
configuration.addProperty("enableSubPackages", "false");
return configuration;
}
private List<TableConfiguration> generateTableConfigurations(Context context) {
List<TableConfiguration> configurations = new ArrayList<TableConfiguration>();
for (Object table : tables) {
TableConfiguration configuration = new TableConfiguration(context);
configuration.setTableName((String)table);
configuration.setSelectByExampleStatementEnabled(false);
configuration.setDeleteByExampleStatementEnabled(false);
configuration.setCountByExampleStatementEnabled(false);
configuration.setUpdateByExampleStatementEnabled(false);
configurations.add(configuration);
}
return configurations;
}
}
還有一個類GeneralCommentGenerator和之前那篇部落格的一樣,就不列出來了,總共就是三個類。
我在MybatisGeneratorConfig類裡的變數上標識了很多@Parameter註解,這些註解指定了外掛在配置時能夠傳入哪些外部引數,Maven外掛在啟動時例項化@Mojo標識類的物件,同時將外部引數傳入到此類(或父類)的屬性中。@Parameter可以定義外掛配置的形式,是否有預設值,是否僅可讀,是否必須等等,若是必須的則在配置外掛時必須有值。
以上就是外掛的所有程式碼了,之後執行Maven的install命令,將外掛安裝到本地maven倉庫。
下面就是在其他專案中使用整個外掛。
首先需要在專案中引入自定義的maven外掛:
<plugins>
<!--############## Maven依賴外掛 ############## -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<groupId>com.bob</groupId>
<artifactId>plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<tables>
<table>bank_account</table>
<table>emp</table>
</tables>
<targetModule>project-root</targetModule>
</configuration>
<executions>
<execution>
<id>generate</id>
<phase>compile</phase>
<goals>
<goal>mybatisGenerate</goal> <!--執行完之後註釋掉 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
我預設是在一臺電腦上,剛剛已經將外掛安裝到了本地maven倉庫,所以這裡引用能夠直接生效。
可以通過Ctrl+左鍵點選configuration內的配置,檢視當前外掛的可配置選項。
我們將逆向工程外掛的mybatisGenerate目標繫結到了compile階段,也就是說在執行maven compile生命週期時會觸發此外掛的相應目標。
外掛配置在了project目錄下的pom.xml裡,逆向工程的資料庫驅動包放在了project-root下,同時制定生成的Model,Mapper介面及Mapper.xml也指向project-root專案。生成的包的路徑,資料庫地址,使用者名稱,密碼等等資訊我在外掛裡做了預設配置,需要的可以在< configuration>覆蓋預設配置,同時若專案的結構和我的不相同,只要修改下外掛裡的預設配置就好了。自行看外掛原始碼,很明瞭的。
在指定好要生成的資料庫表之後,在IDEA裡執行complie,就能執行逆向工程外掛了,執行完之後務必將< goal>,否則每次編譯都會執行此外掛了。