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

yzmm
3354 阅读
6 评论

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

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

连接数据库:

img

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

img

找到IDEA的脚本扩展目录:

img

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

img

Generate Entitys.groovy:

groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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
}

测试代码生成:

img

选择实体层所在的目录:

img

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

img

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

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

评论 (6)

sky

win出现问题还未解决的,请换电脑吧,mac毫无毛病

Hran

非常感谢,很好用~ 在Win上使用有两处需要修改:

  1. getPackageName方法中在dir.toString()后面加上.replaceAll("\\", ".")
  2. 在IDEA安装目录的bin目录下,修改idea[64].exe.vmoptions,添加-Dfile.encoding=utf8就可以解决中文乱码问题了
yzmm

@奶牛君 你用的是Windows?可能是脚本写文件的时候没指定编码或者数据库编码不一致导致的。

奶牛君

请问大牛,生成注释时出现乱码如何解决现将new String(col.getComment().getBytes("UTF-8"), "GBK")处理后仍有部分中文注释出现乱码情况,项目是UTF-8编码的idea设置的默认编码也是utf-8

zll

换连接吗: www.xz-src.com

小哥哥

关注博文已久,不知大牛手上有无web 0day,我愿以惊喜价收入。

发表评论