写项目总是要花很多时间去写实体层,尽管可以直接把变量名一个个拖过去,还是很容易出错,很费神。
这几天发现可以用spring boot生成Entity代码,尝试了一把,发现挺好用的。
后来突发奇想,干脆让它生成所有基础代码算了,说干就干!
先看看生成效果
生成前的项目目录,配置好项目结构,此时不到一千行Java代码
现在进行所有数据表对应代码的一键生成。注意!前方高能!!!!!
两秒钟过后。。。
瞬间生成了七千多行spring boot代码
来看看各层的效果
实体层 生成了各成员变量、swagger注解、toString方法、get和set方法,能够满足所有需要了
动态sql 根据项目的需要,生成了动态插入、多条件查询、部分更新、全部更新四个动态SQL方法语句
数据库接口Dao层、业务Service层 暂时只设置了id查询、动态插入,可以根据自己需要自行修改配置,把有必要的方法自动生成
控制Controller层 完备的swagger api注解
现在运行一下项目
因为自动生成了swagger注释,所以直接可以在swagger看到生成的接口
上面详细介绍了生成的代码,如果跟自己习惯不符,可以根据自己的需要动手定制
现在开始正题,怎么让电脑自己写代码
1.大家可以看到上面的变量和每个实体都有中文注释,这些注释当然不是自动翻译的,是在设计数据库的时候写上去的。
所以要先设计一个符合规范的数据库,注释一定要齐全
还要有对表的注释
我这里每张表加了个前缀,大家如果没有前缀,可以把生成类名时去除前缀的代码去掉
2.用ideal自带的database工具连上数据库,在数据表上点鼠标右键
点Go to Scripts Driectory,进入一个目录,一般大家打开只有最后一个groovy文件,前两个是我自己仿照最后一个写的
.groovy文件就是生成数据库的脚本语言文件
我们先打开自带的Generate POJOs.groovy文件(自己做了些改动,原文件没保留下来,跟大家的又不太一样了)
可以看到语法跟python差不多,又有些地方跟Java很像。
遇到这样陌生的代码,不要怕它,找规律,稍微细心观察一下它的结构,试着去按照自己的想法修改几行看看
用自带的groovy代码生成文件试试,然后改几个参数,看看有什么变化,改多了就会发现,自己好像又学会了一个新的语言,没错,确实是另外一门语言:groovy语言
这里的选项就是脚本文件名了
备注:这里可以选中多张表,同时生成
自动生成以后大概就是这样了,有成员变量和get、set方法,没有注释什么的
3.了解了groovy脚本后,我们来改写适应自己项目所需的groovy脚本,按照上面方法运行就可以了
下面我附上刚才生成代码的完整groovy脚本
注意:运行需谨慎,代码不备份,被删两行泪,是以文件的形式生成,会覆盖同名文件!
package com.example
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 com.intellij.database.model.ObjectKind
/*
* Available context bindings:
* SELECTION Iterable<DasObject>
* PROJECT project
* FILES files helper
*/
// 全局变量,在init()方法中生成(自动生成,无需修改)
fileEncoding = "utf-8"
creatTime = "" //
tableName = "" // 数据表名(Java命名规则)
fields = [[]] // 数据表各列属性
/* 各层类名 在入口方法中设置命名规则 */
entityName = ""
daoName = ""
dynaSqlName = ""
serviceName = ""
controllerName = ""
/* 各层包名 根据设置目录自动生成 */
packageNameEntity = ""
packageNameDao = ""
packageNameDynaSql = ""
packageNameService = ""
packageNameController = ""
// 实体类所在文件夹(手动配置)
dirProject = "P:\\IdeaProjects\\gamaapp_server4" // 项目文件夹
dirEntity = dirProject + "\\src\\main\\java\\com\\example\\demo\\entity" // 实体层文件夹
dirDao = dirProject + "\\src\\main\\java\\com\\example\\demo\\dao" // Dao层文件夹
dirDynaSql = dirProject + "\\src\\main\\java\\com\\example\\demo\\dao\\dynaSql" // 动态Sql文件夹
dirService = dirProject + "\\src\\main\\java\\com\\example\\demo\\service" // Service层文件夹
dirController = dirProject + "\\src\\main\\java\\com\\example\\demo\\controller" // Controller层文件夹
creatTag = "// Auto Created by Zeng" // 自动生产方法注释
// mysql中数据类型和Java数据类型映射
typeMapping = [
(~/(?i)int|tinyint/) : "Integer",
(~/(?i)bigint|timestamp/) : "Long",
(~/(?i)float|double|decimal|real/) : "Double",
(~/(?i)date|datetime|time/) : "Date",
(~/(?i)/) : "String"
]
// 入口函数,选择数据库后进入
SELECTION.filter { it instanceof DasTable }.each {
init(it) // 初始化全局变量数据
// 设置类名规则
entityName = tableName
daoName = tableName + "Dao"
dynaSqlName = tableName + "Sql"
serviceName = tableName + "Service"
controllerName = tableName + "Controller"
/** 把以下不需要生成的注释掉即可 **/
creatEntity(it) // 生成实体类
creatDao(it) // 生成Dao
creatDynaSql(it) // 生成动态Sql
creatService(it) // 生成Service
creatController(it) // 生成Controller
}
// 初始化全局变量
def init(table){
creatTime = new Date().format("yyyy-MM-dd HH:mm:ss")
tableName = javaName(removePrefixName(table.getName()), true)
fields = calcFields(table)
packageNameEntity = getPackageName(dirEntity)
packageNameDao = getPackageName(dirDao)
packageNameDynaSql = getPackageName(dirDynaSql)
packageNameService = getPackageName(dirService)
packageNameController = getPackageName(dirController)
}
// 创建Controller
def creatController(table){
new File(dirController, controllerName + ".java").withPrintWriter(fileEncoding) { out ->
out.println "package ${packageNameController};\n"
out.println "import ${packageNameEntity}.${entityName};"
out.println "import ${packageNameService}.${serviceName};"
out.println "import com.example.demo.utils.Result;"
out.println "import com.example.demo.utils.UserUtils;"
out.println "import io.swagger.annotations.ApiImplicitParam;"
out.println "import io.swagger.annotations.ApiImplicitParams;"
out.println "import io.swagger.annotations.Api;"
out.println "import io.swagger.annotations.ApiOperation;"
out.println "import org.springframework.beans.factory.annotation.Autowired;"
out.println "import org.springframework.web.bind.annotation.*;"
out.println "\n\n// Created on ${creatTime}\n"
out.println "@Api(tags = \"${isNotEmpty(table.getComment())?table.getComment():controllerName}\")"
out.println "@CrossOrigin"
out.println "@RestController"
out.println "@RequestMapping(\"/${javaName(tableName,false)}/\")"
out.println "public class ${controllerName} {\n"
out.println " @Autowired"
out.println " ${serviceName} ${javaName(serviceName,false)};\n\n"
out.println " ${creatTag}"
out.println " @ApiOperation(value = \"selectById\",httpMethod = \"GET\",notes = \"Auto Creat\")"
out.println " @ApiImplicitParams({"
out.println " @ApiImplicitParam(name = \"id\",value = \"${javaName(tableName,false)}Id\",required = true ,dataType=\"int\")"
out.println " })"
out.println " @GetMapping(\"selectById\")"
out.println " public Result selectById(Integer id){"
out.println " if(id == null){"
out.println " return Result.error(\"Not required id!\");"
out.println " }else {"
out.println " return Result.ok(${javaName(serviceName,false)}.selectById(id));"
out.println " }"
out.println " }"
out.println "\n ${creatTag}"
out.println " @ApiOperation(value = \"insert\",httpMethod = \"POST\",notes = \"Auto Creat\")"
out.println " @ApiImplicitParams({"
fields.each() { // 不插入主键
if(!it.isAutoGenerated){
out.println " @ApiImplicitParam(name = \"${it.name}\",value = \"${isNotEmpty(it.commoent)?it.commoent:""}\"${it.isNotNull?",required = true":""}),"
}
}
out.println " })"
out.println " @PostMapping(\"insert\")"
out.println " public Result insert(${entityName} ${javaName(entityName,false)}){"
out.println " int num = ${javaName(serviceName,false)}.insert(${javaName(entityName,false)});"
out.println " if(num == 1){"
out.println " return Result.ok(\"Successful!\",\"\");"
out.println " }else {"
out.println " return Result.error(\"Failure!\",\"\");"
out.println " }"
out.println " }"
out.println "\n\n\n}"
}
}
// 创建Service
def creatService(table){
new File(dirService, serviceName + ".java").withPrintWriter(fileEncoding) { out ->
out.println "package ${packageNameService};\n"
out.println "import ${packageNameDao}.${daoName};"
out.println "import ${packageNameEntity}.${entityName};"
out.println "import org.springframework.beans.factory.annotation.Autowired;"
out.println "import org.springframework.stereotype.Service;"
out.println "\n\n// Created on ${creatTime}\n"
out.println "@Service"
out.println "public class ${serviceName} {\n"
out.println " @Autowired"
out.println " $daoName ${javaName(daoName,false)};\n\n"
out.println " ${creatTag}"
out.println " public $entityName selectById(Integer id){"
out.println " return ${javaName(daoName,false)}.selectById(id);"
out.println " }"
out.println "\n ${creatTag}"
out.println " public int insert(${entityName} ${javaName(entityName,false)}){"
out.println " return ${javaName(daoName,false)}.insert(${javaName(entityName,false)});"
out.println " }"
out.println "\n\n\n}"
}
}
// 创建动态sql
def creatDynaSql(table){
new File(dirDynaSql, dynaSqlName + ".java").withPrintWriter(fileEncoding) { out ->
out.println "package ${packageNameDynaSql};\n"
out.println "import ${packageNameEntity}.${entityName};"
out.println "import org.apache.ibatis.jdbc.SQL;"
out.println "\n\n// Created on ${creatTime}\n"
out.println "public class $dynaSqlName {\n"
// 插入数据库动态sql
out.println " ${creatTag}"
out.println " public String insert(${entityName} ${javaName(entityName,false)}){"
out.println " return new SQL(){"
out.println " {"
out.println " INSERT_INTO(\"${table.getName()}\");"
fields.each() { // 非空变量
if(!it.isAutoGenerated && it.isNotNull && !it.zerofill){
out.println " VALUES(\"${it.colName}\",\"#{${it.name}}\");"
}
}
fields.each() { // 可以为空的变量
if(!it.isNotNull || it.zerofill){
out.println " if(${javaName(entityName,false)}.get${it.name.capitalize()}() != null){"
out.println " VALUES(\"${it.colName}\",\"#{${it.name}}\");"
out.println " }"
}
}
out.println " }"
out.println " }.toString();"
out.println " }\n"
// 多条件查询动态sql
out.println " ${creatTag}"
out.println " public String selectByMutiParams${tableName}(${entityName} ${javaName(entityName,false)}){"
out.println " return new SQL(){"
out.println " {"
out.println " SELECT(\"*\");"
out.println " FROM(\"${table.getName()}\");"
fields.each() { // 查询条件
out.println " if(${javaName(entityName,false)}.get${it.name.capitalize()}() != null){"
out.println " WHERE(\"${it.colName} = #{${it.name}}\");"
out.println " }"
}
out.println " }"
out.println " }.toString();"
out.println " }\n"
// 部分更新动态sql
out.println " ${creatTag}"
out.println " public String updatePart${tableName}(${entityName} ${javaName(entityName,false)}){"
out.println " return new SQL(){"
out.println " {"
out.println " UPDATE(\"${table.getName()}\");"
fields.each() {
if(!it.isAutoGenerated){
out.println " if(${javaName(entityName,false)}.get${it.name.capitalize()}() != null){"
out.println " SET(\"${it.colName} = #{${it.name}}\");"
out.println " }"
}
}
out.println " WHERE(\"id = #{id}\");"
out.println " }"
out.println " }.toString();"
out.println " }\n"
// 全部更新动态sql
out.println " ${creatTag}"
out.println " public String updateALL${tableName}(${entityName} ${javaName(entityName,false)}){"
out.println " return new SQL(){"
out.println " {"
out.println " UPDATE(\"${table.getName()}\");"
fields.each() {
if(!it.isAutoGenerated){
out.println " if(${javaName(entityName,false)}.get${it.name.capitalize()}() != null){"
out.println " SET(\"${it.colName} = #{${it.name}}\");"
out.print " }"
if(!it.isNotNull){
out.println "else {"
out.println " SET(\"${it.colName} = null\");"
out.print " }"
}
out.println ""
}
}
out.println " WHERE(\"id = #{id}\");"
out.println " }"
out.println " }.toString();"
out.println " }\n"
out.println "}"
}
}
// 创建Dao
def creatDao(table){
new File(dirDao, daoName + ".java").withPrintWriter(fileEncoding) { out ->
out.println "package ${packageNameDao};\n"
out.println "import ${packageNameEntity}.${entityName};"
out.println "import ${packageNameDynaSql}.${dynaSqlName};"
out.println "import org.apache.ibatis.annotations.InsertProvider;"
out.println "import org.apache.ibatis.annotations.Mapper;"
out.println "import org.apache.ibatis.annotations.Select;"
out.println "import org.springframework.stereotype.Repository;"
out.println "\n\n// Created on ${creatTime}\n"
out.println "@Mapper"
out.println "@Repository"
out.println "public interface ${daoName} {\n\n"
out.println " ${creatTag}"
out.println " @Select(\"SELECT * FROM ${table.getName()} WHERE id=#{id}\")"
out.println " ${entityName} selectById(Integer id);"
out.println "\n ${creatTag}"
out.println " @InsertProvider(type = ${dynaSqlName}.class,method = \"insert\")"
out.println " int insert(${entityName} ${javaName(entityName,false)});"
out.println "\n\n\n}"
}
}
// 创建实体类
def creatEntity(table){
new File(dirEntity, entityName + ".java").withPrintWriter(fileEncoding) { out ->
def fields = calcFields(table)
out.println "package ${packageNameEntity};\n"
out.println "import java.util.Date;"
out.println "import io.swagger.annotations.ApiModel;"
out.println "import io.swagger.annotations.ApiModelProperty;"
out.println "\n\n// Created on ${creatTime}\n"
out.println "@ApiModel(\"${isNotEmpty(table.getComment())?table.getComment():tableName}\")"
out.println "public class ${entityName} {\n"
// 输出成员变量
fields.each() {
// 输出注释
if(isNotEmpty(it.commoent)){
out.println " @ApiModelProperty(value = \"${it.commoent}\")"
}
// 输出成员变量
if (it.annos != "") out.println " ${it.annos}"
out.println " private ${it.type} ${it.name};"
}
// 输出toString
out.println "\n @Override"
out.println " public String toString() {"
out.println " final StringBuilder sb = new StringBuilder(\"{\");"
fields.each() {
out.println " sb.append(\"\\\"${it.name}\\\":\")"
out.println " .append(${it.name});"
}
out.println " return sb.toString();"
out.println " }\n"
// 输出get、set方法
fields.each() {
out.println " public ${it.type} get${it.name.capitalize()}() {"
out.println " return ${it.name};"
out.println " }\n"
out.println " public void set${it.name.capitalize()}(${it.type} ${it.name}) {"
out.println " this.${it.name} = ${it.name};"
out.println " }"
}
out.println "\n\n}"
}
}
// 获取数据表所有列属性,装入数组中
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), // 转化后的变量名
colType : col.getDataType(), // 数据库数据类型
type : typeStr, // Java数据类型
commoent: col.getComment(), // 备注
isPrimary : DasUtil.isPrimary(col), // 是否主键
isForeign : DasUtil.isForeign(col), // 是否外键
isAutoGenerated : DasUtil.isAutoGenerated(col), // 是否自增
unsigned : col.getDataType().getSpecification().indexOf("unsigned") != -1?true:false, // 无符号
zerofill : col.getDataType().getSpecification().indexOf("zerofill") != -1?true:false, // 零填充
isNotNull : col.isNotNull(), // 非空
annos: ""]]
}
}
// 获取包所在文件夹路径
def getPackageName(dir) {
return dir.toString().replaceAll("\\\\", ".").replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "")
}
// 转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]
}
// 判断字符串是否为空
def isNotEmpty(content){
return content != null && content.trim().length() > 0
}
// 去除数据库前缀后的类名
def removePrefixName(str){
return str.substring(str.indexOf("_")+1)
}
新建一个groovy文件,把代码复制进去修改参数后即可运行自动生成代码
注意:以上代码生成后不会提示完成,刷新一下项目目录即可看见生成文件
关于groovy基础语法可参见 https://www.jianshu.com/p/8127742e0569