你还在手写crud吗,看完这篇文章,绝对赚了

本文转载自微信公众号「Java极客技术」,作者鸭血粉丝 。转载本文请联系Java极客技术公众号。

成都创新互联服务项目包括南乐网站建设、南乐网站制作、南乐网页制作以及南乐网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,南乐网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到南乐省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!

一、介绍

我记得最早刚步入互联网行业的时候,当时按照 MVC 的思想和模型,每次开发新功能,会依次编写 dao、service、controller相关服务类,包括对应的 dto、entity、vo 等等实体类,如果有多张单表,也会重复的编写相似的代码,现在回想起来,感觉当时自己好像处于石器时代!

实际上,当仔细的总结一下,对于任何一张单表的操作,基本都是围绕增(Create )、删(Delete )、改(Update )、查(Retrieve )四个方向进行数据操作,简称 CRUD!

他们除了表名和存储空间不一样,基本的 CRUD 思路基本都是一样的。

为了解决这些重复劳动的痛点,业界逐渐开源了一批代码生成器,目的也很简单,就是为了减少手工操作的繁琐,集中精力在业务开发上,提升开发效率。

而今天,我们所要介绍的也是代码生成器,很多初学者可能觉得代码生成器很高深。代码生成器其实是一个很简单的东西,一点都不高深。

当你看完本文的时候,你会完全掌握代码生成器的逻辑,甚至可以根据自己的项目情况,进行深度定制。

二、实现思路

下面我们就以SpringBoot项目为例,数据持久化操作采用Mybatis,数据库采用Mysql,编写一个自动生成增、删、改、查等基础功能的代码生成器,内容包括controller、service、dao、entity、dto、vo等信息。

实现思路如下:

第一步:获取表字段名称、类型、表注释等信息

第二步:基于 freemarker 模板引擎,编写相应的模板

第三步:根据对应的模板,生成相应的 java 代码

2.1、获取表结构

