自动产生fsm代码的工具_代码自动生成工具

构建支持多种数据库类型的代码自动生成工具

背景:

一般的业务代码中写来写去,无外乎是先建好model,然后针对这个model做些CRUD的操作。(主要针对单表的业务操作)针对于数据库dao、mapper等的代码自动生成已经有了mybatisGenerator这种工具,但是针对于controller、service这些我们现在的接口api一般遵循的是restful风格,因此这些也是有规则可循的。举例有个goodsInfo 的model,针对于他的操作,肯定有 单个查询、list查询、修改、删除等。而这些代码没必要复制粘贴来一遍,完全可以由工具自动生成,若有特殊业务场景重写即可。本工具就算解决这类问题的。

效果截图

运行生成示例结果:

98e8964590f70a792af8e908e5c0f12c.png

a6b2c1ae9c6846b39f171cd41fa273a1.png

表选择界面:

9f219321d2f61012bafe6e66b9374060.png

思路:

代码自动生成说起来很神秘,其实无外乎两个方面:

从数据库拿到需要自动生成的代码对应表。

从表结构、字段名生成对应的mapper、model、及controller、service等

如何拿到需要自动生成的代码对应表

sqlservr、mysql、oracle等这些主流数据库中都存在系统表结构的表,存储的是所有用户自己建立表的名称、字段等,所以直接查询这些系统表即可罗列出所有业务表。然后做个可视化界面供用户选择即可。(这里做一下更新,我实际项目中没有用sql查询的方式,因为不同数据库对于系统表的存储方式各不相同,查询语句写的太蛋疼了,实际采用的是 conn.getMetaData() 的方式,采用元数据来拿到指定数据库中各种表结构信息)

如何自动生成代码

有了表结构、字段名等如何自动生成代码呢,这个时候就需要模板引擎了。简单来讲可以理解为把固定的地方写死,变化的地方按照规则替换。

可以用我们小时候写作文的例子来说明。我们(作文厉害的请自动忽略 “们” 😃)小时候写作文,一般是3段式,开头、结尾、和中间流水账。 开头一般是描写环境心情、中间讲述具体故事,结尾总结赞美。

今天天气不错,风和日丽的,我们早早就来到了学些,大家都很开心。(开头)

小明,突然在地上捡到了一个钱包……(一顿思想斗争,最后交给了警察叔叔)

最后,这个故事告诉了我们……(结尾)

从上面的示例范文中是不是很熟悉,。基本上都是这个结构,中间基本可以随意替换,最后都能凑成一篇基本合格的小学作文。而我们现在要做的就是把一些表名称、字段名称当做需要填充的内容填充到指定的代码段中去。

具体实现

获取数据库表、字段等信息

好了,上面讲了一大堆废话(背景和思路,个人觉得还是有必要的),下面到具体实现中来。

获取数据库表结构(表、字段)信息关键代码如下

@Service

