前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Java|在 IDEA 里自动生成 MyBatis 模板代码

Java|在 IDEA 里自动生成 MyBatis 模板代码

作者头像
mzlogin
发布于 2024-09-25 01:48:51
发布于 2024-09-25 01:48:51
26401
代码可运行
举报
文章被收录于专栏:闷骚的程序员闷骚的程序员
运行总次数:1
代码可运行

背景

基于 MyBatis 开发的项目,新增数据库表以后,总是需要编写对应的 Entity、Mapper 和 Service 等等 Class 的代码,这些都是重复的工作,我们可以想一些办法来自动生成这些代码。

方案

一种可选的方案是使用 MyBatis Generator,官方支持,常见需求一般也都能满足。但是它的配置文件比较繁琐,如果有一些项目相关的个性化需求,不一定很好处理。

这里介绍另外一种我觉得更为简便灵活的方法。

近几年版本的 IDEA 里已经自带了 Database Tools and SQL 插件,可以连接数据库进行常用的操作,并且,它还自带了数据库表对应 POJO 类的代码生成器:在 Database 面板里配置好数据源以后,右键表名,依次选择 Scripted Extensions、Generate POJOs.groovy,选择生成路径后,即可生成对应的 Entity 类。

既然能够生成 Entity,那么我们可以基于它进行修改,让它一次性生成我们需要的 Entity、Mapper 和 Service。

需求

基于项目情况,我们对生成的代码有如下要求:

  1. Entity 需要继承指定基类,数据库表的公共字段放在基类里;
  2. Mapper、Service 和 ServiceImpl 分别需要实现指定的类继承关系;
  3. Entity、Mapper 和 Service 需要自动放在对应的子包下。

以 t_promotion_channel 表为例,指定该表和对应的代码目录之后,生成的目录结构如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.
├── entity
│   └── PromotionChannel.java
├── mapper
│   └── PromotionChannelMapper.java
└── service
    ├── PromotionChannelService.java
    └── impl
        └── PromotionChannelServiceImpl.java

需要生成的代码如下:

entity/PromotionChannel.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.test.data.promotion.entity;

import com.test.common.base.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.Table;

/**
 * @author mazhuang
 */
@EqualsAndHashCode(callSuper = true)
@Data
@Table(name = "t_promotion_channel")
public class PromotionChannel extends BaseEntity {

    private static final long serialVersionUID = 5495175453870776988L;
    /**
     * 用户ID
    */
    private Long fkUserId;

    /**
     * 渠道名称
    */
    private String channelName;

}

mapper/PromotionChannelMapper.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.test.data.promotion.mapper;

import com.test.common.base.BaseMapper;
import com.test.data.promotion.entity.PromotionChannel;

/**
 * @author mazhuang
 */
public interface PromotionChannelMapper extends BaseMapper<PromotionChannel> {

}

service/PromotionChannelService.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.test.data.promotion.service;

import com.test.common.base.BaseService;
import com.test.data.promotion.entity.PromotionChannel;

/**
 * @author mazhuang
 */
public interface PromotionChannelService extends BaseService<PromotionChannel> {

}

service/impl/PromotionChannelServiceImpl.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.test.data.promotion.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.test.common.base.BaseServiceImpl;
import com.test.data.promotion.entity.PromotionChannel;
import com.test.data.promotion.mapper.PromotionChannelMapper;
import com.test.data.promotion.service.PromotionChannelService;

/**
 * @author mazhuang
 */
@Slf4j
@Service
public class PromotionChannelServiceImpl extends BaseServiceImpl<PromotionChannelMapper, PromotionChannel> implements PromotionChannelService {

}

实现

右键一个数据库表,依次选择 Scripted Extensions、Go to Scripts Directory,进入生成的脚本目录,找到 Generate POJOs.groovy,复制一份,重命名为 Generate MyBatis Code.groovy,然后修改内容如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import com.intellij.database.model.DasTable
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil

