当前位置:   article > 正文

还在手写CRUD代码?试试这款代码生成工具吧,彻底解放双手!_根据ddl生成实体类和crud代码的在线工具

根据ddl生成实体类和crud代码的在线工具

缘起

最近在做一个项目,需要新建 20 多张表

相信大多数同学应该和我一样,都是比较讨厌创建新表这个工作的,因为每创建一张表,都要去创建实体类、创建增删改查的接口、编写增删改查的 SQL 代码等等,把这些事情做完,2 个小时也就过去了

我就在思考啊,每一张表,就要耗费两个小时,20 多张表,那就是 40 多个小时,一周的时间就这样过去了。

这谁受得了呀,所以我打算写一个工具,把这些代码都自动生成出来!

在连续爆肝了 5 个晚上之后,我做出了这款自动生成业务代码的工具!

我把它放在了我的工具站上,大家可以访问这个域名直接使用:https://utilsbox.cn/?app=bizcode

目前已经开源:https://github.com/GooseCoding/utilsbox

使用演示

下面给大家演示一下

假设我们现在创建一个商品表

首先填写表名和表的中文名称

然后我们添加商品表对应的字段,这些操作和我们日常使用的数据库工具差不多

把字段填写好了之后,点击“一键生成代码”

高潮的地方来了

DB 层、业务层、甚至是 controller 层的代码,工具都帮我们自动生成了!

来看下代码,建表 sql、增删改查 sql、表对应的实体类、DB 层的接口类、业务层的实体类、业务层的接口类、业务接口的实现类、业务层实体类和 db 层实体类的转换器,最后是 controller 层,这些代码全都帮我们生成好了。

这是什么概念呢

现在我们只需要把这些代码拷贝到项目里,简单设置一下类的引用,增删改查这些基本功能,就已经可以直接给前端去调用了。

很多同学可能会问,如果是现有的数据表,再来这里添加一次感觉太麻烦了

这个问题我也遇到了,所以我做了一个识别建表 SQL 的功能,常见的数据库工具对于已经创建好的表,都提供建表语句的复制功能,只需要把建表 SQL 粘贴到这个文本框里。

点击“识别”按钮,这个 SQL 的信息会自动识别过来,这时候只需要把表的中文名称填写上去,点击“一键生成代码”,就可以马上得到这个表的业务代码。

通用性的思考

不知道大家觉得怎么样哈,如果只是我自己用,我觉着已经非常好了,但既然是开放出来给大家用,通用性肯定还是不够的。

因为现在看到的这一套自动生成的代码,可能只是适合我,但不同的人、不同的公司,它们项目结构的分层、代码的细节,都是不一样的

所以,我还开发了代码模版配置的功能

点击“代码模版配置”按钮,在这个弹窗里,我们可以新增、删除代码的分类。同样的,也可以新增、删除和编辑具体的代码模版。

设计

代码生成的原理

在说代码模版具体怎么配置之前,先给大家讲一下代码自动生成的原理

它由代码模版和动态参数组成,核心就是匹配 - 替换

首先,工具提供了很多动态参数,这些动态参数,对应的是我们填写的表名、字段名等等这些信息的原始值,或者处理过后的值。

然后,代码模版由用户自行定义,在代码的关键位置,插入动态参数,即可形成一份代码模版。

最后,工具通过匹配和替换动态参数,最终生成了代码。

理论上,不论什么语言,你都可以配置专属于你自己的代码模版。

举个简单的栗子:

我们配置了一份这样的代码模版,如下:

  1. /**
  2. * $table_desc$Model模型
  3. * Created by 创建人 on $current_time$.
  4. */
  5. public class $table_name_hump_A$Model extends ToString{
  6. }

可以看到,模版里分别使用了$table_desc$(表中文名)$current_time$(当前时间)$table_name_hump_A$(表名转首字母大写驼峰) 这三个动态参数。

当我们设置 表名 = goods_order、表中文名 = 商品订单 时,代码生成的结果如下所示:

  1. /**
  2. * 商品订单Model模型
  3. * Created by 创建人 on 2023-02-05 17:12:32.
  4. */
  5. public class GoodsOrderModel extends ToString{
  6. }

