网上有很多都是通过groovy从数据库表生成实体类,那可不可以通过groovy获取已经存在的实体类信息呢?答案当然是可以的。本文就是说明如何在IDEA的Groovy控制台,根据已有的entity,获取entity的信息,然后根据获取的信息使用freemarker模板进行输出。
对于已经存在的项目
,它的实体类可能不是那么轻易能覆盖的(涉及字段的类型的确定、注解的组合…)。如何快速校验一个字段超多的实体类字段;如何通过已有的实体类生成DTO、BO、VO等等,从已有的实体获取字段信息无疑是完美的解决方案
。
不需要看步骤的直接跳到本文的总结
不需要看步骤的直接跳到本文的总结
不需要看步骤的直接跳到本文的总结
下面将结合mybatis-plus的注解标注的实体类举例,如果是实体类是JPA的注解标注的,只需要将脚本中获取信息的注解换成JPA的注解即可;
已有一个UserInfo的实体类,其实体类代码假设如下:
package com.test.bean;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 用户信息详情
* @author
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("USER_INFO")
@ApiModel(value = "UserInfo 对象", description = "用户信息详情")
public class UserInfo {
@ApiModelProperty(value = "主键ID")
@TableId(value = "ID")
private String id;
/** 用户名 */
@ApiModelProperty(value = "用户名name")
@TableField(value = "USER_NAME")
private String userName;
/** 用户密码 */
@ApiModelProperty(value = "用户密码")
@TableField(value = "USER_PW")
private String userPw;
}
由上可以看到,实体类的其他信息都由 TableName、TableId、TableField、ApiModelProperty等注解标注清楚了,在IDEA的groovy控制台就可以通过注解获取这些值,使用如下脚本获取实体的信息:
打开Groovy控制台
文件groovy_console.groovy内容:
import com.baomidou.mybatisplus.annotation.TableField
import com.baomidou.mybatisplus.annotation.TableId
import com.baomidou.mybatisplus.annotation.TableName
import com.test.bean.UserInfo
import freemarker.template.Configuration
import freemarker.template.Template
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
import org.apache.commons.lang3.StringUtils
import java.lang.annotation.Annotation
// 获取entity
def entity = UserInfo
// 字段信息
class filedInfo {
def String name; // 默认驼峰命名法
def String capitalName; // 首字母大写
def String dbName; // 数据库的名字
def String type; // 类型名称
def String typeFull; // 类型全称
def String comment; // 字段注释
def boolean ifPk = false;
}
def entityInfo = [
dir: System.getProperty("user.dir"), // 获取工程的目录
package : entity.getPackage().name, // 获取包名
name: entity.getSimpleName(), // 获取类名
tableName: "",
tableComment: "",
filesName: entity.getDeclaredFields().name, // 获取所有字段名
pkFiles: [], // 获取id字段
files: [], // 字段
filesAll: [], // 全部字段
]
def model = entity.getAnnotation(ApiModel)
if (model != null) {
entityInfo.tableComment = model.description()
}
def table = entity.getAnnotation(TableName)
if (table != null) {
entityInfo.tableName = table.value()
}
// 填充 files
for(def field in entity.getDeclaredFields()) {
def info = new filedInfo()
info.name = field.name
info.capitalName = StringUtils.upperCase(field.name[0]) + field.name[1..field.name.length()-1]
info.type = field.type.simpleName
info.typeFull = field.type.name
def tableField = field.getAnnotation(TableField)
def tableId = field.getAnnotation(TableId)
if (tableField != null) {
info.dbName = tableField.value()
info.ifPk = false
entityInfo.files.add(info)
} else if (tableId != null) {
info.dbName = tableId.value()
info.ifPk = true
entityInfo.pkFiles.add(info)
} else {
info.dbName = ""
}
def comment = field.getAnnotation(ApiModelProperty)
if (comment != null) {
info.comment = comment.value()
}
entityInfo.filesAll.add(info)
}
println(entityInfo)
控制台输出如下信息
[
dir:D:\work\workspaces\workspace-an\test,
package:com.test.bean,
name:UserInfo,
tableName:USER_INFO,
tableComment:用户信息详情,
filesName:[id, userName, userPw],
pkFiles:[filedInfo@56f0cc85],
files:[filedInfo@62e20a76, filedInfo@2cc44ad],
filesAll:[filedInfo@56f0cc85, filedInfo@62e20a76, filedInfo@2cc44ad]
]
其中id的filedInfo信息如下
name id;
capitalName Id;
dbName ID;
type String;
typeFull java.lang.String;
comment 主键ID;
ifPk true;
其中userName的filedInfo信息如下
name userName;
capitalName UserName;
dbName USER_NAME;
type String;
typeFull java.lang.String;
comment 用户名name;
ifPk false;
还可以使用模板输出信息
//1.创建freeMarker配置实例
Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
//2.设置模板加载器:开始加载模板 scratches 文件夹为IDEA的临时文件夹
cfg.setDirectoryForTemplateLoading(new File("C:\\Users\\admin\\AppData\\Roaming\\JetBrains\\IntelliJIdea2023.2\\scratches"));
//4.获取模板
Template template = cfg.getTemplate("scratch.ftl");
template.process(entityInfo, new PrintWriter(System.out)); //在控制台输出
scratch.ftl 模板
package ${package};
<#list files as f>
name ${f.name}; capitalName ${f.capitalName}; dbName ${f.dbName}; type ${f.type}; typeFull ${f.typeFull}; comment ${f.comment}; ifPk ${f.ifPk?c};
#list>
${dir}
${name}
<#list files as f>
@ApiModelProperty(value = "${f.comment}")
@TableField(value = "${f.dbName}")
private ${f.type} ${f.name};
#list>
package ${package};
@TableName("${tableName}")
@ApiModel(value = "${name}对象", description = "${tableComment}")
public class ${name} {
}
输出信息如下
package com.test.bean;
name userName; capitalName UserName; dbName USER_NAME; type String; typeFull java.lang.String; comment 用户名name; ifPk true;
name userPw; capitalName UserPw; dbName USER_PW; type String; typeFull java.lang.String; comment 用户密码; ifPk true;
D:\work\workspaces\workspace-an\test
UserInfo
@ApiModelProperty(value = "用户名name")
@TableField(value = "USER_NAME")
private String userName;
@ApiModelProperty(value = "用户密码")
@TableField(value = "USER_PW")
private String userPw;
package com.test.bean;
@TableName("USER_INFO")
@ApiModel(value = "UserInfo对象", description = "用户信息详情")
public class UserInfo {
}
完全的脚本,只需要更换entity的变量即可,在下面的注释获取entity处,加载自己的临时文件夹获取自己定义的模板文件。
import com.baomidou.mybatisplus.annotation.TableField
import com.baomidou.mybatisplus.annotation.TableId
import com.baomidou.mybatisplus.annotation.TableName
import com.test.bean.UserInfo
import freemarker.template.Configuration
import freemarker.template.Template
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
import org.apache.commons.lang3.StringUtils
import java.lang.annotation.Annotation
// 获取entity
def entity = UserInfo
// 字段信息
class filedInfo {
def String name; // 默认驼峰命名法
def String capitalName; // 首字母大写
def String dbName; // 数据库的名字
def String type; // 类型名称
def String typeFull; // 类型全称
def String comment; // 字段注释
def boolean ifPk = false;
}
def entityInfo = [
dir: System.getProperty("user.dir"), // 获取工程的目录
package : entity.getPackage().name, // 获取包名
name: entity.getSimpleName(), // 获取类名
tableName: "",
tableComment: "",
filesName: entity.getDeclaredFields().name, // 获取所有字段名
pkFiles: [], // 获取id字段
files: [], // 字段
filesAll: [], // 全部字段
]
def model = entity.getAnnotation(ApiModel)
if (model != null) {
entityInfo.tableComment = model.description()
}
def table = entity.getAnnotation(TableName)
if (table != null) {
entityInfo.tableName = table.value()
}
// 填充 files
for(def field in entity.getDeclaredFields()) {
def info = new filedInfo()
info.name = field.name
info.capitalName = StringUtils.upperCase(field.name[0]) + field.name[1..field.name.length()-1]
info.type = field.type.simpleName
info.typeFull = field.type.name
def tableField = field.getAnnotation(TableField)
def tableId = field.getAnnotation(TableId)
if (tableField != null) {
info.dbName = tableField.value()
info.ifPk = false
entityInfo.files.add(info)
} else if (tableId != null) {
info.dbName = tableId.value()
info.ifPk = true
entityInfo.pkFiles.add(info)
} else {
info.dbName = ""
}
def comment = field.getAnnotation(ApiModelProperty)
if (comment != null) {
info.comment = comment.value()
}
entityInfo.filesAll.add(info)
}
println(entityInfo)
//1.创建freeMarker配置实例
Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
//2.设置模板加载器:开始加载模板
cfg.setDirectoryForTemplateLoading(new File("C:\\Users\\admin\\AppData\\Roaming\\JetBrains\\IntelliJIdea2023.2\\scratches"));
//4.获取模板
Template template = cfg.getTemplate("scratch.ftl");
template.process(entityInfo, new PrintWriter(System.out)); //在控制台输出
可以根据自己需要进行定制
package ${package};
<#list files as f>
name ${f.name}; capitalName ${f.capitalName}; dbName ${f.dbName}; type ${f.type}; typeFull ${f.typeFull}; comment ${f.comment}; ifPk ${f.ifPk?c};
#list>
<#--项目工程的主目录-->
${dir}
${name}
<#--循环非主键字段-->
<#list files as f>
@ApiModelProperty(value = "${f.comment}")
@TableField(value = "${f.dbName}")
private ${f.type} ${f.name};
#list>
package ${package};
@TableName("${tableName}")
@ApiModel(value = "${name}对象", description = "${tableComment}")
public class ${name} {
}
变量 | 名称 | 使用 | 举例 |
---|---|---|---|
dir | 获取工程的目录 | ${dir} | D:\work\workspaces\workspace-an\test |
package | 获取包名 | ${package} | com.test.bean |
name | 类名 | ${name} | UserInfo |
tableName | 表名 | ${tableName} | USER_INFO |
tableComment | 表注释 | ${tableComment} | 用户信息详情 |
filesName | 字段名称 | ${filesName} | [id, userName, userPw] |
pkFiles | 主键字段 | <#list pkFiles as f>#list> | [filedInfo] |
files | 非主键字段 | <#list files as f>#list> | [filedInfo] |
filesAll | 全部字段(主键字段、非主键字段) | <#list filesAll as f>#list> | [filedInfo] |
变量 | 名称 | 使用 | 举例 |
---|---|---|---|
name | 字段名称 | ${f.name} | userName |
capitalName | 首字母大写 | ${f.capitalName} | UserName |
dbName | 数据库字段名 | ${f.dbName} | USER_NAME |
type | 类型名称 | ${f.type} | String |
typeFull | 类型全称 | ${f.typeFull} | java.lang.String |
comment | 字段注释 | ${f.comment} | 用户名name |
ifPk | 是否主键 | ${f.ifPk?c} | true|false |
<#--循环主键字段-->
<#list pkFiles as f>
@ApiModelProperty(value = "${f.comment}")
@TableId(value = "${f.dbName}")
private ${f.type} ${f.name};
#list>
<#--循环非主键字段-->
<#list files as f>
@ApiModelProperty(value = "${f.comment}")
@TableField(value = "${f.dbName}")
private ${f.type} ${f.name};
#list>
<#--类class-->
package ${package};
@TableName("${tableName}")
@ApiModel(value = "${name}对象", description = "${tableComment}")
public class ${name} {
}
<#--getter和setter-->
<#list filesAll as f>
public ${f.type} get${f.capitalName}() {
return ${f.name};
}
public void set${f.capitalName}(${f.type} ${f.name}) {
this.${f.name}= ${f.name};
}
#list>
<#--生成json信息-->
[
<#list files as f>
{
"name": "${f.name}",
"type": "${f.type}",
"comment": "${f.comment}"
},
#list>
]