mybatis-plus generator自動生成代碼
- 一、概述
- 二、具體實作
-
- 2.1 pom檔案依賴
- 2.2 核心Config類
- 2.3 最終效果
- 三、問題是如何解決的
-
- 3.1 解決重複代碼的問題
- 3.2 解決重新生成時的檔案覆寫問題
- 3.3 支援自定義模版和自定義參數
- 四、參考
一、概述
之前一直使用mybatis的自動代碼生成,雖然也能基本滿足要求,但是在實際使用過程中還是存在問題,比如:
- 自動生成的代碼,每一個mapper,每一個service都會有大量的重複代碼,重複代碼不處理吧看着不舒服,處理的話呢,需要抽象出一個基礎類,在spring環境下,對基礎類以及子類初始化又顯得不夠優雅(參考該項目shuzheng/zheng);
- 在開發過程中,發現需要修改表結構,每次重新生成的話怎麼指定哪些檔案是需要覆寫的;
- 如何自定義模版檔案,且支援自定義變量
帶着這些問題,又重新研究了mybatis的好基友mybatis-plus,發現基本上可以完美解決以上面臨的問題。
二、具體實作
2.1 pom檔案依賴
<properties>
<mybatis-plus.version>3.1.2</mybatis-plus.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<dependencies>
<!-- starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- 資料庫 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<!-- 自動生成代碼 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- 工具 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.0-jre</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
</dependencies>
2.2 核心Config類
@Data
public class GeneratorConfig {
private static String projectPath = currentProjectPath();
private DataSourceConfig dataSourceConfig;
private GlobalConfig globalConfig;
private PackageConfig packageConfig;
private TemplateConfig templateConfig;
private StrategyConfig strategyConfig;
private InjectionConfig injectionConfig;
private List<String> includeTableNames;
public GeneratorConfig() {
this.dataSourceConfig = new DataSourceConfig();
this.globalConfig = initGlobalConfig();
this.packageConfig = new PackageConfig();
this.strategyConfig = initStrategyConfig();
this.templateConfig = initTemplateConfig();
this.injectionConfig = initInjectionConfig();
}
/**
* 全局配置
*/
private static GlobalConfig initGlobalConfig() {
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(projectPath + "/src/main/java");
gc.setOpen(false);
gc.setEntityName("%sEntity");
gc.setServiceName("%sService");
// 預設允許覆寫檔案
gc.setFileOverride(true);
return gc;
}
/**
* 政策配置
*/
private static StrategyConfig initStrategyConfig() {
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
return strategy;
}
/**
* 模版配置
* 優先掃描本項目中的templates目錄
*/
private static TemplateConfig initTemplateConfig() {
TemplateConfig config = new TemplateConfig();
// 不生成Controller
config.setController(null);
return config;
}
/**
* 自定義配置
*/
private static InjectionConfig initInjectionConfig() {
// 自定義參數,在模版檔案裡通過${cfg.xxx}引用
InjectionConfig config = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = this.getMap();
if (map == null) {
map = new HashMap<>();
this.setMap(map);
}
String datetime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
map.put("datetime", datetime);
}
};
// 如果目前檔案已經存在,則僅允許覆寫Entity
IFileCreate fileCreate = (configBuilder, fileType, filePath) -> {
if (new File(filePath).exists()) {
if (configBuilder.getGlobalConfig().isFileOverride()) {
return FileType.ENTITY.equals(fileType);
} else {
return false;
}
}
return true;
};
config.setFileCreate(fileCreate);
return config;
}
private static String currentProjectPath() {
String projectCompletePath = Objects.requireNonNull(ClassLoader.getSystemClassLoader().getResource("")).getPath();
if (projectCompletePath.startsWith("/")) {
projectCompletePath = projectCompletePath.replaceFirst("/", "");
}
return projectCompletePath.replace("/target/classes/", "");
}
}
2.3 最終效果
三、問題是如何解決的
我們來看看文章開頭提出的兩個問題是如何解決的
3.1 解決重複代碼的問題
這個從最終的結果來看,mybatis-plus自動給我們繼承了一個基礎類,完全不用我們自己操心。
3.2 解決重新生成時的檔案覆寫問題
// 如果目前檔案已經存在,則僅允許覆寫Entity
IFileCreate fileCreate = (configBuilder, fileType, filePath) -> {
if (new File(filePath).exists()) {
if (configBuilder.getGlobalConfig().isFileOverride()) {
return FileType.ENTITY.equals(fileType);
} else {
return false;
}
}
return true;
};
config.setFileCreate(fileCreate);
3.3 支援自定義模版和自定義參數
- 首先需要在resources目錄下建立目錄templates,然後将模版檔案放進去,需要注意模版檔案必須和TemplateEngine比對。
- 在模版檔案裡添加自定義參數,例如datetime,通過${cfg.datetime}的方式
/**
* Description:
* ${table.comment!}
*
* @author ${author}
* @since ${cfg.datetime}
*/
- 在代碼裡配置自定義配置
// 自定義參數,在模版檔案裡通過${cfg.xxx}引用
InjectionConfig config = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = this.getMap();
if (map == null) {
map = new HashMap<>();
this.setMap(map);
}
String datetime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
map.put("datetime", datetime);
}
};
四、參考
- 所有代碼都在個人github項目裡mybatis-generator
- mybatis-plus官網