/*
 * Available context bindings:
 *   SELECTION   Iterable<DasObject>
 *   PROJECT     project
 *   FILES       files helper
 */

typeMapping = [
        (~/(?i)int/)                      : "Long",
        (~/(?i)float|double|decimal|real/): "BigDecimal",
        (~/(?i)datetime|timestamp/)       : "java.util.Date",
        (~/(?i)date/)                     : "java.sql.Date",
        (~/(?i)time/)                     : "java.sql.Time",
        (~/(?i)/)                         : "String"
]

FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->
    SELECTION.filter { it instanceof DasTable }.each { generate(it, dir) }
}

def generate(table, dir) {
    def className = javaName(table.getName().replaceFirst('t_', ''), true)
    def fields = calcFields(table)

    dirPath = dir.getAbsolutePath()
    packageName = calcPackageName(dirPath)

    // Generate POJO
    new File(dirPath + File.separator + "entity", className + ".java").withPrintWriter("utf-8") { out -> generateEntity(out, table.getName(), className, fields, packageName) }

    // Generate Mapper
    new File(dirPath + File.separator + "mapper", className + "Mapper.java").withPrintWriter("utf-8") { out -> generateMapper(out, className, packageName) }

    // Generate Service
    new File(dirPath + File.separator + "service", className + "Service.java").withPrintWriter("utf-8") { out -> generateService(out, className, packageName) }

    // Generate ServiceImpl
    new File(dirPath + File.separator + "service" + File.separator + "impl", className + "ServiceImpl.java").withPrintWriter("utf-8") { out -> generateServiceImpl(out, className, packageName) }
}

static def generateEntity(out, tableName, className, fields, packageName) {
    out.println "package $packageName" + ".entity;"
    out.println ""
    out.println "import com.test.common.base.BaseEntity;"
    out.println "import lombok.Data;"
    out.println "import lombok.EqualsAndHashCode;"
    out.println "import javax.persistence.Table;"
    out.println ""
    out.println "/**\n * @author mazhuang\n */"
    out.println "@EqualsAndHashCode(callSuper = true)"
    out.println "@Data"
    out.println "@Table(name = \"$tableName\")"
    out.println "public class $className extends BaseEntity {"
    out.println ""

    def baseEntityFields = ['pkid', 'addedBy', 'addedTime', 'lastModifiedBy', 'lastModifiedTime', 'valid']
    fields.each() {
        if (baseEntityFields.contains(it.name)) {
            return
        }
        if (it.annos != "") out.println "  ${it.annos}"
        if (it.comment != null) out.println "    /**\n     * ${it.comment}\n    */"
        out.println "    private ${it.type} ${it.name};\n"
    }

    out.println "}"
}

static def generateMapper(out, className, packageName) {
    out.println "package $packageName" + ".mapper;"
    out.println ""

    out.println "import com.test.common.base.BaseMapper;"
    out.println "import $packageName" + ".entity.$className;"
    out.println ""

    out.println "/**\n * @author mazhuang\n */"
    out.println "public interface $className" + "Mapper extends BaseMapper<$className> {"
    out.println ""
    out.println "}"
}

static def generateService(out, className, packageName) {
    out.println "package $packageName" + ".service;"
    out.println ""

    out.println "import com.test.common.base.BaseService;"
    out.println "import $packageName" + ".entity.$className;"
    out.println ""

    out.println "/**\n * @author mazhuang\n */"
    out.println "public interface $className" + "Service extends BaseService<$className> {"
    out.println ""
    out.println "}"
}