public class DbServiceImpl implements IDbService {

private Logger logger = LoggerFactory.getLogger(this.getClass());

@Value("${spring.datasource.driverClassName}")

private String driverClassName;

@Value("${spring.datasource.url}")

private String url;

@Value("${spring.datasource.username}")

private String user;

@Value("${spring.datasource.password}")

private String pwd;

@Override

public List getTables(String tableName) {

List tables = new ArrayList<>();

try {

Class.forName(driverClassName);// 动态加载mysql驱动

Connection connection = DriverManager.getConnection(url, user, pwd);

DatabaseMetaData metaData = connection.getMetaData();

ResultSet resultSet = metaData.getTables(null, null, "%", new String[]{"TABLE"});

// metaData.getTables("yjc", "", "%", new String[]{"TABLE"})

while (resultSet.next()) {

if (resultSet.getString("TABLE_NAME").contains(tableName)) {

TableEntity tmpTable = new TableEntity();

tmpTable.setTbName(resultSet.getString("TABLE_NAME"));

tmpTable.setComments(resultSet.getString("REMARKS"));

tmpTable.setCatalog(resultSet.getString("TABLE_CAT"));

tmpTable.setSchema(resultSet.getString("TABLE_SCHEM"));

tables.add(tmpTable);

}

}

} catch (Exception e) {

logger.error("获取数据库表列表失败", e);

}

return tables;

}

@Override

public List getColumns(String tableName) {

List columnEntityList = new ArrayList<>();

try {

Class.forName(driverClassName);// 动态加载mysql驱动

Connection connection = DriverManager.getConnection(url, user, pwd);

DatabaseMetaData metaData = connection.getMetaData();

ResultSet resultSet = metaData.getColumns(null, null, tableName, "%");

while (resultSet.next()) {

ColumnEntity tmpColumnEntity = new ColumnEntity();

tmpColumnEntity.setColumnName(resultSet.getString("COLUMN_NAME"));

tmpColumnEntity.setBufferLength(resultSet.getInt("BUFFER_LENGTH"));

tmpColumnEntity.setColumnSize(resultSet.getInt("COLUMN_SIZE"));

tmpColumnEntity.setComments(resultSet.getString("REMARKS"));

tmpColumnEntity.setDecimalDigits(resultSet.getInt("DECIMAL_DIGITS"));

tmpColumnEntity.setDataType(resultSet.getInt("DATA_TYPE"));

tmpColumnEntity.setTypeName(resultSet.getString("TYPE_NAME"));

tmpColumnEntity.setIsNullAble(resultSet.getString("IS_NULLABLE"));

tmpColumnEntity.setIsAutoIncrement(resultSet.getString("IS_AUTOINCREMENT"));

columnEntityList.add(tmpColumnEntity);

}

} catch (Exception e) {

logger.error("查询表的列发生异常", e);

}

return columnEntityList;

}

@Override

public TableEntity getTableEntity(String tableName) {

TableEntity tableEntity = new TableEntity();

try {

Class.forName(driverClassName);// 动态加载mysql驱动

Connection connection = DriverManager.getConnection(url, user, pwd);

DatabaseMetaData metaData = connection.getMetaData();

ResultSet resultSet = metaData.getTables(null, null, tableName, new String[]{"TABLE"});

while (resultSet.next()) {

if(tableName.equals(resultSet.getString("TABLE_NAME")))

{

tableEntity.setTbName(resultSet.getString("TABLE_NAME"));

tableEntity.setComments(resultSet.getString("REMARKS"));

tableEntity.setCatalog(resultSet.getString("TABLE_CAT"));

tableEntity.setSchema(resultSet.getString("TABLE_SCHEM"));

tableEntity.setPk(this.getPrimaryKeyColumnName(metaData,tableEntity.getCatalog(),tableEntity.getSchema(),tableEntity.getTbName()));

}

}

} catch (Exception e) {

logger.error("获取表对象失败", e);

}

return tableEntity;

}

private String getPrimaryKeyColumnName(DatabaseMetaData metaData,String catalog,String schema,String tableName)

{

String primaryKeyColumnName="";

try {

ResultSet resultSet = metaData.getPrimaryKeys(catalog, schema, tableName);

while (resultSet.next())

{

primaryKeyColumnName= resultSet.getString("COLUMN_NAME");

}

} catch (SQLException e) {

logger.error("获取主键发生异常",e);

}

return primaryKeyColumnName;

}

}

另外在使用 DatabaseMetaData获取表、列信息的时候,如

DatabaseMetaData metaData = connection.getMetaData();

ResultSet resultSet = metaData.getColumns(null, null, tableName, "%");

DatabaseMetaData metaData = connection.getMetaData();

ResultSet resultSet = metaData.getTables(null, null, "%", new String[]{"TABLE"});

获取表格信息、获取列信息都是返回的 ResultSet,这个ResultSet 有点蛋疼,需要按照字段来查询,或者指定索引顺序来获取想要的结果,对照关系如下面截图

b810f49bb0a647e945883d107d5b9108.png

eefa00d8d6a83b95a0c80c195cab00a8.png

使用模板生成代码

使用的是velocity引擎(当然也可以使用freemarker等,这个不重要)

模板代码示例如下:

package ${package}.${moduleName}.entity;

import com.baomidou.mybatisplus.annotations.TableId;

import com.baomidou.mybatisplus.annotations.TableName;

#if(${hasBigDecimal})

import java.math.BigDecimal;

#end

import java.io.Serializable;

import java.util.Date;

