2017-04-08 16:18:15

IDEA 由数据库表生成带注释的java实体类代码

Java生成实体类代码有非常多的方案,而且强大的可以生成整个项目的解决方案,不过这里只是讨论实体类的生成。IDEA提供了类似的实体类生成脚本,用起来比较方便简捷。不过需要用IDEA支持的jvm脚本语言开发(默认示例是Clojure、Groovy)。

但是自带的脚本简单到生成的代码都没法用(有bug),所以花了点时间完善了下脚本实现代码,这里简单介绍下如何使用我们的脚本去生成java实体类代码。

连接数据库:

配置数据库连接信息,如果没有下载过jdbc的jar,这里需要点击download


找到IDEA的脚本扩展目录:


在这个脚本目录下新建Generate Entitys.groovy并复制如下代码



Generate Entitys.groovy:

import com.intellij.database.model.DasTable
import com.intellij.database.model.ObjectKind
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil

/*
 * 默认可用的 context 绑定:
 *   SELECTION   Iterable*   PROJECT     project
 *   FILES       files helper
 */

packageName = ""
typeMapping = [
        (~/(?i)tinyint|smallint|mediumint/)      : "Integer",
        (~/(?i)int/)                             : "Long",
        (~/(?i)bool|bit/)                        : "Boolean",
        (~/(?i)float|double|decimal|real/)       : "Double",
        (~/(?i)datetime|timestamp|date|time/)    : "Date",
        (~/(?i)blob|binary|bfile|clob|raw|image/): "InputStream",
        (~/(?i)/)                                : "String"
]

FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->
    SELECTION.filter { it instanceof DasTable && it.getKind() == ObjectKind.TABLE }.each { generate(it, dir) }
}

def generate(table, dir) {
    def className = javaName(table.getName(), true)
    def fields = calcFields(table)
    packageName = getPackageName(dir)
    new File(dir, className + ".java").withPrintWriter { out -> generate(out, className, fields) }
}

/**
 * 获取包名称
 * @param dir 实体类所在目录
 * @return
 */
def getPackageName(dir) {
    return dir.toString().replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "") + ";"
}

/**
 * 实体类代码生成
 * @param out
 * @param className
 * @param fields
 * @return
 */
def generate(out, className, fields) {
    out.println "package $packageName"
    out.println ""

    Settypes = new HashSet()

    fields.each() {
        types.add(it.type)
    }

    if (types.contains("Date")) {
        out.println "import java.util.Date;"
    }

    if (types.contains("InputStream")) {
        out.println "import java.io.InputStream;"
    }

    out.println ""
    out.println "public class $className {"
    fields.each() {
        out.println ""
        if (it.annos != "") out.println "  ${it.annos}"

        // 输出注释
        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * ${it.commoent}"
            out.println "\t */"
        }

        // 输出成员变量
        out.println "\tprivate ${it.type} ${it.name};"
    }

    // 输出get/set方法
    fields.each() {
        out.println ""

        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * 获取${it.commoent}"
            out.println "\t */"
        }

        def actionName = "Boolean".equals(it.type.toString()) ? "is" : "get"

        out.println "\tpublic ${it.type} ${actionName}${it.name.capitalize()}() {"
        out.println "\t\treturn this.${it.name};"
        out.println "\t}"
        out.println ""

        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * 设置${it.commoent}"
            out.println "\t */"
        }
        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 ""
    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 += [[
                           colName : col.getName(),
                           name    : javaName(col.getName(), false),
                           type    : typeStr,
                           commoent: col.getComment(),
                           annos   : ""]]
    }
}

def javaName(str, capitalize) {
    def s = str.split(/[^\p{Alnum}]/).collect { def s = Case.LOWER.apply(it).capitalize() }.join("")
    capitalize ? s : Case.LOWER.apply(s[0]) + s[1..-1]
}

def isNotEmpty(content) {
    return content != null && content.toString().trim().length() > 0
}


测试代码生成:


选择实体层所在的目录:


最终生成的代码效果如图:


生成注释的前提是数据库字段已设置注释信息(comment),否则无法生成。由于脚本写的比较简单,所以支持的数据类型有限。如代码中的typeMapping可自行添加。对于boolean类型的数据类型支持不够友好因为每个数据库的实现差异比较大,不过bool之类的可以直接翻译。

插件代码下载地址: Generate Entitys.groovy


发表回复