生成MyBatisPlus实体
在I DEA 编辑器,双击 shift 键在 Generate POJOs.groovy
文件,同级目录下新建一个文件MyBatisPlus pojo.groovy
,将下面的代码粘贴进去即可,有问题可以自己改,在IDEA自带数据库工具的数据库表上右键执行
import com.intellij.database.model.DasTable
import com.intellij.database.model.ObjectKind
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
/*
* Available context bindings:
* SELECTION Iterable<DasObject>
* PROJECT project
* FILES files helper
*/
packageName = "com.monkeyhi.xxx"
// 此处指定对应的类型映射,可按需修改,目前tinyint如果要映射到自定义枚举类型,只能手动修改
typeMapping = [
(~/(?i)tinyint|smallint|mediumint/) : "Integer",
(~/(?i)bool|bit/) : "Boole",
(~/(?i)int/) : "Integer",
(~/(?i)float|double|decimal|real|number/): "BigDecimal",
(~/(?i)datetime|timestamp/) : "LocalDateTime",
(~/(?i)date/) : "LocalDate",
(~/(?i)time/) : "LocalDateTime",
(~/(?i)blob|mediumblob|binary|bfile|clob|raw|image/): "Byte[]",
(~/(?i)text|mediumtext/) : "String",
(~/(?i)/) : "String",
]
// 上面用到类和它的导入路径的之间的映射
importMap = [
"BigDecimal" : "java.math.BigDecimal",
"LocalDate" : "java.time.LocalDate",
"LocalDateTime": "java.time.LocalDateTime",
]
// 导入路径列表,下面引用的时候会去重,也可以直接声明成一个 HashSet
importList = []
// 弹出选择文件的对话框
FILES.chooseDirectoryAndSave("选择文件夹", "选择存储位置") { 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 PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(dir, className + ".java")), "utf-8")).withPrintWriter { out -> generate(out, className, fields, table) }
}
def calcFields(table) {
def pkSet = new HashSet<String>()
def prKey = DasUtil.getPrimaryKey(table);
if (prKey != null) {
def keyRef = prKey.getColumnsRef();
if (keyRef != null) {
def it = keyRef.iterate();
while (it.hasNext()) {
pkSet.add(it.next())
}
}
}
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
if (importMap.containsKey(typeStr)) {
importList.add(importMap.get(typeStr))
}
fields += [[
colName : col.getName(),
name : javaName(col.getName(), false),
type : typeStr,
comment: col.getComment(),
isKey: pkSet.contains(col.getName()),//判读字段是否是主健
annos : ""
]]
}
}
def isNotEmpty(content) {
return content != null && content.toString().trim().length() > 0
}
// 获取包所在文件夹路径
def getPackageName(dir) {
return dir.toString().replaceAll("\\\\", ".").replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "")
}
def javaName(str, capitalize) {
def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
.collect { Case.LOWER.apply(it).capitalize() }
.join("")
.replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")
capitalize || s.length() == 1 ? s : Case.LOWER.apply(s[0]) + s[1..-1]
}
static String genSerialID() {
return " private static final long serialVersionUID = " + Math.abs(new Random().nextLong()) + "L;"
}
// 从这里开始,拼实体类的具体逻辑代码
def generate(out, className, fields, table) {
out.println """
package ${packageName};
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
${importList.unique().collect { "import " + it + ";" }.join("\n")}
/**
* ${table.getComment()?:""}
*
* @author monkeyhi
* @since ${LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))}
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("${table.getName()}")
public class $className implements Serializable {
${genSerialID()}
${fields.collect {"""
/**
* ${it.comment?:''}
*/
${it.isKey ? "@TableId(value = \"${it.colName}\", type = IdType.AUTO)" :
"@TableField(\"${it.colName}\")"}
@ApiModelProperty(\"${it.comment?:''}\")
private ${it.type} ${it.name};
""" }.join("")}
}
"""
}
生成的实体如下:
package com.xxx..entity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
/**
* 请求-单位关联表
*
* @author monkeyhi
* @since 2025-07-01 15:26
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tab_xxx_ddd")
public class TabXxxDdd implements Serializable {
private static final long serialVersionUID = 615020304229774329L;
/**
* 主键
*/
@TableId(value = "ID", type = IdType.AUTO)
@ApiModelProperty("主键")
private String id;
/**
* 请求id
*/
@TableField("QQ_ID")
@ApiModelProperty("请求id")
private String qqId;
/**
* 单位id
*/
@TableField("DW_ID")
@ApiModelProperty("单位id")
private String dwId;
}
生成表结构JSON
也有可以生成json,然后自己可以用 javaScript 在浏览器控制台输出相关功能代码,,同上新建一个文件 Generate tableJson.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
import java.time.LocalDate
/*
* Available context bindings:
* SELECTION Iterable<DasObject>
* PROJECT project
* FILES files helper
*/
// 此处指定对应的类型映射,可按需修改,目前tinyint如果要映射到自定义枚举类型,只能手动修改
typeMapping = [
(~/(?i)tinyint|smallint|mediumint/) : "Integer",
(~/(?i)bool|bit/) : "Boole",
(~/(?i)int/) : "Integer",
(~/(?i)float|double|decimal|real|number/): "BigDecimal",
(~/(?i)datetime|timestamp/) : "LocalDateTime",
(~/(?i)date/) : "LocalDate",
(~/(?i)time/) : "LocalDateTime",
(~/(?i)blob|mediumblob|binary|bfile|clob|raw|image/): "Byte[]",
(~/(?i)text|mediumtext/) : "String",
(~/(?i)/) : "String",
]
// 上面用到类和它的导入路径的之间的映射
importMap = [
"BigDecimal" : "java.math.BigDecimal",
"LocalDate" : "java.time.LocalDate",
"LocalDateTime": "java.time.LocalDateTime",
]
// 导入路径列表,下面引用的时候会去重,也可以直接声明成一个 HashSet
importList = []
// 弹出选择文件的对话框
FILES.chooseDirectoryAndSave("选择文件夹", "选择存储位置") { 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 entityInfo = [
dir: dir, // 获取工程的目录
package : getPackageName(dir), // 获取包名
name: className, // 获取类名
tableName: table.getName(),
tableComment: table.getComment()?:"",
fieldName: [], // 获取所有字段名
pkField: [], // 获取id字段
field: [], // 字段
fieldAll: [], // 全部字段
]
// 填充field
calcFields(table, entityInfo)
new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(dir, className + ".json")), "utf-8")).withPrintWriter { out -> generate(out, entityInfo, table) }
}
def calcFields(table, entityInfo) {
def pkSet = new HashSet<String>()
def prKey = DasUtil.getPrimaryKey(table);
if (prKey != null) {
def keyRef = prKey.getColumnsRef();
if (keyRef != null) {
def it = keyRef.iterate();
while (it.hasNext()) {
pkSet.add(it.next())
}
}
}
entityInfo.fieldAll = 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
def typeStrFull = "java.lang" + "." + typeStr
if (importMap.containsKey(typeStr)) {
def matchType = importMap.get(typeStr)
importList.add(matchType)
// 有映射关系,使用映射关系
typeStrFull = matchType
}
def ifPk = pkSet.contains(col.getName())
// def ifPk = DasUtil.isPrimary(col)
fields += [[
name : javaName(col.getName(), false), // 默认驼峰命名法
capitalName: javaName(col.getName(), true), // 首字母大写
dbName : col.getName(), // 数据库的名字
type : typeStr, // 类型名称
typeFull : typeStrFull, // 类型全称
comment : col.getComment() ?: "", // 字段注释
ifPk : ifPk
]]
}
// 填充pk
entityInfo.pkField = entityInfo.fieldAll.findAll { it -> it.ifPk}
// 填充filed
entityInfo.field = entityInfo.fieldAll.findAll { it -> !it.ifPk}
// 填充fieldName
entityInfo.fieldName = entityInfo.fieldAll.collect { it.name }
}
def isNotEmpty(content) {
return content != null && content.toString().trim().length() > 0
}
def javaName(str, capitalize) {
def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
.collect { Case.LOWER.apply(it).capitalize() }
.join("")
.replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")
capitalize || s.length() == 1 ? s : Case.LOWER.apply(s[0]) + s[1..-1]
}
// 获取包所在文件夹路径
def getPackageName(dir) {
return dir.toString().replaceAll("\\\\", ".").replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "") + ";"
}
// 从这里开始,拼实的具体逻辑代码
def generate(out, entityInfo, table) {
out.print """
{
"dir": "${entityInfo.dir}",
"package" : "${entityInfo.package}",
"name": "${entityInfo.name}",
"tableName": "${entityInfo.tableName}",
"tableComment": "${entityInfo.tableComment}",
"fieldName": [
${entityInfo.fieldName.collect { '"' + it + '"' }.join(", ")}
],
"pkField": [${entityInfo.pkField.collect {"""
{
"name": "${it.name}",
"capitalName": "${it.capitalName}",
"dbName": "${it.dbName}",
"type": "${it.type}",
"typeFull": "${it.typeFull}",
"comment": "${it.comment}",
"ifPk": ${it.ifPk}
}"""}.join(",")}
],
"field": [${entityInfo.field.collect {"""
{
"name": "${it.name}",
"capitalName": "${it.capitalName}",
"dbName": "${it.dbName}",
"type": "${it.type}",
"typeFull": "${it.typeFull}",
"comment": "${it.comment}",
"ifPk": ${it.ifPk}
}"""}.join(",")}
],
"fieldAll": [${entityInfo.fieldAll.collect {"""
{
"name": "${it.name}",
"capitalName": "${it.capitalName}",
"dbName": "${it.dbName}",
"type": "${it.type}",
"typeFull": "${it.typeFull}",
"comment": "${it.comment}",
"ifPk": ${it.ifPk}
}"""}.join(",")}
]
}
"""
}
生成的 JSON 格式如下
{
"dir": "/Users/monkeyhi/work/workspace/test-server/src/main/java/com/xxx/entity",
"package" : "com.xxx.entity;",
"name": "TabXxxDdd",
"tableName": "tab_xxx_ddd",
"tableComment": "请求-单位关联表",
"fieldName": [
"id", "qqId", "dwId"
],
"pkField": [
{
"name": "id",
"capitalName": "Id",
"dbName": "ID",
"type": "String",
"typeFull": "java.lang.String",
"comment": "主键",
"ifPk": true
}
],
"field": [
{
"name": "qqId",
"capitalName": "QqId",
"dbName": "QQ_ID",
"type": "String",
"typeFull": "java.lang.String",
"comment": "请求id",
"ifPk": false
},
{
"name": "dwId",
"capitalName": "DwId",
"dbName": "DW_ID",
"type": "String",
"typeFull": "java.lang.String",
"comment": "单位id",
"ifPk": false
}
],
"fieldAll": [
{
"name": "id",
"capitalName": "Id",
"dbName": "ID",
"type": "String",
"typeFull": "java.lang.String",
"comment": "主键",
"ifPk": true
},
{
"name": "qqId",
"capitalName": "QqId",
"dbName": "QQ_ID",
"type": "String",
"typeFull": "java.lang.String",
"comment": "请求id",
"ifPk": false
},
{
"name": "dwId",
"capitalName": "DwId",
"dbName": "DW_ID",
"type": "String",
"typeFull": "java.lang.String",
"comment": "单位id",
"ifPk": false
}
]
}
常用的一些函数收集
参数是table的
table.getName() // 表名称
table.getComment() // 表注释
table:属性 name、comment
获取列
JBIterable<? extends DasColumn> = DasUtil.getColumns(table)
JBIterable<? extends DasForeignKey> = DasUtil.getForeignKeys(table)
JBIterable<? extends DasIndex> = DasUtil.getIndices(table)
JBIterable<? extends DasTableKey> = DasUtil.getTableKeys(table)
DasTableKey = DasUtil.getPrimaryKey(table)
所有的key都可以获取列 JBIterable<? extends DasColumn> = key.getColumnsRef()
比如获取主键的所有列:
===
def pkSet = new HashSet<String>()
def prKey = DasUtil.getPrimaryKey(table);
if (prKey != null) {
def keyRef = prKey.getColumnsRef();
def it = keyRef.iterate();
while (it.hasNext()) {
pkSet.add(it.next())
}
}
===
列可以获取到表
table = column.getTable()
判断列的属性
column:{name,comment,dataType:{size,scale,sizeUnit,jdbcType:未来将会被移除,vagueArg,suffix,schemaName,packageName,typeName}}
DasUtil.isPrimary(column)
DasUtil.isForeign(column)
DasUtil.isAuto(column)
DasUtil.isAutoGenerated(column)
DasUtil.isComputed(column)
DasUtil.hasAttribute(column, DasColumn.Attribute.PRIMARY_KEY)
dataType = column.getDataType()
dataType.getSpecification() = dataType.toString() = 'varchar(30)'
dataType.getLength() = dataType.getPrecision() = dataType.size = 30
dataType.getScale() = dataType.scale = 0
dataType.jdbcType = 12 = org.apache.ibatis.type.JdbcType.forCode(12) = org.apache.ibatis.type.JdbcType.VARCHAR
常量
DasColumn.Attribute 的枚举值 DasColumn.Attribute.PRIMARY_KEY 其key还可以取如下值:PRIMARY_KEY, CANDIDATE_KEY, FOREIGN_KEY, INDEX, AUTO_GENERATED, COMPUTED, VERSION