自定义代码生成器
前提
- 这是在开发自己写的数据采集项目中,根据实际需要生成期望模板的生成器,支持多表,支持任意模型的插拔(如:只生成Controller和Service,其他模型不要)
- 基于SpringBoot项目,配置文件为yml类型
- 使用MySQL数据源
- 使用Mybatis-Plus+Spring JPA,所以会有JPA的注解存在
结果展示
流程
文件结构
1. 项目上配置好数据源信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/自己的数据库?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&generateSimpleParameterMetadata=true&nullCatalogMeansCurrent=true
username: 数据库账号
password: 数据库密码
2. 基本信息properites中做好配置
# 表名,逗号分隔,大小写不敏感
tableName=SINA_ASHARES_QUOTES
# 工程名
projectDirectory=betrice-data-acquisition
# 工程下生成的代码的父目录,程序会拼接在path之后
secondaryModule=finance
# 工程下生成的位置
path=src\\main\\java\\com\\devilvan\\betrice\\
# 作者
author=Evad.Wu
# 父目录下的单位目录
packageName=com.devilvan.betrice
3. BetriceCodeGenerator中选择好生成的模型
4. 在BetriceCodeGenerator中运行
代码
BetriceCodeGenerator
public class BetriceCodeGenerator {
private static final String SUFFIX_JAVA = ".java";
private static final String SUFFIX_XML = ".xml";
private static Map<String, Object> basicMap;
static {
basicMap = loadBasic();
}
public static void main(String[] args) {
List<String> tableList = Optional.of(Arrays.asList(String.valueOf(basicMap.get("tableName")).toUpperCase(Locale.ROOT).split(",")))
.filter(f -> f.size() > 0)
.orElseThrow(() -> new BetriceException("待生成的数据库表名不能为空!"));
BetriceDataSourceTbDto betriceDataSourceTbDto = assemDataSourceTbDto(tableList);
List<BetriceDbDto> dbDtoList = printTableStructure(betriceDataSourceTbDto);
generate(dbDtoList);
}
/**
* 生成模型文件开关
* @param dbDtoList 待生成代码的数据表信息
*/
private static void generate(List<BetriceDbDto> dbDtoList) {
for (BetriceDbDto dbDto : dbDtoList) {
generateVo(dbDto);
generatePo(dbDto);
generateDto(dbDto);
generateController(dbDto);
generateService(dbDto);
generateServiceImpl(dbDto);
generateRepository(dbDto);
generateMapper(dbDto);
generateMapperXml(dbDto);
}
}
/**
* 初始化方法,加载basic.properties 获取如表名、包名、作者等基础信息
* @return 解析properties的key-value后封装的Map
*/
private static Map<String, Object> loadBasic() {
HashMap<String, Object> map = new HashMap<>();
Properties pro = new Properties();
try {
pro.load(new FileReader("betrice-common\\betrice-common-codegen\\src\\main\\resources\\basic.properties"));
} catch (IOException e) {
e.printStackTrace();
}
String tableName = String.valueOf(pro.get("tableName"));
String projectDirectory = String.valueOf(pro.get("projectDirectory"));
String secondaryModule = String.valueOf(pro.get("secondaryModule"));
String path = pro.get("path") + secondaryModule + "\\";
String author = String.valueOf(pro.get("author"));
String packageName = pro.get("packageName") + "." + secondaryModule;
map.put("tableName", tableName);
map.put("projectDirectory", projectDirectory);
map.put("secondaryModule", secondaryModule);
map.put("path", path);
map.put("author", author);
map.put("packageName", packageName);
map.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
return map;
}
/**
* springboot项目,获取application.yml中数据源信息
* @param tableList 需要生成的表名
* @return 数据源信息
*/
private static BetriceDataSourceTbDto assemDataSourceTbDto(List<String> tableList) {
ClassPathResource resource = new ClassPathResource("application-parent.yml");
YamlPropertiesFactoryBean ymlFactory = new YamlPropertiesFactoryBean();
ymlFactory.setResources(resource);
Properties pro = Optional.ofNullable(ymlFactory.getObject()).orElseThrow(() -> new BetriceException("获取配置失败!"));
String driver = String.valueOf(pro.get("spring.datasource.driver-class-name"));
String url = String.valueOf(pro.get("spring.datasource.url"));
String uname = String.valueOf(pro.get("spring.datasource.username"));
String pwd = String.valueOf(pro.get("spring.datasource.password"));
BetriceDataSourceTbDto tbDto = new BetriceDataSourceTbDto(driver, url, uname, pwd);
tbDto.setTableList(tableList);
return tbDto;
}
/**
* 根据数据源信息获取到对应数据表的字段
* @param tbDto 数据源信息
* @return 数据表、字段信息
*/
private static List<BetriceDbDto> printTableStructure(BetriceDataSourceTbDto tbDto) {
List<BetriceDbDto> dbDtoList = new ArrayList<>();
// 每张表默认的审计字段,在生成的Model中只显示业务字段,而通过继承一个BasePo管理这些审计字段
List<String> auditList = List.of("ID", "CREATOR", "CREATE_TIME", "MODIFIER", "MODIFY_TIME", "LOGIC_DEL", "REC_VER");
try {
// JDBC的过程了,加载MySQL驱动-连接-执行-结果集
Class.forName(tbDto.getDriver());
Connection connection = DriverManager.getConnection(tbDto.getUrl(), tbDto.getUname(), tbDto.getPwd());
DatabaseMetaData metaData = connection.getMetaData();
// 获取所有表
List<String> tableList = tbDto.getTableList();
for (String table : tableList) {
// 根据表名获取数据表的元数据
ResultSet tableResultSet = metaData.getTables(null, null, table, new String[]{"TABLE"});
while (tableResultSet.next()) {
String tableName = tableResultSet.getString("TABLE_NAME").toUpperCase(Locale.ROOT);
// 将表名转化成类名
String className = tableName2className(table);
System.out.println("tableName: " + tableName);
// 获取数据表的描述-comment
String comment = tableResultSet.getString("REMARKS");
if (StrUtil.isNotEmpty(comment)) {
throw new BetriceException("表描述不能为空!");
}
System.out.println("comment: " + comment);
BetriceDbDto dbDto = new BetriceDbDto(table, className, comment);
// 获取表字段结构
ResultSet columnResultSet = metaData.getColumns(null, "%", tableName, "%");
List<BetriceCgField> betriceCgFieldList = new ArrayList<>();
// 遍历表中每个字段
while (columnResultSet.next()) {
String columnName = columnResultSet.getString("COLUMN_NAME");
if (auditList.contains(columnName)) {
continue;
}
String fieldName = columnName2Field(columnName);
String columnType = columnResultSet.getString("TYPE_NAME");
String javaType = columnType2JavaType(columnType);
int datasize = columnResultSet.getInt("COLUMN_SIZE");
int digits = columnResultSet.getInt("DECIMAL_DIGITS");
// false-不可为空
boolean nullable = columnResultSet.getInt("NULLABLE") == 1;
String remarks = columnResultSet.getString("REMARKS");
BetriceCgField betriceCgField = new BetriceCgField(columnName, fieldName, columnType, javaType, datasize, digits, nullable, remarks);
betriceCgFieldList.add(betriceCgField);
}
dbDto.setFieldList(betriceCgFieldList);
dbDtoList.add(dbDto);
System.out.println("=================================");
}
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return dbDtoList;
}
/**
* 表名转类名
* @param table 表名
* @return 类名
*/
private static String tableName2className(String table) {
StringBuilder sb = new StringBuilder();
String[] split = table.toLowerCase(Locale.ROOT).split("_");
for (String s : split) {
if (s.length() == 1) {
sb.append(s.toUpperCase(Locale.ROOT));
} else {
sb.append(s.substring(0, 1).toUpperCase(Locale.ROOT)).append(s.substring(1));
}
}
return sb.toString();
}
/**
* DB字段类型转Java类型
* @param columnType 字段类型
* @return Java类型
*/
private static String columnType2JavaType(String columnType) {
if ("VARCHAR".equals(columnType) || "CHAR".equals(columnType) || "TINYTEXT".equals(columnType) ||
"MEDIUNTEXT".equals(columnType) || "TEXT".equals(columnType) || "LONGTEXT".equals(columnType)) {
return "String";
} else if ("DATE".equals(columnType) || "TIME".equals(columnType) || "DATETIME".equals(columnType) ||
"TIMESTAMP".equals(columnType) || "YEAR".equals(columnType)) {
return "Date";
} else if ("TINYINT".equals(columnType) || "SMALLINT".equals(columnType) || "MEDIUMINT".equals(columnType) ||
"INT".equals(columnType)) {
return "Integer";
} else if ("BIGINT".equals(columnType)) {
return "Long";
} else if ("FLOAT".equals(columnType)) {
return "Float";
} else if ("DOUBLE".equals(columnType)) {
return "Double";
} else if ("DECIMAL".equals(columnType)) {
return "BigDecimal";
}
return "String";
}
/**
* DB字段名转Java属性名
* @param columnName DB字段名
* @return Java属性名
*/
private static String columnName2Field(String columnName) {
StringBuilder sb = new StringBuilder();
String[] split = columnName.toLowerCase(Locale.ROOT).split("_");
for (int i = 0; i < split.length; i++) {
if (i == 0) {
sb.append(split[0]);
} else if (split[i].length() == 1) {
sb.append(split[i].toUpperCase(Locale.ROOT));
} else {
sb.append(split[i].substring(0, 1).toUpperCase(Locale.ROOT)).append(split[i].substring(1));
}
}
return sb.toString();
}
/**
* 根据freemarker模板,生成文件到对应目录下
* @param templateName 模板名称
* @param file 待生成的文件名
* @param basicMap 待生成的文件中的基本信息
*/
private static void generateFileByTemplate(String templateName, File file, Map<String, Object> basicMap) {
try {
Template template = FreemarkerTemplateUtil.getTemplate(templateName);
FileOutputStream fos = new FileOutputStream(file);
Writer out = new BufferedWriter(new OutputStreamWriter(fos, StandardCharsets.UTF_8), 10240);
template.process(basicMap, out);
FreemarkerTemplateUtil.clearCache();
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
}
private static void generateVo(BetriceDbDto dbDto) {
String parentPath = basicMap.get("projectDirectory") + "\\" + basicMap.get("path") + "\\vo\\";
String templateName = "vo.ftl";
File mapperFile = new File(parentPath);
if (!mapperFile.exists()) {
mapperFile.mkdirs();
}
File path = new File(parentPath + dbDto.getClassName() + "Vo" + SUFFIX_JAVA);
Map<String, Object> map = new HashMap<>(basicMap);
map.put("dbDto", dbDto);
generateFileByTemplate(templateName, path, map);
}
private static void generatePo(BetriceDbDto dbDto) {
String parentPath = basicMap.get("projectDirectory") + "\\" + basicMap.get("path") + "\\po\\";
String templateName = "po.ftl";
File mapperFile = new File(parentPath);
if (!mapperFile.exists()) {
mapperFile.mkdirs();
}
File path = new File(parentPath + dbDto.getClassName() + "Po" + SUFFIX_JAVA);
Map<String, Object> map = new HashMap<>(basicMap);
map.put("dbDto", dbDto);
generateFileByTemplate(templateName, path, map);
}
private static void generateController(BetriceDbDto dbDto) {
String parentPath = basicMap.get("projectDirectory") + "\\" + basicMap.get("path") + "\\controller\\";
String templateName = "controller.ftl";
File mapperFile = new File(parentPath);
if (!mapperFile.exists()) {
mapperFile.mkdirs();
}
File path = new File(parentPath + dbDto.getClassName() + "Controller" + SUFFIX_JAVA);
Map<String, Object> map = new HashMap<>(basicMap);
map.put("dbDto", dbDto);
generateFileByTemplate(templateName, path, map);
}
private static void generateDto(BetriceDbDto dbDto) {
String parentPath = basicMap.get("projectDirectory") + "\\" + basicMap.get("path") + "\\dto\\";
String templateName = "dto.ftl";
File mapperFile = new File(parentPath);
if (!mapperFile.exists()) {
mapperFile.mkdirs();
}
File path = new File(parentPath + dbDto.getClassName() + "Dto" + SUFFIX_JAVA);
Map<String, Object> map = new HashMap<>(basicMap);
map.put("dbDto", dbDto);
generateFileByTemplate(templateName, path, map);
}
private static void generateService(BetriceDbDto dbDto) {
String parentPath = basicMap.get("projectDirectory") + "\\" + basicMap.get("path") + "\\service\\";
String templateName = "service.ftl";
File mapperFile = new File(parentPath);
if (!mapperFile.exists()) {
mapperFile.mkdirs();
}
File path = new File(parentPath + dbDto.getClassName() + "Service" + SUFFIX_JAVA);
Map<String, Object> map = new HashMap<>(basicMap);
map.put("dbDto", dbDto);
generateFileByTemplate(templateName, path, map);
}
private static void generateServiceImpl(BetriceDbDto dbDto) {
String parentpPath = basicMap.get("projectDirectory") + "\\" + basicMap.get("path") + "\\service\\impl\\";
String templateName = "serviceImpl.ftl";
File mapperFile = new File(parentpPath);
if (!mapperFile.exists()) {
mapperFile.mkdirs();
}
File path = new File(parentpPath + dbDto.getClassName() + "ServiceImpl" + SUFFIX_JAVA);
Map<String, Object> map = new HashMap<>(basicMap);
map.put("dbDto", dbDto);
generateFileByTemplate(templateName, path, map);
}
private static void generateMapper(BetriceDbDto dbDto) {
String parentPath = basicMap.get("projectDirectory") + "\\" + basicMap.get("path") + "\\mapper\\";
String templateName = "mapper.ftl";
File mapperFile = new File(parentPath);
if (!mapperFile.exists()) {
mapperFile.mkdirs();
}
File path = new File(parentPath + dbDto.getClassName() + "Mapper" + SUFFIX_JAVA);
Map<String, Object> map = new HashMap<>(basicMap);
map.put("dbDto", dbDto);
generateFileByTemplate(templateName, path, map);
}
private static void generateMapperXml(BetriceDbDto dbDto) {
String parentPath = basicMap.get("projectDirectory") + "\\src\\main\\resources\\mapper\\";
String templateName = "mapperXml.ftl";
File mapperFile = new File(parentPath);
if (!mapperFile.exists()) {
mapperFile.mkdirs();
}
File path = new File(parentPath + dbDto.getClassName() + "Mapper" + SUFFIX_XML);
Map<String, Object> map = new HashMap<>(basicMap);
map.put("dbDto", dbDto);
generateFileByTemplate(templateName, path, map);
}
private static void generateRepository(BetriceDbDto dbDto) {
String parentPath = basicMap.get("projectDirectory") + "\\" + basicMap.get("path") + "\\repository\\";
String templateName = "repository.ftl";
File mapperFile = new File(parentPath);
if (!mapperFile.exists()) {
mapperFile.mkdirs();
}
File path = new File(parentPath + dbDto.getClassName() + "Repository" + SUFFIX_JAVA);
Map<String, Object> map = new HashMap<>(basicMap);
map.put("dbDto", dbDto);
generateFileByTemplate(templateName, path, map);
}
}
BetriceDbDto
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "数据库表信息 数据传输对象")
public class BetriceDbDto implements Serializable {
@Serial
private static final long serialVersionUID = -179434144799166939L;
@ApiModelProperty(value = "表名")
private String tableName;
@ApiModelProperty(value = "类名")
private String className;
@ApiModelProperty(value = "表描述")
private String comment;
@ApiModelProperty(value = "字段值对象")
private List<BetriceCgField> fieldList;
public BetriceDbDto(String tableName, String className, String comment) {
this.tableName = tableName;
this.className = className;
this.comment = comment;
}
}
BetriceDataSourceTbDto
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "数据源信息 数据传输对象")
public class BetriceDataSourceTbDto extends BetriceDataSourceDto{
@ApiModelProperty(value = "需要生成的表名")
private List<String> tableList;
public BetriceDataSourceTbDto(String driver, String url, String uname, String pwd) {
super(driver, url, uname, pwd);
}
}
BetriceDataSourceDto
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "数据源信息 数据传输对象")
public class BetriceDataSourceDto{
@ApiModelProperty(value = "数据库驱动")
private String driver;
@ApiModelProperty(value = "数据库URL")
private String url;
@ApiModelProperty(value = "账号")
private String uname;
@ApiModelProperty(value = "密码")
private String pwd;
}
BetriceCgField
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "表字段及转换相关字段")
public class BetriceCgField {
@ApiModelProperty(value = "字段名称")
private String columnName;
@ApiModelProperty(value = "字段名称转换的属性名称")
private String fieldName;
@ApiModelProperty(value = "字段类型")
private String columnType;
@ApiModelProperty(value = "Java类型")
private String javaType;
@ApiModelProperty(value = "字段长度")
private Integer dataSize;
@ApiModelProperty(value = "精度")
private Integer digits;
@ApiModelProperty(value = "是否为空")
private Boolean nullable;
@ApiModelProperty(value = "字段描述")
private String remark;
}
FreemarkerTemplateUtil-Freemarker生成模板工具类
public class FreemarkerTemplateUtil {
private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_31);
static {
//这里比较重要,用来指定加载模板所在的路径
CONFIGURATION.setTemplateLoader(new ClassTemplateLoader(FreemarkerTemplateUtil.class,
"/static/ftl"));
CONFIGURATION.setDefaultEncoding("UTF-8");
CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
CONFIGURATION.setCacheStorage(NullCacheStorage.INSTANCE);
}
public static Template getTemplate(String templateName) throws IOException {
return CONFIGURATION.getTemplate(templateName);
}
public static void clearCache() {
CONFIGURATION.clearTemplateCache();
}
}
模型模板ftl文件
controller.ftl
package ${packageName}.controller;
import ${packageName}.po.${dbDto.className}Po;
import ${packageName}.service.${dbDto.className}Service;
import com.devilvan.betrice.common.BetriceResultVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @author ${author}
* @Description ${dbDto.comment} 控制器
* @date ${date}
*/
@RestController
@RequestMapping(value = "${dbDto.className?uncap_first}Controller")
@Api(tags = "${dbDto.comment} 控制器")
public class ${dbDto.className}Controller {
@Resource(name = "${dbDto.className?uncap_first}ServiceImpl")
private ${dbDto.className}Service ${dbDto.className?uncap_first}Service;
/**
* 总请求控制器
*
* @return 形式返回
*/
@ApiOperation(value = "总请求控制器")
@RequestMapping(value = "do${dbDto.className}")
public BetriceResultVo<${dbDto.className}Po> do${dbDto.className}() {
BetriceResultVo<${dbDto.className}Po> betriceResultVo = new BetriceResultVo<>();
return betriceResultVo;
}
/**
* 采集报文控制器
*
* @return 形式返回
*/
@ApiOperation(value = "采集报文控制器")
@RequestMapping(value = "do${dbDto.className}Crawler")
public BetriceResultVo<${dbDto.className}Po> do${dbDto.className}Crawler() {
BetriceResultVo<${dbDto.className}Po> betriceResultVo = new BetriceResultVo<>();
return betriceResultVo;
}
/**
* 解析报文控制器
*
* @param request 报文
* @return 形式返回
*/
@ApiOperation(value = "解析报文控制器")
@RequestMapping(value = "do${dbDto.className}Request")
public BetriceResultVo<${dbDto.className}Po> do${dbDto.className}Request(@RequestBody String request) {
BetriceResultVo<${dbDto.className}Po> betriceResultVo = new BetriceResultVo<>();
return betriceResultVo;
}
}
dto.ftl
package ${packageName}.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import java.util.Date;
/**
* @author ${author}
* @Description ${dbDto.comment} 数据传输对象
* @date ${date}
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "${dbDto.comment} 数据传输对象")
public class ${dbDto.className}Dto {
<#if dbDto.fieldList ??>
<#list dbDto.fieldList as field>
@ApiModelProperty(value = "${field.remark ! ''}")
private <#if field.columnType == 'BIT'>Boolean<#else>${field.javaType}</#if> ${field.fieldName};
</#list>
</#if>
}
mapper.ftl
package ${packageName}.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import ${packageName}.po.${dbDto.className}Po;
import org.apache.ibatis.annotations.Mapper;
/**
* @author ${author}
* @Description ${dbDto.comment} 持久层
* @date ${date}
*/
@Mapper
public interface ${dbDto.className}Mapper extends BaseMapper<${dbDto.className}Po> {
}
mapperXml.ftl
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="${packageName}.mapper.${dbDto.className}Mapper">
</mapper>
po.ftl
package ${packageName}.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.devilvan.betrice.common.BasePo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.hibernate.annotations.DynamicInsert;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author ${author}
* @Description ${dbDto.comment} 映射
* @date ${date}
*/
@Setter
@Getter
@ToString
@NoArgsConstructor
@Accessors(chain = true)
@TableName(value = "${dbDto.tableName}")
@Entity
@Table(name = "${dbDto.tableName}")
@DynamicInsert
@EntityListeners(AuditingEntityListener.class)
@ApiModel(value = "${dbDto.comment} 映射")
public class ${dbDto.className}Po extends BasePo implements Serializable {
<#if dbDto.fieldList ??>
<#list dbDto.fieldList as field>
@ApiModelProperty(value = "${field.remark ! ''}")
@TableField(value = "${field.columnName}")
@Column(name = "${field.columnName}", columnDefinition = "<#if field.javaType != 'Date'>${field.columnType}(${field.dataSize}) <#else>${field.columnType} </#if><#if field.nullable = false>NOT NULL </#if>COMMENT '${field.remark}'")
private <#if field.columnType == 'BIT'>Boolean<#else>${field.javaType}</#if> ${field.fieldName};
</#list>
</#if>
}
repository.ftl
package ${packageName}.repository;
import ${packageName}.po.${dbDto.className}Po;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author ${author}
* @Description ${dbDto.comment} 持久层
* @date ${date}
*/
@Repository
public interface ${dbDto.className}Repository extends JpaRepository<${dbDto.className}Po, Long> {
}
service.ftl
package ${packageName}.service;
import ${packageName}.dto.${dbDto.className}Dto;
import ${packageName}.po.${dbDto.className}Po;
import java.util.List;
/**
* @author ${author}
* @Description ${dbDto.comment} 业务逻辑接口
* @date ${date}
*/
public interface ${dbDto.className}Service {
/**
* 保存
*
* @param ${dbDto.className?uncap_first}Dto 控制层处理后的数据传输对象
* @return 保存回调对象
*/
${dbDto.className}Po saveUpdate(${dbDto.className}Dto ${dbDto.className?uncap_first}Dto);
/**
* 批量保存
*
* @param list 控制层处理后的数据传输对象集合
* @return 保存回调对象
*/
List<${dbDto.className}Po> saveUpdateBatch(List<${dbDto.className}Dto> list);
}
serviceImpl.ftl
package ${packageName}.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ${packageName}.dto.${dbDto.className}Dto;
import ${packageName}.po.${dbDto.className}Po;
import ${packageName}.service.${dbDto.className}Service;
import ${packageName}.mapper.${dbDto.className}Mapper;
import ${packageName}.repository.${dbDto.className}Repository;
import org.springframework.stereotype.Service;
import com.devilvan.betrice.util.CopyUtil;
import javax.annotation.Resource;
import java.util.List;
/**
* @author ${author}
* @Description ${dbDto.comment} 业务逻辑类
* @date ${date}
*/
@Service
public class ${dbDto.className}ServiceImpl extends ServiceImpl<${dbDto.className}Mapper, ${dbDto.className}Po> implements ${dbDto.className}Service {
@Resource(name = "${dbDto.className?uncap_first}Repository")
private ${dbDto.className}Repository ${dbDto.className?uncap_first}Repository;
@Override
public ${dbDto.className}Po saveUpdate(${dbDto.className}Dto ${dbDto.className?uncap_first}Dto) {
${dbDto.className}Po ${dbDto.className?uncap_first}Po = new ${dbDto.className}Po();
CopyUtil.fullCopy(${dbDto.className?uncap_first}Dto, ${dbDto.className?uncap_first}Po);
return ${dbDto.className?uncap_first}Repository.saveAndFlush(${dbDto.className?uncap_first}Po);
}
@Override
public List<${dbDto.className}Po> saveUpdateBatch(List<${dbDto.className}Dto> list) {
List<${dbDto.className}Po> ${dbDto.className?uncap_first}PoList = CopyUtil.fullCopyCollections(list, ${dbDto.className}Po.class);
return ${dbDto.className?uncap_first}Repository.saveAllAndFlush(${dbDto.className?uncap_first}PoList);
}
}
vo.ftl
package ${packageName}.vo;
import com.alibaba.fastjson.annotation.JSONField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author ${author}
* @Description ${dbDto.comment} 值对象
* @date ${date}
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "${dbDto.comment} 值对象")
public class ${dbDto.className}Vo {
<#if dbDto.fieldList ??>
<#list dbDto.fieldList as field>
@ApiModelProperty(value = "${field.remark ! ''}")
@JSONField(alternateNames = {"${field.fieldName}"})
private <#if field.columnType == 'BIT'>Boolean<#else>${field.javaType}</#if> ${field.fieldName};
</#list>
</#if>
}