动态参数部分,全部替换成了我们输入的表信息。

最后希望这个项目对大家有用,之后我会开发更多有意思的项目。

由于这个项目都是晚上加班肝出来的,可能会存在一些 BUG,发现了我会尽快修复的,也请大家多多包涵。

这几天我会整理一下代码,把注释什么的都写好,然后把代码完完整整的开源给大家,感谢大家的观看,我们下期见。

代码模版参考

以下是当前工具里默认的代码模版,你可以通过参考这些模版,举一反三,配置出专属于你自己的代码模版。

工具提供了模版的导入和导出功能,如果你创建好了一份非常满意的模版,可以导出,然后发给你的同事直接使用,这样它就不用重复创建了,你也可以忽悠你的同事来创建,然后分享给你。

建表 SQL 模版

  1. CREATE TABLE `$table_name$` (
  2. $create_table_field_list$
  3. PRIMARY KEY (`$primary_key$`)
  4. ) ENGINE=$db_engine$ DEFAULT CHARSET=$db_encoded$;

实体类模版

主体

  1. /**
  2. * $table_desc$DTO模型
  3. * Created by 创建人 on $current_time$.
  4. */
  5. public class $table_name_hump_A$DO {
  6. $member_param_list$
  7. $get_set_method_list$
  8. }

成员代码块 成员变量列表(member_param_list)

  1. /** $field_comment$ */
  2. private $field_type_java$ $field_name_hump$;

成员代码块 GetSet 方法列表(get_set_method_list)

  1. public $field_type_java$ get$field_name_hump_A$() {
  2. return $field_name_hump$;
  3. }
  4. public void set$field_name_hump_A$($field_type_java$ $field_name_hump$) {
  5. this.$field_name_hump$ = $field_name_hump$;
  6. }

接口类模版(DB 层)

  1. import org.apache.ibatis.annotations.Mapper;
  2. import org.apache.ibatis.annotations.Param;
  3. import java.util.List;
  4. import java.util.Map;
  5. /**
  6. * $table_desc$DB接口
  7. * Created by 创建人 on $current_time$
  8. */
  9. @Mapper
  10. public interface $table_name_hump_A$DAO {
  11. /**
  12. * 添加
  13. * @param data
  14. * return 影响行数
  15. */
  16. int insert($table_name_hump_A$DO data);
  17. /**
  18. * 修改
  19. * @param data
  20. * return 影响行数
  21. */
  22. int update($table_name_hump_A$DO data);
  23. /**
  24. * 分页查询
  25. * @param param
  26. * return 结果列表
  27. */
  28. List<$table_name_hump_A$DO> pageQuery(Map param);
  29. /**
  30. * 查询count
  31. * @param param
  32. * return count条数
  33. */
  34. Long pageQueryCount(Map param);
  35. /**
  36. * 根据ID查询
  37. * @param id
  38. * return 结果DO对象
  39. */
  40. $table_name_hump_A$DO queryById(@Param("$primary_key_hump$") $primary_key_type_java$ $primary_key_hump$);
  41. /**
  42. * 根据ID查询(带锁)
  43. * @param id
  44. * return 结果DO对象
  45. */
  46. $table_name_hump_A$DO queryByIdLock(@Param("$primary_key_hump$") $primary_key_type_java$ $primary_key_hump$);
  47. }

