IDEA通过Groovy逆向生成java代码

idea自带groovy插件,可以通过groovy逆向生成java代码,优点是可以灵活配置,根据自己需求生成的模板,使用方法如下

第一步:IDEA配置数据库

        配置方法这里不讲,配置结果如图

 第二步:编写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 com.intellij.psi.codeStyle.NameUtil

import java.io.*
import java.text.SimpleDateFormat

// 注释中作者
userName = "Li Chengjin"
// 表名如果以t_开头或者其他前缀,需要处理掉是改为true
isRemoveTableNamePrefix = false 
// 默认包名
entityPackageName = "entity"
mapperPackageName = "mapper"
servicePackageName = "service"
serviceImplPackageName = "impl"

baseDirName =""
basePackageName = ""
baseClassName = ""
entityClassNamePO = ""
entityClassNameVO = ""
serviceClassName = ""
serviceImplClassName = ""
mapperClassName = ""
currentTime= new SimpleDateFormat("yyyy-MM-dd").format(new Date())

// 映射数据库字段
typeMapping = [
        (~/(?i)int|tinyint|smallint|mediumint/)  : "Integer",
        (~/(?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"
]

// 选择框获取数据库表及java文件夹
FILES.chooseDirectoryAndSave("Choose directory", "Choose where to save the generate files !!!") {
    dir ->
        SELECTION
            .filter { it instanceof DasTable && it.getKind() == ObjectKind.TABLE}
            .each {
                basePackageName = getPackageName(dir)
                baseClassName = changeStrToCamelCase(it.getName(), true)
                baseDirName = dir.toString()
                // 生成实体类
                generateEntityPO(it)
                // 生成mapper
                generateMapper()
                // 生产mapper.xml
                generateMapperXML()
                // 生成service
                generateService()
                // 生成service实现类
                generateServiceImpl()
            }
}

// 生成Entity实体文件
def generateEntityPO(table) {
    def fields = calcFields(table)
    entityClassNamePO = "${baseClassName}PO"
    entityClassNameVO = "${baseClassName}VO"
    // 先创建文件夹
    def entityDir = "${baseDirName}/${entityPackageName}"
    def dirFile = new File(entityDir)
    if (!dirFile.exists()) {
        dirFile.mkdirs()
    }
    def filePO = new File(entityDir, "${entityClassNamePO}.java")
    // 输出实体
    new PrintWriter(new OutputStreamWriter(new FileOutputStream(filePO), "UTF-8"))
            .withPrintWriter {
                out -> generateEntityPOContent(out, fields, table)
            }
    def fileVO = new File(entityDir, "${entityClassNameVO}.java")
    // 输出实体
    new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileVO), "UTF-8"))
            .withPrintWriter {
                out -> generateEntityVOContent(out, fields, table)
            }
}

// 生成实体类内容
def generateEntityPOContent(out, fields, table) {
    out.println "package ${basePackageName}.${entityPackageName};"
    out.println ""
    out.println "import com.baomidou.mybatisplus.annotation.IdType;"
    out.println "import com.baomidou.mybatisplus.annotation.TableId;"
    out.println "import com.baomidou.mybatisplus.annotation.TableField;"
    out.println "import com.baomidou.mybatisplus.annotation.TableName;"
    out.println "import java.io.Serializable;"
    out.println "import lombok.Data;"

    Set types = 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 "/**\n" +
            " * @Description  \n" +
            " * @author ${userName}\n" +
            " * @Date ${currentTime}\n" +
            " */"
    out.println "@Data"
    out.println "@TableName(value =\"${table.getName()}\")"
    out.println "public class ${entityClassNamePO} implements Serializable {"
    out.println genSerialID()
    fields.each() {
        out.println ""
        // 输出注释
        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * ${it.commoent.toString()}"
            out.println "\t */"
        }
        // 输出注解
        if ((it.annos + "").indexOf("[@Id]") >= 0) out.println "\t@TableId(type = IdType.AUTO)"
        if (it.annos != "") out.println " ${it.annos.replace("[@Id]", "")}"
        // 输出成员变量
        out.println "\tprivate ${it.type} ${it.name};"
    }
    out.println ""
    out.println "}"
}