static def generateServiceImpl(out, className, packageName) {
    out.println "package $packageName" + ".service.impl;"
    out.println ""

    out.println "import lombok.extern.slf4j.Slf4j;"
    out.println "import org.springframework.stereotype.Service;"
    out.println "import com.test.common.base.BaseServiceImpl;"
    out.println "import $packageName" + ".entity.$className;"
    out.println "import $packageName" + ".mapper.$className" + "Mapper;"
    out.println "import $packageName" + ".service.$className" + "Service;"
    out.println ""

    out.println "/**\n * @author mazhuang\n */"
    out.println "@Slf4j"
    out.println "@Service"
    out.println "public class $className" + "ServiceImpl extends BaseServiceImpl<$className" + "Mapper, $className> implements $className" + "Service {"
    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 += [[
                               name   : javaName(col.getName(), false),
                               type   : typeStr,
                               comment: col.getComment(), // 注释
                               default: col.getDefault(), // 默认值
                               annos  : ""]]

    }
}

static def calcPackageName(dirPath) {
    def startPos = dirPath.indexOf('com')
    return dirPath.substring(startPos).replaceAll(File.separator, ".")
}

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]
}

大功告成,现在右键一个数据库表,依次选择 Scripted Extensions、Generate MyBatis Code.groovy,在弹出的目录选择框里选择想要放置代码的目录,即可生成期望的模板代码了。

后续如果有一些个性化的代码生成需求,可以根据实际情况修改、新增脚本来完成。

其它

本文代码生成器脚本已上传至 GitHub,仓库地址:https://github.com/mzlogin/code-generator,以后如果有更新,或者新的代码生成脚本,也会放在这个仓库里。