/**

* ${comments}

*

* @author ${author}

* @email ${email}

* @date ${datetime}

*/

@TableName("${tableName}")

public class ${className}Entity implements Serializable {

private static final long serialVersionUID = 1L;

#foreach ($column in $columns)

/**

* $column.comments

*/

#if($column.columnName == $pk.columnName)

@TableId

#end

private $column.attrType $column.attrname;

#end

#foreach ($column in $columns)

/**

* 设置:${column.comments}

*/

public void set${column.attrName}($column.attrType $column.attrname) {

this.$column.attrname = $column.attrname;

}

/**

* 获取:${column.comments}

*/

public $column.attrType get${column.attrName}() {

return $column.attrname;

}

#end

}

package ${package}.${moduleName}.controller;

import java.util.Arrays;

import java.util.Map;

import org.apache.shiro.authz.annotation.RequiresPermissions;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.http.ResponseEntity;

import org.springframework.web.bind.annotation.*;

import ${package}.${moduleName}.entity.${className}Entity;

import ${package}.${moduleName}.service.${className}Service;

import ${mainPath}.common.utils.PageUtils;

import ${mainPath}.common.utils.R;

/**

* ${comments}

*

* @author ${author}

* @email ${email}

* @date ${datetime}

*/

@RestController

@RequestMapping("${moduleName}/${pathName}")

public class ${className}Controller {

@Autowired

private ${className}Service ${classname}Service;

/**

* 列表

*/

@GetMapping("/list")

public ResponseEntity>> list(@PageableDefault(value = 15, sort = { "${pk}" }, direction = Sort.Direction.DESC) Pageable pageable)

{

BaseResponse > baseResponse=new BaseResponse<>();

Page all = ${classname}Repository.findAll(pageable)};

if(all!=null && !all.isEmpty())

{

return new ResponseEntity>>(BaseResponseFactory.success(all),HttpStatus.OK);

}

else

{

return new ResponseEntity<>(HttpStatus.BAD_REQUEST);

}

}

/**

* 单个查询

*/

@GetMapping("/{${pk}}")

@ApiOperation(value = "/{${pk}}", httpMethod = "GET", notes = "查询单个${className}信息}")

public ResponseEntity> info(@PathVariable long ${pk}) {

Optional optional = ${classname}Repository.findById(${pk});

if(optional.isPresent())

{

return new ResponseEntity<>(BaseResponseFactory.success(optional.get()), HttpStatus.OK);

}else

{

return new ResponseEntity(HttpStatus.NOT_FOUND);

}

}

/**

* 保存

*/

@PostMapping("/add")

public ResponseEntity> save(@Validated @RequestBody ${className} goodsInfo, BindingResult bindingResult)

{

ResponseEntity> responseEntity;

BaseResponse baseResponse=new BaseResponse<>();

if(bindingResult.hasErrors())

{

StringBuilder sb=new StringBuilder();

for (FieldError fieldError : bindingResult.getFieldErrors()) {

sb.append(fieldError.getDefaultMessage());

sb.append(" ");

}

baseResponse.setCode(400);

baseResponse.setMessage(sb.toString());

responseEntity=new ResponseEntity<>(baseResponse,HttpStatus.BAD_REQUEST);

}

else

{

${className} save = ${classname}Repository.save(${classname});

baseResponse.setCode(200);

baseResponse.setMessage("保存成功");

baseResponse.setData(save);

responseEntity=new ResponseEntity<>(baseResponse, HttpStatus.OK);

}

return responseEntity;

}

}

字段对应转换

如何将数据库的字段类型对应到java代码上,比如数据库中的varchar,需要对应到java的String,本例是参考了一个自动生成工具的方式,使用了对应配置表,内容如下。

#代码生成器,配置信息

mainPath=com.

#包名

package=redheart

moduleName=erp

#作者

author=pf

#Email

email=103868365@qq.com

#表前缀(类名不会包含表前缀)

tablePrefix=yjc_

#类型转换,配置信息

TINYINT=Integer

SMALLINT=Integer

MEDIUMINT=Integer

INT=Integer

INTEGER=Integer

BIGINT=Long

FLOAT=Float

DOUBLE=Double

DECIMAL=BigDecimal

BIT=Boolea