// 生成实体类内容
def generateEntityVOContent(out, fields, table) {
    out.println "package ${basePackageName}.${entityPackageName};"
    out.println ""
    out.println "import lombok.Data;"

    Set types = 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 "/**\n" +
            " * @Description  \n" +
            " * @author ${userName}\n" +
            " * @Date ${currentTime}\n" +
            " */"
    out.println "@Data"
    out.println "public class ${entityClassNameVO} {"
    fields.each() {
        out.println ""
        // 输出注释
        if (isNotEmpty(it.commoent)) {
            out.println "\t/**"
            out.println "\t * ${it.commoent.toString()}"
            out.println "\t */"
        }
        // 输出成员变量
        out.println "\tprivate ${it.type} ${it.name};"
    }
    out.println ""
    out.println "}"
}

// 生成Mapper文件
def generateMapper() {
    mapperClassName = "${baseClassName}Mapper"
    // 先创建文件夹
    def mapperDir = "${baseDirName}/${mapperPackageName}"
    def dirFile = new File(mapperDir)
    if (!dirFile.exists()) {
        dirFile.mkdirs()
    }
    def file = new File(mapperDir, "${mapperClassName}.java")
    // 输出mapper
    new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"))
            .withPrintWriter {
                out -> generateMapperContent(out)
            }
}

// 生成Mapper内容
def generateMapperContent(out) {

    out.println "package ${basePackageName}.${mapperPackageName};"
    out.println ""
    out.println "import org.apache.ibatis.annotations.Mapper;"
    out.println "import com.baomidou.mybatisplus.core.mapper.BaseMapper;"
    out.println "import ${basePackageName}.${entityPackageName}.${entityClassNamePO};"
    out.println ""
    out.println "/**\n" +
            " * @Description  \n" +
            " * @author ${userName}\n" +
            " * @Date ${currentTime}\n" +
            " */"
    out.println "@Mapper"
    out.println "public interface ${mapperClassName} extends BaseMapper<${entityClassNamePO}> {\n" + "}"
}
// 生成mapper.xml
def generateMapperXML(){
    def mapperDir = "${baseDirName}/${mapperPackageName}"
    def dirFile = new File(mapperDir)
    if (!dirFile.exists()) {
        dirFile.mkdirs()
    }
    def file = new File(mapperDir, "${mapperClassName}.xml")
    new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"))
            .withPrintWriter {
                out -> generateMapperXmlContent(out)
            }
}
// 生成mapper.xml内容
def generateMapperXmlContent(out) {
    out.println('<?xml version="1.0" encoding="UTF-8"?>');
    out.println('<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">')
    out.println("<mapper namespace=\"${basePackageName}.${mapperPackageName}.${mapperClassName}\">")
    out.println('')
    out.println('</mapper>')
}

// 生成 Service 文件
def generateService() {
    serviceClassName = "${baseClassName}Service"
    // 先创建文件夹
    def serviceDir = "${baseDirName}/${servicePackageName}"
    def dirFile = new File(serviceDir)
    if (!dirFile.exists()) {
        dirFile.mkdirs()
    }
    def file = new File(serviceDir, "${serviceClassName}.java")
    PrintWriter printWriterMapper = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"))
    printWriterMapper.withPrintWriter { out -> generateServiceContent(out) }
}

// Service 文件具体生成逻辑
def generateServiceContent(out) {
    out.println "package ${basePackageName}.${servicePackageName};"
    out.println ""
    out.println "import com.baomidou.mybatisplus.extension.service.IService;"
    out.println "import ${basePackageName}.entity.${entityClassNamePO};"
    out.println ""
    out.println "/**\n" +
            " * @Description  \n" +
            " * @author ${userName}\n" +
            " * @Date ${currentTime}\n" +
            " */"
    out.println "public interface ${serviceClassName} extends IService<${entityClassNamePO}> {\n}"
}

// 生成 ServiceImpl 文件
def generateServiceImpl() {
   serviceImplClassName = "${baseClassName}ServiceImpl"
    // 先创建文件夹
    def serviceImplDir = "${baseDirName}/${servicePackageName}/${serviceImplPackageName}"
    def dirFile = new File(serviceImplDir)
    if (!dirFile.exists()) {
        dirFile.mkdirs()
    }
    def file = new File(serviceImplDir, "${serviceImplClassName}.java")

    new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"))
            .withPrintWriter {
                out -> generateServiceImplContent(out)
            }
}