文档信息

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024/09/24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
IDEA + Groovy脚本一键生成实体类,用法舒服,高效!
idea 功能很强大,以前不知道有这样的提升工作效率的方法,虽然有的工具确实可以直接生成实体类,mapper文件,还有dao接口,但是个人觉得涉及到复杂业务还是只生成实体类比较好,后面部分就自己搞定就可以了。
好好学java
2020/12/21
7270
IDEA + Groovy脚本一键生成实体类,用法舒服,高效!
SpringBoot中的自动代码生成 - 基于Mybatis-Plus
大家好啊,我是汤圆,今天给大家带来的是《SpringBoot中的自动代码生成 - 基于Mybatis-Plus》,希望对大家有帮助,谢谢
汤圆学Java
2021/04/22
1.1K0
刚入职没多久,连夜手写了一个代码生成器,项目开发速度瞬间屌炸了!
最近刚入职一个新团队,还没来得及熟悉业务,甲方爸爸就要求项目要在2个月内完成开发并上线!
Java极客技术
2022/12/04
5040
刚入职没多久,连夜手写了一个代码生成器,项目开发速度瞬间屌炸了!
TKmybatis的框架介绍及使用方法
最近项目使用了SpringBoot+TKMytis框架,期间遇到一些问题,顺便记一下。
全栈程序员站长
2022/07/21
1.1K0
Java|让 JUnit4 测试类自动注入 logger 和被测 Service
本文介绍如何通过自定义 IDEA 的 JUnit4 Test Class 模板,实现生成测试类时自动注入 logger 和被测 Service。
mzlogin
2024/09/26
1650
Java|让 JUnit4 测试类自动注入 logger 和被测 Service
IDEA连接数据库生成对应实体类(有字段注释)
添加模板 import com.intellij.database.model.DasTable import com.intellij.database.util.Case import com.i
须臾之余
2019/12/16
2K0
IDEA连接数据库生成对应实体类(有字段注释)
JUnit4 测试类自动注入 logger 和被测 Service 的方法
在 IntelliJ IDEA 中,通过快捷键可以快速生成 JUnit4 测试类,但是生成测试类以后,总是需要手动添加 logger 和被测 Service 的注入。虽然这是一个很小的「重复动作」,但程序员还是不能忍(其实已经忍了很多年了)。
Power
2025/04/02
780
代码生成器初体验
修改数据库的连接信息,由于目前使用的MySQL8.0版本,所以只修改了MySQL的相关信息,可以根据自己需要修改相关数据库的连接信息。
猫老师的叶同学
2023/03/01
1.3K0
代码生成器初体验
代码演示Mybatis-Generator 扩展自定义生成
Mybatis-Generator 可自动生成Model、Dao、Mapper代码,但其自带生成的代码存在以下问题:
宜信技术学院
2020/03/06
1.9K0
搭建单体SpringBoot项目 集成MybatisPlus代码生成
郭顺发
2023/07/17
3260
jeesite快速开发平台(七)—-代码生成原理
jeesite代码生成用的是FreeMarker模板引擎结合xml技术来实现的,定义的模板都放在resources/templates/modules/gen下
全栈程序员站长
2021/06/21
9600
jeesite快速开发平台(七)—-代码生成原理
由需求而产生的一款db导出excel的工具
程序员最大的毛病可能就是懒,因为懒所以做出了许许多多提高自己工作效率的工具. 起因于我是商业开发,既然是商业项目避免不了各种数据统计,虽然公司有专门的数据平台,但是应对一些临时性需求还是免不了开发人员去导出一些数据.每一次有需求来我都是写一个复杂的sql,然后放到DataGrip中执行,利用其功能导出cvs,然而越来越多的需求该功能无法满足,比如导出组合表,也就是一个excel中有多个sheet表.那么应该这个需求我写了一个为自己的工具.
屈定
2018/09/27
5940
(三)Mybatis-Plus代码生成器
上一篇我们已经把所有需要的东西配置好了,接下来我们准备连接数据库生成代码。 首先准备一张student表: SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for student -- ---------------------------- DROP TABLE IF EXISTS `student`; CREATE TABLE `student`
Java那些事儿
2020/07/21
6040
(三)Mybatis-Plus代码生成器
velocity笔记(一)什么是velocity,我们什么时候会使用到这个,基本语法,利用模板生成实体类的各层代码
也就是前端程序员写velocity模板,后端程序员写数据模型,最后整合就是展示给用户的东西
一写代码就开心
2022/05/09
1.1K0
velocity笔记(一)什么是velocity,我们什么时候会使用到这个,基本语法,利用模板生成实体类的各层代码
Mybatis系列之全局扫描ant通配符格式的包名
业务场景:首先项目进行分布式拆分之后,按照模块再分为为api层和service层,web层。 其中订单业务的实体类放在com.muses.taoshop.item.entity,而用户相关的实体类放在com.muses.taoshop.user.entity。所以就这样,通过通配符方式去setTypeAliasesPackage ,com.muses.taoshop.*.entity
SmileNicky
2022/05/07
4920
一键生成前后端代码,Mybatis-Plus代码生成器让我舒服了
在日常的软件开发中,程序员往往需要花费大量的时间写CRUD,不仅枯燥效率低,而且每个人的代码风格不统一。MyBatis-Plus 代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块及前端页面的代码,极大的提升了开发效率。
不会飞的小鸟
2020/07/31
4.3K0
IDEA 不愧为神器,结合 Groovy 脚本,简直无敌!
(1),如果只是创建简单的, 只有属性, getter, setter 的实体类, 而不需要 JPA/Hibernate 的实体类注解。
江南一点雨
2020/07/07
2.7K0
IDEA 不愧为神器,结合 Groovy 脚本,简直无敌!
MyBatis-flex自动生成代码类
4xx.me
2023/08/24
8490
MyBatis-flex自动生成代码类
SpringBoot快速整合通用Mapper
后端业务开发,每个表都要用到单表的增删改查等通用方法,而配置了通用Mapper可以极大的方便使用Mybatis单表的增删改查操作。
用户10384376
2023/02/26
4670
SpringBoot快速整合通用Mapper
JPA自动生成POJO
程序员朱永胜
2023/08/21
1930
JPA自动生成POJO
推荐阅读
相关推荐
IDEA + Groovy脚本一键生成实体类,用法舒服,高效!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档