CRUD SQL 模版

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- $table_name_hump_A$Mapper.xml -->
  3. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  4. <mapper namespace="com.xxx.$table_name_hump_A$DAO">
  5. <insert id="insert" useGeneratedKeys="true" keyProperty="id">
  6. INSERT INTO $table_name$($insert_field_name_list$)
  7. VALUES ($insert_field_value_list$);
  8. </insert>
  9. <update id="update">
  10. UPDATE $table_name$ SET
  11. $update_field_list$
  12. WHERE $primary_key$ = #{$primary_key_hump$};
  13. </update>
  14. <select id="pageQuery" resultType="com.xxx.$table_name_hump_A$DO">
  15. SELECT $select_field_list$ FROM $table_name$
  16. WHERE 1=1
  17. $while_field_list$
  18. ORDER BY $primary_key$ DESC
  19. <if test="pageIndex != null and pageSize != null">
  20. LIMIT #{offset},#{rows}
  21. </if>
  22. </select>
  23. <select id="pageQueryCount" resultType="java.lang.Long">
  24. SELECT COUNT(1) as total FROM $table_name$
  25. WHERE 1=1
  26. $while_field_list$
  27. </select>
  28. <select id="queryById" resultType="com.xxx.$table_name_hump_A$DO">
  29. SELECT $select_field_list$ FROM $table_name$
  30. WHERE $primary_key$ = #{$primary_key_hump$};
  31. </select>
  32. <select id="queryByIdLock" resultType="com.xxx.$table_name_hump_A$DO">
  33. SELECT $select_field_list$ FROM $table_name$
  34. WHERE $primary_key$ = #{$primary_key_hump$} FOR UPDATE;
  35. </select>
  36. </mapper>

模型转换器模版

不同层级间,可能会有不同的实体类,那么它们相互之间的数据转换,也是一个重复且浪费时间的工作,所以也可以配置一个模版。

  1. import org.springframework.util.CollectionUtils;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /**
  5. * $table_desc$ 模型转换器
  6. * Created by 创建人 on $current_time$
  7. */
  8. public class $table_name_hump_A$Converter {
  9. /**
  10. * dto转do
  11. * @param source
  12. * return do模型
  13. */
  14. public static $table_name_hump_A$DO toDo($table_name_hump_A$DTO source){
  15. $table_name_hump_A$DO target = new $table_name_hump_A$DO();
  16. $converter_source_to_target_params_list$
  17. return target;
  18. }
  19. /**
  20. * do转dto
  21. * @param source
  22. * return dto模型
  23. */
  24. public static $table_name_hump_A$DTO toDto($table_name_hump_A$DO source){
  25. $table_name_hump_A$DTO target = new $table_name_hump_A$DTO();
  26. $converter_source_to_target_params_list$
  27. return target;
  28. }
  29. /**
  30. * do list 转 dto
  31. * @param data
  32. * return list dto模型
  33. */
  34. public static List<$table_name_hump_A$DTO> toDtoList(List<$table_name_hump_A$DO> data){
  35. if (CollectionUtils.isEmpty(data)){
  36. return null;
  37. }
  38. List<$table_name_hump_A$DTO> list = new ArrayList<>();
  39. for ($table_name_hump_A$DO item : data){
  40. list.add($table_name_hump_A$Converter.toDto(item));
  41. }
  42. return list;
  43. }
  44. }

成员代码块 模型转换器参数列表(converter_source_to_target_params_list)

       target.set$field_name_hump_A$(source.get$field_name_hump_A$());