// ServiceImpl 文件具体生成逻辑
def generateServiceImplContent(out) {

    out.println "package ${basePackageName}.${servicePackageName}.${serviceImplPackageName};"
    out.println ""
    out.println "import lombok.extern.slf4j.Slf4j;"
    out.println "import org.springframework.stereotype.Service;"
    out.println "import org.springframework.transaction.annotation.Transactional;"
    out.println "import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;"
    out.println "import ${basePackageName}.${mapperPackageName}.${mapperClassName};"
    out.println "import ${basePackageName}.${servicePackageName}.${serviceClassName};"
    out.println "import ${basePackageName}.${entityPackageName}.${entityClassNamePO};"
    out.println ""
    out.println "/**\n" +
            " * @Description  \n" +
            " * @Author ${userName}\n" +
            " * @Date ${currentTime} \n" +
            " */"
    out.println "@Slf4j"
    out.println "@Service"
    out.println "@Transactional(rollbackFor = Exception.class)"
    out.println "public class ${serviceImplClassName} extends ServiceImpl<${mapperClassName},${entityClassNamePO}> implements ${serviceClassName} {\n}"
}
// 获取包所在文件夹路径
def getPackageName(dir) {
    return dir.toString().replaceAll("\\\\", ".").replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "")
}
// 读取表
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
        def comm = [
                colName : col.getName(),
                name    : changeStrToCamelCase(col.getName(), false),
                type    : typeStr,
                commoent: col.getComment(),
                annos   : "\t@TableField(value = \"" + col.getName() + "\")"]
        if ("id".equals(Case.LOWER.apply(col.getName())))
            comm.annos += ["@Id"]
        fields += [comm]
    }
}
// 改变变量名风格,将变量或表名改为驼峰
def changeStrToCamelCase(String str, isCapitalize) {
    def s = NameUtil.splitNameIntoWords(str)
            .collect { Case.LOWER.apply(it).capitalize() }
            .join("")
            .replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")
    s = isRemoveTableNamePrefix ? s[1..s.size() - 1] : s
    isCapitalize || s.length() == 1 ? s : Case.LOWER.apply(s[0]) + s[1..-1]
}

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

static String genSerialID() {
    return "\tprivate static final long serialVersionUID =  " + Math.abs(new Random().nextLong()) + "L;"
}

 第三步:放置脚本

        这一步主要是方便后续选择,也可以放在电脑固定的文件夹中,脚本放置位置如图

 第四步:使用脚本

        在需要逆向的表中右键点击,如图选择到刚才编写的脚本

        点击后弹出选择框,这一步是选择生产文件的位置,选中文件后会在指定位置生成mapper,entity和service

         通知提示生成成功

第五步:检查

        代码逆向生成成功

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IntelliJ IDEA 中,你可以使用 Live Template 功能来快速生成单元测试代码。具体实现过程如下: 1. 打开 IntelliJ IDEA,进入 Settings -> Editor -> Live Templates 页面,点击 “+” 按钮,新建一个 Live Template。 2. 在 Abbreviation 栏中输入一个简短的缩写,例如 “test”,在 Template Text 栏中输入以下代码: ```groovy @Test void test$testName$() { $END$ } ``` 其中,`$testName$` 是一个变量,在使用 Live Template 时会被替换成用户输入的测试方法名。 3. 在 Applicable In 栏中,勾选 Java,并在下方的 Expression 栏中输入以下代码: ```groovy groovyScript("_editor.selectionStart != _editor.selectionEnd", "java.lang.Boolean") ``` 这段代码的作用是检查当前光标所在的位置是否有选中文本,如果有则只在选中的文本中生成测试代码,否则在光标所在行生成代码。 4. 点击 OK 按钮保存 Live Template。 5. 在 Java代码中输入缩写 “test”,然后按下 Tab 键,即可生成单元测试代码。在输入方法名时,可以通过 Tab 键切换到下一个变量位置,便于快速输入。 例如,在下面的代码中输入 “test” 并按下 Tab 键,即可生成一个名为 “testAddition()” 的测试方法: ```java public class Calculator { public int add(int a, int b) { return a + b; } } ``` 生成的测试代码如下: ```java @Test void testAddition() { // TODO: test goes here } ``` 6. 在生成的测试方法中,补充需要测试的代码,并运行测试,即可得到测试结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值