CHAR=String

VARCHAR=String

TINYTEXT=String

TEXT=String

MEDIUMTEXT=String

LONGTEXT=String

DATE=Date

DATETIME=Date

TIMESTAMP=Date

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/427313.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gtest测试框架使用详解_测试框架TestNG使用介绍

近期接触到了一个比较全面的基于Java的接口自动化测试框架&#xff0c;作为一名Java小白&#xff0c;所以打算研究一下&#xff0c;顺带学习学习Java&#xff0c;该测试框架的逻辑控制层使用的HttpClient TestNG。在本期中&#xff0c;给大家分享一下TestNG测试框架的基础知识…

LOJ#6282. 数列分块入门 6

一个动态的插入过程&#xff0c;还需要带有查询操作。 我可以把区间先分块&#xff0c;然后每个块块用vector来维护它的插入和查询操作&#xff0c;但是如果我现在这个块里的vector太大了&#xff0c;我可能的操作会变的太大&#xff0c;所以这时候我需要把现在里面的数全部拿出…

fragment在activity中的静态和动态用法_使用Matlab修改压缩Gif动态图片制作微信表情...

脚本之家你与百万开发者在一起作者&#xff1a;theOwlAndPussyCat/焦旭光引言电脑里存了很多有意思的Gif动态图片&#xff0c;闲暇想把这些动图全导入微信表情&#xff0c;可是这些动图很多大小超过了微信表情大小1MB的限制&#xff0c;要制作成表情只能压缩图像文件大小。网上…

frontcon函数用不了_C++复制构造函数与析构函数

想用机器人赋能未来&#xff0c;少不了扎实的编程的基本功&#xff0c;让我们跟着清华大学的C语言程序设计课程一起过一遍C的语法知识吧&#xff01;当定义基本类型的变量时&#xff0c;经常会用已有的变量去初始化新定义的变量&#xff0c;当定义对象的时候也有类似的需求&…

软件项目立项书_2019年度上海市软件和集成电路产业发展专项资金项目立项

上海艾瑞德生物科技有限公司荣获2019年上海市软件和集成电路产业发展专项资金(集成电路和电子信息制造领域)项目立项&#xff01;上海艾瑞德生物科技有限公司的【医用体外诊断动态光场图像采集电子模块的研发及产业化】喜获2019年上海市软件和集成电路产业发展专项资金(集成电路…

mysql提供了表示日期和时间的数据类型_MySQL数据类型 - 日期和时间类型(1)

1.日期和时间数据类型语法用于表示时间值的日期和时间数据类型是DATE, TIME, DATETIME, TIMESTAMP和 YEAR。对于TIME, DATETIME和 TIMESTAMP值&#xff0c;MySQL支持小数秒&#xff0c;精度可达微秒(6位数)。要定义包含小数秒部分的列&#xff0c;请使用语法type_name(fsp)&…

软件质量保证计划_CMMI V2.0 精讲之“过程质量保证”

过程质量保证(PROCESS QUALITY ASSURANCE, PQA)目的&#xff1a;验证并改进已执行的过程和所产生的工作产品的质量。价值&#xff1a;增强过程使用和改进的一致性&#xff0c;以最大限度地提高业务效益和客户满意度。实践概述第1级PQA 1.1识别并解决过程和工作产品问题。第2级P…

mysql gzip_在mysql中存储GZIP:ed文本?

Is it a common thing for bigger applications and databases to GZIP text data before inserting it to the database?Ill guess that any full-text search on the actual text field will not be working before unzipping it again?解决方案Ive not seen this done muc…

html 分页_JQuery堪称完美的分页函数

演示效果&#xff1a;html部分&#xff08;引入jquery.js&#xff09;<!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>jQuery简单的分页插件</title> </head><link rel"stylesheet" href"…

mysql 8.0.12解压版安装教程_mysql 8.0.12 解压版安装教程

本文为大家分享了mysql 8.0.12 解压版安装教程&#xff0c;供大家参考&#xff0c;具体内容如下1、首先在官网上下载mysql8.0.12的压缩包&#xff1a;下载地址2、下载成功后解压到任意目录&#xff0c;比如我的是E:\download\mysql-8.0.12-winx64&#xff1b;3、配置环境变量&a…