业务接口实现类模版

  1. import com.alibaba.fastjson.JSONObject;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.stereotype.Service;
  5. /**
  6. * $table_desc$ 业务实现
  7. * Created by 创建人 on $current_time$
  8. */
  9. @Service
  10. public class $table_name_hump_A$ServiceImpl implements $table_name_hump_A$Service {
  11. private static final Logger LOGGER = LoggerFactory.getLogger($table_name_hump_A$ServiceImpl.class);
  12. @Resource
  13. private $table_name_hump_A$DAO $table_name_hump$DAO;
  14. @Override
  15. public CommonResult create(JSONObject request) {
  16. // 入参转成对应类型
  17. CommonAssert.isNoEmptyObj(request, "请求参数不可空");
  18. $table_name_hump_A$DTO dto = JSON.toJavaObject(request, $table_name_hump_A$DTO.class);
  19. // 参数校验
  20. $biz_check_required_params$
  21. // 转成do模型
  22. $table_name_hump_A$DO dataDo = $table_name_hump_A$Converter.toDo(dto);
  23. // 落库
  24. int count = $table_name_hump$DAO.insert(dataDo);
  25. CommonAssert.isTrue(count > 0, "创建失败,请重试");
  26. // 返回创建成功的ID数据
  27. return new CommonResult(dataDo.get$primary_key_hump_A$());
  28. }
  29. @Override
  30. public CommonResult modify(JSONObject request) {
  31. // 入参转成对应类型
  32. CommonAssert.isNoEmptyObj(request, "请求参数不可空");
  33. $table_name_hump_A$DTO dto = JSON.toJavaObject(request, $table_name_hump_A$DTO.class);
  34. // 参数校验
  35. $biz_check_required_params$
  36. // 转成do模型
  37. $table_name_hump_A$DO dataDo = $table_name_hump_A$Converter.toDo(dto);
  38. // 落库
  39. int count = $table_name_hump$DAO.update(dataDo);
  40. CommonAssert.greaterThanZero(count, "修改失败,请重试");
  41. // 返回修改成功的ID数据
  42. return new CommonResult(dataDo.get$primary_key_hump_A$());
  43. }
  44. @Override
  45. public CommonResult pageQuery(JSONObject request) {
  46. // 入参基本校验
  47. CommonAssert.isNoEmptyObj(request, "请求参数不可空");
  48. // 分页信息校验
  49. PaginationDO pagination = PaginationDO.setRequestOffsetAndRows(request);
  50. CommonAssert.isNoEmptyObj(pagination, "分页参数 $pageIndex、$pageSize 不可空");
  51. CommonAssert.isTrue(pagination.getPageSize() <= 100, "单次查询条数不可超过100条");
  52. // 取分页列表数据
  53. List<$table_name_hump_A$DO> dbResult = $table_name_hump$DAO.pageQuery(request);
  54. // 取count数据
  55. long count = $table_name_hump$DAO.pageQueryCount(request);
  56. // 空返回
  57. if (CollectionUtils.isEmpty(dbResult)){
  58. return new CommonResult(new PaginationResult(null, request, count));
  59. }
  60. // 模型转换
  61. List<$table_name_hump_A$DTO> list = $table_name_hump_A$Converter.toDtoList(dbResult);
  62. // 返回分页结果
  63. return new CommonResult(new PaginationResult(list, request, count));
  64. }
  65. @Override
  66. public CommonResult queryById(JSONObject request) {
  67. // 取入参
  68. CommonAssert.isNoEmptyObj(request, "请求参数不可空");
  69. // 根据ID获取数据
  70. $primary_key_type_java$ $primary_key_hump$ = request.get$primary_key_type_java$("$primary_key_hump$");
  71. CommonAssert.isNoEmptyObj($primary_key_hump$, "参数错误,无法执行查询");
  72. $table_name_hump_A$DO dbResult = $table_name_hump$DAO.queryById($primary_key_hump$);
  73. // 未查询到结果,返回
  74. if (null == dbResult){
  75. return new CommonResult();
  76. }
  77. // 模型转换
  78. $table_name_hump_A$DTO result = $table_name_hump_A$Converter.toDto(dbResult);
  79. // 返回结果对象
  80. return new CommonResult(result);
  81. }
  82. }

成员代码块 必填项业务校验(biz_check_required_params)

 CommonAssert.$java_type_adapter_assert_method$(dto.get$field_name_hump_A$(), "$field_comment$ 不可空");

