feat(code-gen): 代码生成器

This commit is contained in:
15858193327
2020-11-03 02:16:17 +08:00
parent ca3161b0f2
commit 1dee2ae5f4
16 changed files with 357 additions and 119 deletions

View File

@@ -44,7 +44,7 @@ public class GeneratorApp {
private final SysGeneratorService sysGeneratorService;
/**
* 列出数据库中所有表
* ===========【 列出数据库中所有表 】===========
* <a href="http://localhost:8080/generator/list?page=1&limit=100">列出数据库中所有表</a>
*/
@ResponseBody
@@ -54,9 +54,9 @@ public class GeneratorApp {
}
/**
* 生成代码
* ===========【 生成代码 】===========
* web 中不需要主动关闭流
* <a href="http://localhost:8080/generator/code?tables=_all">所有表</a>
* <a href="http://localhost:8080/generator/code?tables=_all">所有表生成代码</a>
* @param tables 表名逗号分隔_all 全部
*/
@RequestMapping("code")

View File

@@ -29,7 +29,9 @@
</select>
<select id="queryColumns" resultType="map">
select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra from information_schema.columns
select column_name columnName, data_type dataType, column_comment columnComment, column_key columnKey, extra ,
CHARACTER_MAXIMUM_LENGTH charLength, COLUMN_TYPE columnType, IS_NULLABLE isNullable
from information_schema.columns
where table_name = #{tableName} and table_schema = (select database()) order by ordinal_position
</select>
</mapper>

View File

@@ -25,4 +25,15 @@ public class TableEntity {
//类名(第一个字母小写)sys_user => sysUser
private String lowClassName;
/**
* Controller 中生成校验权限注解Spring Security
*/
private boolean checkAuth;
/**
* 表类型:
* TREE(parent_id), CREATOR, MODIFIER, CREATOR_TIME, UPDATE_TIME, BATCH
*/
private List<String> types;
}

View File

@@ -33,15 +33,21 @@ public class GenUtils {
*/
public static List<String> getTemplates() {
List<String> templates = new ArrayList<String>();
templates.add("template/Controller.java.vm");
templates.add("template/JpaEntity.java.vm");
templates.add("template/JpaRepository.java.vm");
templates.add("template/Model.java.vm");
templates.add("template/DTO.java.vm");
templates.add("template/PO.java.vm");
templates.add("template/Mapper.java.vm");
templates.add("template/Mapper.xml.vm");
templates.add("template/Converter.java.vm");
templates.add("template/Service.java.vm");
templates.add("template/ServiceImpl.java.vm");
templates.add("template/Controller.java.vm");
templates.add("template/Mapper.java.vm");
templates.add("template/Mapper.xml.vm");
templates.add("template/index.html.vm");
@@ -131,6 +137,9 @@ public class GenUtils {
columnEntity.setDataType(column.get("dataType"));
columnEntity.setComments(column.get("columnComment"));
columnEntity.setExtra(column.get("extra"));
String len = String.valueOf(column.get("charLength"));
columnEntity.setLength("null".equalsIgnoreCase(len) ? 0 : Integer.parseInt(len));
columnEntity.setNotEmpty("NO".equalsIgnoreCase(column.get("isNullable")));
//列名转换成Java属性名
String attrName = columnToJava(columnEntity.getColumnName());
@@ -197,10 +206,22 @@ public class GenUtils {
return packagePath + "entity" + File.separator + className + "Entity.java";
}
if (template.contains("Model.java.vm")) {
return packagePath + "model" + File.separator + className + ".java";
}
if (template.contains("PO.java.vm")) {
return packagePath + "po" + File.separator + className + "PO.java";
}
if (template.contains("DTO.java.vm")) {
return packagePath + "dto" + File.separator + className + "DTO.java";
}
if (template.contains("Converter.java.vm")) {
return packagePath + "convert" + File.separator + className + "Converter.java";
}
if (template.contains("Mapper.java.vm")) {
return packagePath + "dao" + File.separator + className + "Mapper.java";
}

View File

@@ -3,17 +3,18 @@ package ${package}.${pkgName}.controller;
import java.util.Map;
import io.swagger.annotations.Api;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
#if(${checkAuth})
import org.springframework.security.access.prepost.PreAuthorize;
#end
import org.shoulder.core.dto.response.PageResult;
import org.shoulder.core.dto.response.RestResult;
import ${package}.${pkgName}.po.${className};
import ${package}.${pkgName}.convert.${className}Converter;
import ${package}.${pkgName}.dto.${className}DTO;
import ${package}.${pkgName}.model.${className};
import ${package}.${pkgName}.service.${className}Service;
/**
@@ -35,50 +36,80 @@ public class ${className}Controller {
* @param condition 查询条件
* @return 分页结果
*/
@RequestMapping("/list")
@RequestMapping("list")
#if(${checkAuth})
@PreAuthorize("hasAnyAuthority('${tableName}:${pathName}:list')")
#end
public PageResult list(@RequestParam Map<String, Object> condition){
PageResult pageResult = ${lowClassName}Service.findAll(condition);
return pageResult;
return ${lowClassName}Service.findAll(condition);
}
/**
* 保存单个
* @param ${lowClassName} 新增数据
* 保存单个,推荐使用幂等的 PUT 方法,体现接口幂等性。为了方便习惯,也开放了 POST
*
* @param ${lowClassName}DTO 新增数据
* @return 保存成功
*/
@RequestMapping("/save")
@RequestMapping(value = "save", method = {RequestMethod.PUT, RequestMethod.POST})
#if(${checkAuth})
@PreAuthorize("hasAnyAuthority('resource:sysroleuser:save')")
public RestResult save(@RequestBody ${className} ${lowClassName}){
${lowClassName}Service.save(${lowClassName});
#end
public RestResult save(@RequestBody ${className}DTO ${lowClassName}DTO){
${className} ${lowClassName} = ${className}Converter.CONVERTER.fromDTO(${lowClassName}DTO);
${lowClassName}Service.save(${lowClassName});
return RestResult.succeed();
return RestResult.success();
}
/**
* 单个修改
* @param ${lowClassName} 修改属性
*
* @param ${lowClassName}DTO 修改属性
* @return 修改成功
*/
@RequestMapping("/update")
@PostMapping("update")
#if(${checkAuth})
@PreAuthorize("hasAnyAuthority('resource:sysroleuser:update')")
public RestResult update(@RequestBody ${className} ${lowClassName}){
#end
public RestResult update(@RequestBody ${className}DTO ${lowClassName}DTO){
${className} ${lowClassName} = ${className}Converter.CONVERTER.fromDTO(${lowClassName}DTO);
${lowClassName}Service.update(${lowClassName});
return RestResult.succeed();
return RestResult.success();
}
/**
* 根据 id 删除单个
*
* @param ${pk.attributeName} id
* @return 删除成功
*/
@RequestMapping("/delete/{id}")
@RequestMapping(value = "delete/{id}", method = {RequestMethod.DELETE, RequestMethod.POST})
#if(${checkAuth})
@PreAuthorize("hasAnyAuthority('resource:sysroleuser:delete')")
#end
public RestResult delete(@PathVariable Long ${pk.attributeName}){
${lowClassName}Service.delete(${pk.attributeName});
return RestResult.succeed();
${lowClassName}Service.deleteById(${pk.attributeName});
return RestResult.success();
}
/**
* 根据 id 批量删除
*
* @param idList ids
* @return 删除成功
*/
@RequestMapping(value = "delete", method = {RequestMethod.DELETE, RequestMethod.POST})
#if(${checkAuth})
@PreAuthorize("hasAnyAuthority('resource:sysroleuser:delete')")
#end
public RestResult delete(List<Long> idList){
if(CollectionUtils.isEmpty(idList)){
return RestResult.success();
}
${lowClassName}Service.deleteByIds(idList);
return RestResult.success();
}
}

View File

@@ -0,0 +1,48 @@
package ${package}.${pkgName}.convert;
import ${package}.${pkgName}.model.${className};
import ${package}.${pkgName}.po.${className}PO;
import ${package}.${pkgName}.dto.${className}DTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* ${comments} 模型转换
*
* @author ${author}
* @date ${datetime}
*/
@Mapper(componentModel = "spring") // 置为 spring 默认作为 bean 注入 Spring 容器中
public interface ${className}Converter {
${className}Converter CONVERTER = Mappers.getMapper(${className}Converter.class);
/**
* DTO 转为标准模型,用于接口传入时
* @param dto 传输层对象
* @return 标准模型
*/
${className} fromDTO(${className}DTO dto);
/**
* PO 转为标准模型,用于存储中返回查询结果后
* @param po 持久层对象
* @return 标准模型
*/
${className} fromPO(${className}PO po);
/**
* 标准模型转为 DTO用于接口返回查询结果时转化为视图层对象
* @param model 标准模型
* @return 传输层对象
*/
${className}DTO toDTO(${className} model);
/**
* 标准模型转为 PO用于存储入库前
* @param model 标准模型
* @return 持久层对象
*/
${className}PO toPO(${className} model);
}

View File

@@ -8,6 +8,9 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Length;
#if(${hasBigDecimal})
import java.math.BigDecimal;
#end
@@ -15,12 +18,11 @@ import java.io.Serializable;
import java.util.Date;
/**
* ${comments}
* ${comments} 传输层定义 分为 paramadd / update、vo
*
* @author ${author}
* @date ${datetime}
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@@ -29,18 +31,17 @@ import java.util.Date;
@ApiModel(value = "${className}DTO", description = "${tableName}")
public class ${className}DTO implements Serializable {
private static final long serialVersionUID = 1L;
#foreach ($column in $columns)
/**
* $column.comments
*/
#if($column.notEmpty)
#if($column.notEmpty)
@NotNull(message = "$column.comments 不能为空")
#end
#if($column.length > 0)
#end
#if($column.length > 0)
@Length(max = $column.length, message = "$column.comments 长度不能超过 $column.length")
#end
#end
@ApiModelProperty(value = "$column.comments", notes = "$column.comments")
private $column.attrType $column.attributeName;
#end

View File

@@ -1,5 +1,8 @@
package ${package}.${pkgName}.entity;
import lombok.AllArgsConstructor;
import lombok.experimental.Accessors;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
@@ -20,18 +23,20 @@ import java.util.Date;
@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Builder
@Table// 唯一索引 (uniqueConstraints = {@UniqueConstraint(name = "uk_$pk.columnName", columnNames = {"$pk.columnName"})})
public class ${className}Entity implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
#foreach ($column in $columns)
#if($column.columnName == $pk.columnName)
#if($column.columnName == $pk.columnName)
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
#end
private $column.attrType $column.attributeName;
#end
private $column.attrType $column.attributeName;
#end
}

View File

@@ -5,6 +5,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import ${package}.${pkgName}.entity.${className}Entity;
import javax.transaction.Transactional;
import java.util.List;

View File

@@ -1,10 +1,11 @@
package ${package}.${pkgName}.dao;
import ${package}.${pkgName}.po.${className};
import ${package}.${pkgName}.po.${className}PO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
/**
* ${comments}
*
@@ -14,12 +15,44 @@ import java.util.Map;
@Mapper
public interface ${className}Mapper {
int insert(${className}PO ${lowClassName});
/**
* 插入单条记录
*
* @param ${lowClassName}PO 要添加的
* @return 数据库影响行数
*/
int insert(${className}PO ${lowClassName}PO);
int update(${className}PO ${lowClassName});
/**
* 更新单个
*
* @param ${lowClassName}PO 要更新的
* @return 数据库影响行数
*/
int update(${className}PO ${lowClassName}PO);
int delete(Long id);
/**
* 根据 id 删除单个
*
* @param id 要删除的数据 id
* @return 数据库影响行数
*/
int deleteById(Long id);
/**
* 根据 ids 批量删除
*
* @param ids 要删除的数据 id
* @return 数据库影响行数
*/
int deleteByIds(List<Long> ids);
/**
* 分页查询
*
* @param params 查询条件
* @return 查询结果
*/
List<${className}PO> findAll(Map<String, Object> params);
}

View File

@@ -10,42 +10,64 @@
#end
</resultMap>
#if(${baseColumnList})
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
${pk}
#foreach($column in $columns)
, ${column.columnName}
#end
</sql>
#end
<insert id="save">
insert into ${tableName}(
#foreach($column in $columns)
#if( $!{velocityCount} == $!{columns.size()})
#foreach($column in $columns)
#if( $!{velocityCount} == $!{columns.size()})
${column.columnName}
#else
#else
${column.columnName},
#end
#end
#end
#end
) values (
#foreach($column in $columns)
#if( $!{velocityCount} == $!{columns.size()})
#foreach($column in $columns)
#if( $!{velocityCount} == $!{columns.size()})
#{${column.columnName}}
#else
#else
#{ ${column.columnName}},
#end
#end
#end
#end
)
</insert>
<update id="update">
update ${tableName}
<set>
#foreach($column in $columns)
#foreach($column in $columns)
<if test="${column.columnName} != null">
${column.columnName} = #{${column.columnName}},
</if>
#end
#end
</set>
where id = #{id}
</update>
<!-- 根据传入 id 删除单个 -->
<delete id="delete" parameterType="long" flushCache="true">
delete from ${tableName} where id = #{id}
</delete>
<!-- 根据传入 id 批量删除 -->
<delete id="deleteByIds" parameterType="java.util.List" flushCache="true">
delete from ${tableName}
<foreach collection="list" item="ids" index="index" separator="or" open="(" close=")" >
id in
<foreach collection="ids" item="id" index="index" open="(" close=")" separator="," >
#{id}
</foreach>
</foreach>
</delete>
<select id="findAll" resultType="${package}.${pkgName}.po.${className}PO">
select * from ${tableName} t
<include refid="where"/>
@@ -54,11 +76,11 @@
<sql id="where">
<where>
#foreach($column in $columns)
<if test="searchKey != null and searchKey != '' and searchKey=='${column.columnName}'">
and t.${column.columnName} like concat('%', #{searchValue}, '%')
</if>
#end
#foreach($column in $columns)
<if test="searchKey != null and searchKey != '' and searchKey=='${column.columnName}'">
and t.${column.columnName} like concat('%', #{searchValue}, '%')
</if>
#end
</where>
</sql>

View File

@@ -1,8 +1,8 @@
package ${package}.${pkgName}.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.experimental.Accessors;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -18,21 +18,18 @@ import java.util.Date;
* @author ${author}
* @date ${datetime}
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Builder
public class ${className} implements Serializable {
private static final long serialVersionUID = 1L;
#foreach ($column in $columns)
/**
* $column.columnName $column.comments
*/
#if($column.columnName == $pk.columnName)
@TableId(type = IdType.AUTO)
#end
@TableField("$column.columnName")
private $column.attrType $column.attributeName;
#end

View File

@@ -3,6 +3,11 @@ package ${package}.${pkgName}.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.experimental.Accessors;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -18,20 +23,22 @@ import java.util.Date;
* @author ${author}
* @date ${datetime}
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Builder
@TableName("${tableName}")
public class ${className}PO implements Serializable {
private static final long serialVersionUID = 1L;
#foreach ($column in $columns)
/**
* $column.columnName $column.comments
*/
#if($column.columnName == $pk.columnName)
#if($column.columnName == $pk.columnName)
@TableId(type = IdType.AUTO)
#end
#end
@TableField("$column.columnName")
private $column.attrType $column.attributeName;
#end

View File

@@ -1,9 +1,11 @@
package ${package}.${pkgName}.service;
import ${package}.${pkgName}.po.${className};
import ${package}.${pkgName}.dto.${className}DTO;
import ${package}.${pkgName}.model.${className};
import ${package}.${pkgName}.po.${className}PO;
import org.shoulder.core.dto.response.PageResult;
import java.util.List;
import java.util.Map;
/**
@@ -13,29 +15,44 @@ import java.util.Map;
* @date ${datetime}
*/
public interface ${className}Service {
/**
* 添加
* @param ${lowClassName}
* 添加单个
*
* @param ${lowClassName} 要添加的
* @return 数据库影响行数
*/
int save(${className} ${lowClassName});
/**
* 修改
* @param ${lowClassName}
* 修改单个
*
* @param ${lowClassName} 修改
* @return 数据库影响行数
*/
int update(${className}PO ${lowClassName});
int update(${className} ${lowClassName});
/**
* 删除
* @param id
* 根据 id 删除单个
*
* @param id 要删除的数据 id
* @return 数据库影响行数
*/
int delete(Long id);
int deleteById(Long id);
/**
* 列表
* @param params
* @return
* 根据 ids 批量删除
*
* @param idList 要删除的数据 id
* @return 数据库影响行数
*/
int deleteByIds(List<Long> idList);
/**
* 分页查询
*
* @param params 条件
* @return 查询结果
*/
PageResult<${className}PO> findAll(Map<String, Object> params);

View File

@@ -1,5 +1,7 @@
package ${package}.${pkgName}.service.impl;
import ${package}.${pkgName}.convert.${className}Converter;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.shoulder.core.dto.response.PageResult;
@@ -8,59 +10,73 @@ import com.github.pagehelper.PageInfo;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.collections4.MapUtils;
import ${package}.${pkgName}.po.${className};
import org.shoulder.core.dto.response.PageResult;
import ${package}.${pkgName}.dto.${className}DTO;
import ${package}.${pkgName}.dao.${className}Mapper;
import ${package}.${pkgName}.model.${className};
import ${package}.${pkgName}.po.${className}PO;
import ${package}.${pkgName}.service.${className}Service;
/**
* ${className} 业务层
*
* @author ${author}
* @date ${datetime}
*/
@Service
public class ${className}ServiceImpl implements ${className}Service {
@Autowired
private ${className}Mapper ${lowClassName}Mapper;
/**
* 添加
* @param ${lowClassName}
*/
@Override
public int save(${className} ${lowClassName}){
return ${lowClassName}Mapper.insert(${lowClassName});
${className}PO ${lowClassName}PO = ${className}Converter.CONVERTER.toPO(${lowClassName});
return ${lowClassName}Mapper.insert(${lowClassName}PO);
}
/**
* 修改
* @param ${lowClassName}
*/
@Override
public int update(${className} ${lowClassName}){
return ${lowClassName}Mapper.update(${lowClassName});
${className}PO ${lowClassName}PO = ${className}Converter.CONVERTER.toPO(${lowClassName});
return ${lowClassName}Mapper.update(${lowClassName}PO);
}
@Override
public int deleteById(Long id) {
return ${lowClassName}Mapper.deleteById(id);
}
@Override
public int deleteByIds(List<Long> idList) {
return ${lowClassName}Mapper.deleteByIds(idList);
}
/**
* 删除
* @param id 主键
*/
public int delete(Long id){
return ${lowClassName}Mapper.delete(id);
}
/**
* 列表
* @param params
* @return
*/
@Override
public PageResult<${className}> findAll(Map<String, Object> params){
//设置分页信息,分别是当前页数和每页显示的记录数
// 设置当前页数和每页显示的最大记录数
if (MapUtils.getInteger(params, "page")!=null && MapUtils.getInteger(params, "limit")!=null) {
PageHelper.startPage(MapUtils.getInteger(params, "page"), MapUtils.getInteger(params, "limit"), true);
}
List<${className}> list = ${lowClassName}Mapper.findAll(params);
PageInfo<${className}> pageInfo = new PageInfo(list);
List<${className}PO> poList = ${lowClassName}Mapper.findAll(params);
// todo 如果为空则返回空
if(CollectionUtils.isEmpty(poList)) {
throw new RuntimeException("return empty...");
//return PageResult.empty(0);
}
List<${className}> list = poList.stream()
.map(${className}Converter.CONVERTER::fromPO)
.collect(Collectors.toList());
PageInfo<${className}> pageInfo = new PageInfo<>(list);
return PageResult.<${className}>builder().data(pageInfo.getList()).code(0).count(pageInfo.getTotal()).build();
return PageResult.PageResultBuilder.aPageResult()
.list(pageInfo.getList())
.totalPageNum((int) pageInfo.getTotal())
.build();
}
}

View File

@@ -16,6 +16,32 @@
<groupId>cn.itlym.platform</groupId>
<artifactId>system-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.6.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>3.4.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
<scope>compile</scope>
</dependency>
</dependencies>