简洁又快速地处理集合——Java8 Stream(下)

上一篇文章我讲解 Stream 流的基本原理&#xff0c;以及它与集合的区别关系&#xff0c;讲了那么多抽象的&#xff0c;本篇文章我们开始实战&#xff0c;讲解流的各个方法以及各种操作 没有看过上篇文章的可以先点击进去学习一下 简洁又快速地处理集合——Java8 Stream&#xf…

python入口函数的作用_python之函数中参数的作用域

学编程究竟学的是什么呢&#xff1f;在写文章的这几天也一直在思考这个问题——恐怕这也是接下来的几年一直会去思考的问题。这个问题的答案也会指导我的方法论&#xff0c;所以索性整顿一下。 现阶段我的回答是&#xff0c;发现需求&#xff0c;然后解决。 最大的需求无非是完…

idea lombok 离线安装_Lombok与IntelliJ IDEA干了一架,完胜

我相信前段时间&#xff0c;有更新IDEA到2020.2版本的同学&#xff0c;在安装Lombok的过程中&#xff0c;肯定遇到与Lombok无法兼容的问题&#xff0c;并且报错&#xff1a;Caused by: com.intellij.psi.PsiInvalidElementAccessException: Element: class de.plushnikov.intel…

jquery设置宽_JavaScript学习笔记(三十二) jQuery(中)

jQuery昨天讲了 jQuery 的基本选择器筛选器和属性操作今天来说一些 jQuery 别的东西元素操作创建一个元素var div $()内部插入元素// 向 div 元素中插入一个 p 元素&#xff0c;放在最后$(div).append($())// 把 p 元素插入到 div 中去&#xff0c;放在最后$(hello).appendTo(…

python自动化框架测试实操_自动化框架之 python+selenium+pytest

1.概述 selenium&#xff1a; 基于JavaScript代码库的自动化测试框架&#xff0c;通过脚本语言&#xff0c;模拟用户行为操作&#xff0c;最接近用户真实场景&#xff0c;实现对web自动测试。 Selenium&#xff0c;是目前的最火爆企业最主流的webUI自动化框架 pytest: pytest是…

mysql 关联查询慢_mysql慢查询语句分析总结

我们经常会接触到MySQL&#xff0c;也经常会遇到一些MySQL的性能问题。我们可以借助慢查询日志和explain命令初步分析出SQL语句存在的性能问题通过SHOW FULL PROCESSLIST查看问题SHOW FULL PROCESSLIST相当于select * from information_schema.processlist可以列出正在运行的连…

python opencv3 轮廓检测

git&#xff1a;https://github.com/linyi0604/Computer-Vision 1 # coding:utf82 3 import cv24 import numpy as np5 6 # 创建一个200*200 的黑色空白图像7 img np.zeros((200, 200), dtypenp.uint8)8 # 在图像的中央位置 放置一个100*100的白色方块9 img[50:150, 50: 150] …

CentOS7搭建NTP服务器

搭建ntp服务器 查看服务器、客户端操作系统版本 2查看服务器是否安装ntp 3如果没有安装 4安装完成后重新查看服务器是否安装ntp 5查看ntp服务器状态 6修改配置文件 注释 #server 0.centos.pool.ntp.org iburst #server 1.centos.pool.ntp.org iburst #server 2.centos.p…

mysql 5.7.21-linux_MySQL 5.7.21 Linux平台安装 Part 2

从今天开始MySQL相关方面的东西今天是关于MySQL的安装系统为 redhat 6.10数据库为MySQL 5.7.21PS:目前最新版本为MySQL 5.7.251. 目录规划2. MySQL 5.7 下载目前MySQL 社区的GA 提供5 和8 的下载由于目前大多数系统用的还是5的版本这里统一使用5的版本注意&#xff0c;下面是按…

session很快失效_深夜,我偷听到程序员要对session下手...

我是一个web服务器我的工作是给人类提供上网服务&#xff0c;我每天要为数以万计的人提供网页浏览服务。已经是深夜了&#xff0c;我还在和手下几个兄弟为了一件事紧张讨论着。“老大&#xff0c;现在咱们每天处理的请求越来越多了&#xff0c;session同步的问题不能再拖了&…