Controller 模版

  1. import com.alibaba.fastjson.JSONObject;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.web.bind.annotation.*;
  5. import javax.annotation.Resource;
  6. /**
  7. * $table_desc$HTTP请求控制器
  8. * Created by 创建人 on $current_time$.
  9. */
  10. @CrossOrigin
  11. @RestController
  12. @RequestMapping(value = "/$table_name_hump$/")
  13. public class $table_name_hump_A$Controller {
  14. private static final Logger LOGGER = LoggerFactory.getLogger($table_name_hump_A$Controller.class);
  15. @Resource
  16. private $table_name_hump_A$Service $table_name_hump$Service;
  17. /**
  18. * 创建
  19. * @param request
  20. * @return
  21. */
  22. @RequestMapping(value = "create.json", method = {RequestMethod.GET, RequestMethod.POST})
  23. @ResponseBody
  24. public Object create(@RequestBody JSONObject request){
  25. return CommonTemplate.run(LOGGER, new CommonTemplate() {
  26. @Override
  27. protected Object business() {
  28. return $table_name_hump$Service.create(request);
  29. }
  30. }, request);
  31. }
  32. /**
  33. * 修改
  34. * @param request
  35. * @return
  36. */
  37. @RequestMapping(value = "modify.json", method = {RequestMethod.GET, RequestMethod.POST})
  38. @ResponseBody
  39. public Object modify(@RequestBody JSONObject request){
  40. return CommonTemplate.run(LOGGER, new CommonTemplate() {
  41. @Override
  42. protected Object business() {
  43. return $table_name_hump$Service.modify(request);
  44. }
  45. }, request);
  46. }
  47. /**
  48. * 分页查询
  49. * @param request
  50. * @return
  51. */
  52. @RequestMapping(value = "pageQuery.json", method = {RequestMethod.GET, RequestMethod.POST})
  53. @ResponseBody
  54. public Object pageQuery(@RequestBody JSONObject request){
  55. return CommonTemplate.run(LOGGER, new CommonTemplate() {
  56. @Override
  57. protected Object business() {
  58. return $table_name_hump$Service.pageQuery(request);
  59. }
  60. }, request);
  61. }
  62. /**
  63. * 通过主键查询
  64. * @param request
  65. * @return
  66. */
  67. @RequestMapping(value = "queryById.json", method = {RequestMethod.GET, RequestMethod.POST})
  68. @ResponseBody
  69. public Object queryById(@RequestBody JSONObject request){
  70. return CommonTemplate.run(LOGGER, new CommonTemplate() {
  71. @Override
  72. protected Object business() {
  73. return $table_name_hump$Service.queryById(request);
  74. }
  75. }, request);
  76. }
  77. }

动态参数

原始表名 $table_name$

用户输入的表名,不做任何处理。

表名驼峰首字母小写 $table_name_hump$

用户输入的表名,经过驼峰处理。例如输入:goods_order ,输出:goodsOrder

表名驼峰首字母大写 $table_name_hump_A$

用户输入的表名,经过驼峰处理。例如输入:goods_order ,输出:GoodsOrder

表中文名 $table_desc$

用户输入的表中文名,不做任何处理。

数据库引擎 $db_engine$

用户输入的表数据库引擎,不做任何处理。

数据库编码 $db_encoded$

用户输入的表数据库编码,不做任何处理。

原始字段名 $field_name$

用户输入的表字段名,不做任何处理。

字段名驼峰首字母小写 $field_name_hump$

用户输入的表字段名,经过驼峰处理。例如输入:order_number ,输出:orderNumber

字段名驼峰首字母大写 $field_name_hump_A$

用户输入的表字段名,经过驼峰处理。例如输入:order_number ,输出:OrderNumber

字段说明 $field_comment$

用户输入的表字段说明,不做任何处理。

字段数据类型(对应 DB)$field_type_db$

用户选择的表字段类型,不做任何处理。

字段数据类型(对应 Java)$field_type_java$

用户选择的表字段类型,会自动匹配对应的 Java 类型。例如输入:VARCHAR(),输出:String

主键字段名 $primary_key$

用户选择的主键字段,不做任何处理。例如用户定义的主键是 id,那么输出就是:id

主键字段名驼峰首字母小写 $primary_key_hump$

用户选择的主键字段,经过驼峰处理。例如输入:order_number ,输出:orderNumber

主键字段名驼峰首字母大写 $primary_key_hump_A$

用户选择的主键字段,经过驼峰处理。例如输入:order_number ,输出:OrderNumber

主键字段数据类型(对应 Java)$primary_key_type_java$

用户选择的主键字段类型,会自动匹配对应的 Java 类型。例如输入:VARCHAR(),输出:String

插入数据 sql,字段名列表 $insert_field_name_list$

例如表中有三个字段:id(主键)、goods_name、price,输出:goods_name,price 。会自动排除主键 不仅插入数据时可用,任何需要排除 ID,然后使用英文逗号拼接表所有字段信息的地方,都可以使用它

插入数据 sql,字段值列表 $insert_field_value_list$

例如表中有三个字段:id(主键)、goods_name、price,输出:#{goodsName},#{price} 。会自动排除主键 不仅插入数据时可用,任何需要排除 ID,然后使用英文逗号拼接表所有字段信息的地方,都可以使用它

修改数据 sql,字段名列表 $update_field_list$