首先我们创建一张test_db表,脚本如下:

 
 
 
 
  1. CREATE TABLE test_db (
  2.   id bigint(20) unsigned NOT NULL COMMENT '主键ID',
  3.   name varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名称',
  4.   is_delete tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否删除 1:已删除;0:未删除',
  5.   create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  6.   update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  7.   PRIMARY KEY (id),
  8.   KEY idx_create_time (create_time) USING BTREE
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='测试表';

表创建完成之后,基于test_db表,我们查询对应的表结果字段名称、类型、备注信息,这些关键信息将用于后续进行代码生成器所使用!

 
 
 
 
  1. # 获取对应表结构
  2. SELECT column_name, data_type, column_comment FROM information_schema.columns WHERE table_schema = 'yjgj_base' AND table_name = 'test_db'

同时,获取对应表注释,用于生成备注信息!

 
 
 
 
  1. # 获取对应表注释
  2. SELECT TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'yjgj_base' AND table_name = 'test_db'

2.2、编写模板

编写mapper.ftl模板,涵盖新增、修改、删除、查询等信息

 
 
 
 
  1.  
  2.  
  3.         <#list columns as pro>
  4.             <#if pro.proName == primaryId>
  5.     
  6.             <#else>
  7.     
  8.             
  9.         
  10.  
  11.  
  12.  
  13.         <#list columns as pro>
  14.             <#if pro_index == 0>${pro.fieldName}<#else>,${pro.fieldName}
  15.         
  16.  
  17.  
  18.  
  19.   insert into ${tableName} (
  20.         <#list columns as pro>
  21.             <#if pro_index == 0>${pro.fieldName},<#elseif pro_index == 1>${pro.fieldName}<#else>,${pro.fieldName}
  22.         
  23.   )
  24.   values
  25.   
  26.    
  27.                 <#list columns as pro>
  28.                     ${r"#{obj." + pro.proName + r"}"},
  29.                 
  30.    
  31.   
  32.  
  33.  
  34.  
  35.   insert into ${tableName}
  36.   
  37.             <#list columns as pro>
  38.     
  39.                     ${pro.fieldName},
  40.     
  41.             
  42.   
  43.   
  44.             <#list columns as pro>
  45.     
  46.                     ${r"#{" + pro.proName + r",jdbcType=" + pro.fieldType +r"}"},
  47.     
  48.             
  49.   
  50.  
  51.  
  52.  
  53.   update ${tableName}
  54.   
  55.             <#list columns as pro>
  56.                 <#if pro.fieldName != primaryId && pro.fieldName != primaryId>
  57.      
  58.                         ${pro.fieldName} = ${r"#{" + pro.proName + r",jdbcType=" + pro.fieldType +r"}"},
  59.      
  60.                 
  61.             
  62.   
  63.   where ${primaryId} = ${r"#{" + "${primaryId}" + r",jdbcType=BIGINT}"}
  64.  
  65.  
  66.  
  67.   update ${tableName}
  68.   
  69.             <#list columns as pro>
  70.                 <#if pro.fieldName != primaryId && pro.fieldName != primaryId>
  71.      
  72.       
  73.        
  74.         when id = ${r"#{" + "obj.id" + r"}"}
  75.         then  ${r"#{obj." + pro.proName + r",jdbcType=" + pro.fieldType +r"}"}
  76.        
  77.       
  78.      
  79.                 
  80.             
  81.   
  82.   where
  83.   
  84.    id = ${r"#{" + "obj.id" + r"}"}
  85.   
  86.  
  87.  
  88.  
  89.   delete from ${tableName}
  90.   where ${primaryId} = ${r"#{" + "${primaryId}" + r",jdbcType=BIGINT}"}
  91.  
  92.  
  93.  
  94.   select
  95.   
  96.   from ${tableName}
  97.   where ${primaryId} = ${r"#{" + "${primaryId}" + r",jdbcType=BIGINT}"}
  98.  
  99.  
  100.  
  101.   select
  102.   
  103.   from ${tableName}
  104.  
  105.  
  106.  
  107.   select
  108.   
  109.   from ${tableName}
  110.   
  111.    
  112.     and ${primaryId} in
  113.     
  114.                     ${r"#{" + "item" + r"}"}
  115.     
  116.    
  117.   
  118.  
  119.  
  120.  
  121.   select
  122.   
  123.   from ${tableName}
  124.  
  125.  
  126.  
  127.   select count(${primaryId})
  128.   from ${tableName}
  129.  
  130.  
  131.  
  132.   select
  133.   
  134.   from ${tableName}
  135.   limit ${r"#{" + "start,jdbcType=INTEGER" + r"}"},${r"#{" + "end,jdbcType=INTEGER" + r"}"}
  136.  

编写dao.ftl数据访问模板

 
 
 
 
  1. package ${daoPackageName};
  2. import com.example.generator.core.BaseMapper;
  3. import java.util.List;
  4. import ${entityPackageName}.${entityName};
  5. import ${dtoPackageName}.${dtoName};
  6. /**
  7. *
  8. * @ClassName: ${daoName}
  9. * @Description: 数据访问接口
  10. * @author ${authorName}
  11. * @date ${currentTime}
  12. *
  13. */
  14. public interface ${daoName} extends BaseMapper<${entityName}>{
  15.  int countPage(${dtoName} ${dtoName?uncap_first});
  16.  List<${entityName}> selectPage(${dtoName} ${dtoName?uncap_first});
  17. }

编写service.ftl服务接口模板

 
 
 
 
  1. package ${servicePackageName};
  2. import com.example.generator.core.BaseService;
  3. import com.example.generator.common.Pager;
  4. import ${voPackageName}.${voName};
  5. import ${dtoPackageName}.${dtoName};
  6. import ${entityPackageName}.${entityName};
  7. /**
  8.  *
  9.  * @ClassName: ${serviceName}
  10.  * @Description: ${entityName}业务访问接口
  11.  * @author ${authorName}
  12.  * @date ${currentTime}
  13.  *
  14.  */
  15. public interface ${serviceName} extends BaseService<${entityName}> {
  16.  /**
  17.   * 分页列表查询
  18.   * @param request
  19.   */
  20.  Pager<${voName}> getPage(${dtoName} request);
  21. }

编写serviceImpl.ftl服务实现类模板

 
 
 
 
  1. package ${serviceImplPackageName};
  2. import com.example.generator.common.Pager;
  3. import com.example.generator.core.BaseServiceImpl;
  4. import com.example.generator.test.service.TestEntityService;
  5. import org.springframework.beans.BeanUtils;
  6. import org.springframework.stereotype.Service;
  7. import org.springframework.util.CollectionUtils;
  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import ${daoPackageName}.${daoName};
  13. import ${entityPackageName}.${entityName};
  14. import ${dtoPackageName}.${dtoName};
  15. import ${voPackageName}.${voName};
  16. @Service
  17. public class ${serviceImplName} extends BaseServiceImpl<${daoName}, ${entityName}> implements ${serviceName} {
  18.  private static final Logger log = LoggerFactory.getLogger(${serviceImplName}.class);
  19.  /**
  20.   * 分页列表查询
  21.   * @param request
  22.   */
  23.  public Pager<${voName}> getPage(${dtoName} request) {
  24.   List<${voName}> resultList = new ArrayList();
  25.   int count = super.baseMapper.countPage(request);
  26.   List<${entityName}> dbList = count > 0 ? super.baseMapper.selectPage(request) : new ArrayList<>();
  27.   if(!CollectionUtils.isEmpty(dbList)){
  28.    dbList.forEach(source->{
  29.     ${voName} target = new ${voName}();
  30.     BeanUtils.copyProperties(source, target);
  31.     resultList.add(target);
  32.    });
  33.   }
  34.   return new Pager(request.getCurrPage(), request.getPageSize(), count, resultList);
  35.  }
  36. }

编写controller.ftl控制层模板

 
 
 
 
  1. package ${controllerPackageName};
  2. import com.example.generator.common.IdRequest;
  3. import com.example.generator.common.Pager;
  4. import org.springframework.beans.BeanUtils;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.web.bind.annotation.PostMapping;
  7. import org.springframework.web.bind.annotation.RequestBody;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.RestController;
  10. import java.util.Objects;
  11. import ${servicePackageName}.${serviceName};
  12. import ${entityPackageName}.${entityName};
  13. import ${dtoPackageName}.${dtoName};
  14. import ${voPackageName}.${voName};
  15. /**
  16.  *
  17.  * @ClassName: ${controllerName}
  18.  * @Description: 外部访问接口
  19.  * @author ${authorName}
  20.  * @date ${currentTime}
  21.  *
  22.  */
  23. @RestController
  24. @RequestMapping("/${entityName?uncap_first}")
  25. public class ${controllerName} {
  26.  @Autowired
  27.  private ${serviceName} ${serviceName?uncap_first};
  28.  /**
  29.   * 分页列表查询
  30.   * @param request
  31.   */
  32.  @PostMapping(value = "/getPage")
  33.  public Pager<${voName}> getPage(@RequestBody ${dtoName} request){
  34.   return ${serviceName?uncap_first}.getPage(request);
  35.  }
  36.  /**
  37.   * 查询详情
  38.   * @param request
  39.   */
  40.  @PostMapping(value = "/getDetail")
  41.  public ${voName} getDetail(@RequestBody IdRequest request){
  42.   ${entityName} source = ${serviceName?uncap_first}.selectById(request.getId());
  43.   if(Objects.nonNull(source)){
  44.    ${voName} result = new ${voName}();
  45.    BeanUtils.copyProperties(source, result);
  46.    return result;
  47.   }
  48.   return null;
  49.  }
  50.  /**
  51.   * 新增操作
  52.   * @param request
  53.   */
  54.  @PostMapping(value = "/save")
  55.  public void save(${dtoName} request){
  56.   ${entityName} entity = new ${entityName}();
  57.   BeanUtils.copyProperties(request, entity);
  58.   ${serviceName?uncap_first}.insert(entity);
  59.  }
  60.  /**
  61.   * 编辑操作
  62.   * @param request
  63.   */
  64.  @PostMapping(value = "/edit")
  65.  public void edit(${dtoName} request){
  66.   ${entityName} entity = new ${entityName}();
  67.   BeanUtils.copyProperties(request, entity);
  68.   ${serviceName?uncap_first}.updateById(entity);
  69.  }
  70.  /**
  71.   * 删除操作
  72.   * @param request
  73.   */
  74.  @PostMapping(value = "/delete")
  75.  public void delete(IdRequest request){
  76.   ${serviceName?uncap_first}.deleteById(request.getId());
  77.  }
  78. }

编写entity.ftl实体类模板

 
 
 
 
  1. package ${entityPackageName};
  2. import java.io.Serializable;
  3. import java.math.BigDecimal;
  4. import java.util.Date;
  5. /**
  6.  *
  7.  * @ClassName: ${entityName}
  8.  * @Description: ${tableDes!}实体类
  9.  * @author ${authorName}
  10.  * @date ${currentTime}
  11.  *
  12.  */
  13. public class ${entityName} implements Serializable {
  14.  private static final long serialVersionUID = 1L;
  15.  
  16.  <#--属性遍历-->
  17.  <#list columns as pro>
  18.  <#--<#if pro.proName != primaryId
  19.  && pro.proName != 'remarks'
  20.  && pro.proName != 'createBy'
  21.  && pro.proName != 'createDate'
  22.  && pro.proName != 'updateBy'
  23.  && pro.proName != 'updateDate'
  24.  && pro.proName != 'delFlag'
  25.  && pro.proName != 'currentUser'
  26.  && pro.proName != 'page'
  27.  && pro.proName != 'sqlMap'
  28.  && pro.proName != 'isNewRecord'
  29.  >-->
  30.  /**
  31.   * ${pro.proDes!}
  32.   */
  33.  private ${pro.proType} ${pro.proName};
  34.  
  35.  <#--属性get||set方法-->
  36.  <#list columns as pro>
  37.  public ${pro.proType} get${pro.proName?cap_first}() {
  38.   return this.${pro.proName};
  39.  }
  40.  public ${entityName} set${pro.proName?cap_first}(${pro.proType} ${pro.proName}) {
  41.   this.${pro.proName} = ${pro.proName};
  42.   return this;
  43.  }
  44.  
  45. }

编写dto.ftl实体类模板

 
 
 
 
  1. package ${dtoPackageName};
  2. import com.example.generator.core.BaseDTO;
  3. import java.io.Serializable;
  4. /**
  5.  * @ClassName: ${dtoName}
  6.  * @Description: 请求实体类
  7.  * @author ${authorName}
  8.  * @date ${currentTime}
  9.  *
  10.  */
  11. public class ${dtoName} extends BaseDTO {
  12. }

编写vo.ftl视图实体类模板

 
 
 
 
  1. package ${voPackageName};
  2. import java.io.Serializable;
  3. /**
  4.  * @ClassName: ${voName}
  5.  * @Description: 返回视图实体类
  6.  * @author ${authorName}
  7.  * @date ${currentTime}
  8.  *
  9.  */
  10. public class ${voName} implements Serializable {
  11.  private static final long serialVersionUID = 1L;
  12. }

可能细心的网友已经看到了,在模板中我们用到了BaseMapper、BaseService、BaseServiceImpl等等服务类。

之所以有这三个类,是因为在模板中,我们有大量的相同的方法名包括逻辑也相似,除了所在实体类不一样以外,其他都一样,因此我们可以借助泛型类来将这些服务抽成公共的部分。

BaseMapper,主要负责将dao层的公共方法抽出来

 
 
 
 
  1. package com.example.generator.core;
  2. import org.apache.ibatis.annotations.Param;
  3. import java.io.Serializable;
  4. import java.util.List;
  5. import java.util.Map;
  6. /**
  7.  * @author pzblog
  8.  * @Description
  9.  * @since 2020-11-11
  10.  */
  11. public interface BaseMapper {
  12.     /**
  13.      * 批量插入
  14.      * @param list
  15.      * @return
  16.      */
  17.     int insertList(@Param("list") List list);
  18.     /**
  19.      * 按需插入一条记录
  20.      * @param entity
  21.      * @return
  22.      */
  23.     int insertPrimaryKeySelective(T entity);
  24.     /**
  25.      * 按需修改一条记录(通过主键ID)
  26.      * @return
  27.      */
  28.     int updatePrimaryKeySelective(T entity);
  29.     /**
  30.      * 批量按需修改记录(通过主键ID)
  31.      * @param list
  32.      * @return
  33.      */
  34.     int updateBatchByIds(@Param("list") List list);
  35.     /**
  36.      * 根据ID删除
  37.      * @param id 主键ID
  38.      * @return
  39.      */
  40.     int deleteByPrimaryKey(Serializable id);
  41.     /**
  42.      * 根据ID查询
  43.      * @param id 主键ID
  44.      * @return
  45.      */
  46.     T selectByPrimaryKey(Serializable id);
  47.     /**
  48.      * 按需查询
  49.      * @param entity
  50.      * @return
  51.      */
  52.     List selectByPrimaryKeySelective(T entity);
  53.     /**
  54.      * 批量查询
  55.      * @param ids 主键ID集合
  56.      * @return
  57.      */
  58.     List selectByIds(@Param("ids") List ids);
  59.     /**
  60.      * 查询(根据 columnMap 条件)
  61.      * @param columnMap 表字段 map 对象
  62.      * @return
  63.      */
  64.     List selectByMap(Map columnMap);
  65. }

BaseService,主要负责将service层的公共方法抽出来

 
 
 
 
  1. package com.example.generator.core;
  2. import java.io.Serializable;
  3. import java.util.List;
  4. import java.util.Map;
  5. /**
  6.  * @author pzblog
  7.  * @Description 服务类
  8.  * @since 2020-11-11
  9.  */
  10. public interface BaseService {
  11.     /**
  12.      * 新增
  13.      * @param entity
  14.      * @return boolean
  15.      */
  16.     boolean insert(T entity);
  17.     /**
  18.      * 批量新增
  19.      * @param list
  20.      * @return boolean
  21.      */
  22.     boolean insertList(List list);
  23.     /**
  24.      * 通过ID修改记录(如果想全部更新,只需保证字段都不为NULL)
  25.      * @param entity
  26.      * @return boolean
  27.      */
  28.     boolean updateById(T entity);
  29.     /**
  30.      * 通过ID批量修改记录(如果想全部更新,只需保证字段都不为NULL)
  31.      * @param list
  32.      * @return boolean
  33.      */
  34.     boolean updateBatchByIds(List list);
  35.     /**
  36.      * 根据ID删除
  37.      * @param id 主键ID
  38.      * @return boolean
  39.      */
  40.     boolean deleteById(Serializable id);
  41.     /**
  42.      * 根据ID查询
  43.      * @param id 主键ID
  44.      * @return
  45.      */
  46.     T selectById(Serializable id);
  47.     /**
  48.      * 按需查询
  49.      * @param entity
  50.      * @return
  51.      */
  52.     List selectByPrimaryKeySelective(T entity);
  53.     /**
  54.      * 批量查询
  55.      * @param ids
  56.      * @return
  57.      */
  58.     List selectByIds(List ids);
  59.     /**
  60.      * 根据条件查询
  61.      * @param columnMap
  62.      * @return
  63.      */
  64.     List selectByMap(Map columnMap);
  65. }

BaseServiceImpl,service层的公共方法具体实现类

 
 
 
 
  1. package com.example.generator.core;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.transaction.annotation.Transactional;
  4. import java.io.Serializable;
  5. import java.util.List;
  6. import java.util.Map;
  7. /**
  8.  * @author pzblog
  9.  * @Description 实现类( 泛型说明:M 是 mapper 对象,T 是实体)
  10.  * @since 2020-11-11
  11.  */
  12. public abstract class BaseServiceImpl, T> implements BaseService{
  13.     @Autowired
  14.     protected M baseMapper;
  15.     /**
  16.      * 新增
  17.      * @param entity
  18.      * @return boolean
  19.      */
  20.     @Override
  21.     @Transactional(rollbackFor = {Exception.class})
  22.     public boolean insert(T entity){  标题名称:你还在手写crud吗,看完这篇文章,绝对赚了
    文章源于:http://www.hantingmc.com/qtweb/news8/270608.html

    网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联