idea + groovy + mybatis 自動生成 Dao、mappings 和 實體類
背景
在 windows 系統中,idea 在 C:\Users\使用者名稱\.IntelliJIdea2018.2\config\extensions\com.intellij.database\schema
目錄下預設存在如下 Groovy 檔案:Generate POJOs.groovy
,配合 idea 的 Database 資料庫管理工具,可以快速生成 POJO 類。
於是我想何不基於這個類編寫 groovy 程式碼自動生成 mappings 和 dao 呢,並按自己專案需要改造 Generate POJOs.groovy
。
Groovy
groovy 是在 java 平臺上的、具有象 Python,Ruby 和 Smalltalk 語言特性的靈活動態語言,groovy 保證了這些
特性象 java 語法一樣被 java 開發者使用。 – 《Groovy in action》
Groovy 跟 java 一樣是運行於 JVM 之上的語言,比起 java 擁有許多語法上的便利,可以無縫使用 java 類庫及其特性,甚至可以直接用 Groovy 開發 Web 程式。
推薦一個 Youtube 上一小時多的視訊,看完 Groovy 的大部分語法也就掌握了: Groovy Tutorial
實現
無論是修改 Generate POJOs.groovy
還是在其基礎之上編寫新的 groovy 檔案都需要將其放於C:\Users\使用者名稱\.IntelliJIdea2018.2\config\extensions\com.intellij.database\schema
com.intellij.database.*
才能找到,新建 idea 專案也會在 Scratches and Consoles 目錄下找到。連上資料庫後就可以選中要生成的表,滑鼠右鍵即可看到。
程式碼說明
先拿 Generate POJOs.groovy
舉例進行說明,關鍵程式碼如下:
FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->
SELECTION.filter { it instanceof DasTable }.each { generate(it, dir) }
}
def generate(table, dir) {
def className = javaName(table.getName(), true)
def fields = calcFields(table)
// 實體類字尾需要手動設定,這裡為 Entity
new File(dir, className + "Entity.java").withPrintWriter { out -> generate(out, className + "Entity", fields) }
}
def generate(out, className, fields) {
...
}
FILES.chooseDirectoryAndSave
是在 idea 的 Database 視窗滑鼠右鍵點選 groovy 選項後彈出資料夾選擇框關閉時回撥的方法,DasTable 指代一張表,儲存了該張表中的一些資訊,如表名,欄位等,dir 是選中的資料夾。
generate 方法會根據 table 和 dir 生成目標檔案。generate(out, className, fields)
方法是正真進行模板生成並寫入檔案的地方。
def generate(out, className, fields) {
def date = new Date().format("yyyy/MM/dd")
out.println "package $packageName"
out.println "import java.io.Serializable;"
out.println "import java.util.Date;"
out.println ""
out.println "/**"
out.println " * Created on $date."
out.println " *"
out.println " * @author XX" // 可自定義
out.println " */"
out.println "public class $className implements Serializable {"
out.println ""
fields.each() {
if (isNotEmpty(it.comment)) {
out.println "\t/**"
out.println "\t * ${it.comment}"
out.println "\t */"
}
if (it.annos != "")
out.println "\t${it.annos}"
out.println "\tprivate ${it.type} ${it.name};"
out.println ""
}
fields.each() {
out.println ""
out.println "\tpublic ${it.type} get${it.name.capitalize()}() {"
out.println "\t\treturn ${it.name};"
out.println "\t}"
out.println ""
out.println "\tpublic void set${it.name.capitalize()}(${it.type} ${it.name}) {"
out.println "\t\tthis.${it.name} = ${it.name};"
out.println "\t}"
}
out.println "}"
}
另外還有兩個方法是比較重要的:
def calcFields(table) {
DasUtil.getColumns(table).reduce([]) { fields, col ->
def spec = Case.LOWER.apply(col.getDataType().getSpecification())
def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.value
fields += [[
comment: col.getComment(), // 表字段說明
name : javaName(col.getName(), false), // 欄位名對應到 java 駝峰變數名
type : typeStr, // 將資料庫欄位型別對映到 java 型別
annos : ""]]
}
}
def javaName(str, capitalize) {
def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
.collect { Case.LOWER.apply(it).capitalize() }
.join("")
.replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")
name = capitalize || s.length() == 1 ? s : Case.LOWER.apply(s[0]) + s[1..-1]
}
calcFields 方法會遍歷並取出 DasTable 中每一個欄位的屬性並放入 fields 中,fields 型別相當於 java 中一個元素型別為 Map 的 List。
javaName 將資料庫欄位名對映為駝峰風格的 java 變數名。
同理 Generate Dao.groovy
和 Generate Mappings.groovy
都是對 generate(table, dir) 和 generate(out, className, fields)
進行修改就可以。
需要注意的是三個 groovy 檔案中有些屬性需要手動進行修改,如 Generate Mappings.groovy
中的 basePackage,生成 dao 時類的字尾,實體類的位置,或者要繼承的基礎類等,需要按需進行適當修改。
示例程式碼上傳 GitHub,你可以在這裡找到: DuanJiaNing/demos/tree/master/groovy-demo/src/tools