例如表中有三个字段:id(主键)、goods_name、price 输出(会自动换行,会携带以下缩进,会自动排除主键):
goods_name = #{goodsName},price = #{price}

查询数据 sql,字段名列表 $select_field_list$

例如表中有三个字段:id(主键)、goods_name、price,输出:id,goods_name,price 。带主键

whele 字段条件 sql,字段名列表 $where_field_list$

例如表中有三个字段:id(主键)、goods_name、price, 输出(会自动换行,会携带以下缩进):
  1. <if test="id != null">
  2. AND id = #{id}
  3. </if>
  4. <if test="goodsName != null">
  5. AND goods_name = #{goodsName}
  6. </if>
  7. <if test="price != null">
  8. AND price = #{price}
  9. </if>

创建表-表字段列表 $create_table_field_list$

例如表中有三个字段:id(自增主键)、goods_name、price 输出(会自动换行,会携带以下缩进):
  1. `id` INT(11) NOT NULL AUTO_INCREMENT,
  2. `goods_name` VARCHAR(128) NOT NULL DEFAULT 'NULL',
  3. `price` DECIMAL(10,2) NOT NULL DEFAULT 'NULL'

当前时间 $current_time$

自动获取当前时间,格式:yyyy-MM-DD hh:mm:ss,示例值:2023-02-05 17:31:18

自动根据数据类型,匹配断言方法 $java_type_adapter_assert_method$

对于 Java 数据类型等于 String 的字段,使用 isNoBlankStr 方法,其他的类型都使用 isNoEmptyObj 方法 这是一个定制化很高的动态参数,可忽略它。

动态代码块

动态代码块由用户自行定义,代码块中也可以设置动态参数,目前仅提供 4 种明确的动态代码块

成员变量列表 $member_param_list$

例如表中有三个字段:id(主键)、goods_name、price

假设用户定义了如下代码块内容:

  1. /** $field_comment$ */
  2. private $field_type_java$ $field_name_hump$;

输出(会自动根据字段数量,累加输出自定义代码块内容):

  1. /** id */
  2. private Integer id;
  3. /** 商品名称 */
  4. private String goodsName;
  5. /** 商品价格 */
  6. private String price;

GetSet 方法列表 $get_set_method_list$

例如表中有三个字段:id(主键)、goods_name、price

假设用户定义了如下代码块内容:

  1. public $field_type_java$ get$field_name_hump_A$() {
  2. return $field_name_hump$;
  3. }
  4. public void set$field_name_hump_A$($field_type_java$ $field_name_hump$) {
  5. this.$field_name_hump$ = $field_name_hump$;
  6. }

输出(会自动根据字段数量,累加输出自定义代码块内容):

  1. public Integer getId() {
  2. return id;
  3. }
  4. public void setId(Integer id) {
  5. this.id = id;
  6. }
  7. public String getGoodsName() {
  8. return goodsName;
  9. }
  10. public void setGoodsName(String goodsName) {
  11. this.goodsName = goodsName;
  12. }
  13. public String getPrice() {
  14. return price;
  15. }
  16. public void setPrice(String price) {
  17. this.price = price;
  18. }

模型转换器参数列表 $converter_source_to_target_params_list$

例如表中有三个字段:id(主键)、goods_name、price

假设用户定义了如下代码块内容:

target.set$field_name_hump_A$(source.get$field_name_hump_A$());

输出(会自动根据字段数量,累加输出自定义代码块内容):

  1. target.setId(source.getId());
  2. target.setGoodsName(source.getGoodsName());
  3. target.setPrice(source.getPrice());

必填项业务校验 $biz_check_required_params$

例如表中有三个字段:id(主键)、goods_name、price

假设用户定义了如下代码块内容:

CommonAssert.$java_type_adapter_assert_method$(dto.get$field_name_hump_A$(), "$field_comment$ 不可空");

输出(会自动根据字段数量,累加输出自定义代码块内容):

  1. CommonAssert.isNoBlankStr(dto.getGoodsName(), "goodsName不可空");
  2. CommonAssert.isNoBlankStr(dto.getPrice(), "price不可空");
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/231142
推荐阅读
相关标签
  

闽ICP备14008679号