initial commit
This commit is contained in:
commit
56df0d7bb4
|
@ -0,0 +1,44 @@
|
|||
######################################################################
|
||||
# Build Tools
|
||||
|
||||
.gradle
|
||||
/build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
######################################################################
|
||||
# IDE
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/*
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
||||
|
||||
######################################################################
|
||||
# Others
|
||||
*.log
|
||||
*.xml.versionsBackup
|
||||
*.swp
|
||||
|
||||
!*/build/*.java
|
||||
!*/build/*.html
|
||||
!*/build/*.xml
|
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.msph.cls</groupId>
|
||||
<artifactId>cls-common</artifactId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.msph.cls.generate.code</groupId>
|
||||
<artifactId>generate-code</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<version>${jdbc.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fast.json.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>${freemarker.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-generator</artifactId>
|
||||
<version>${mybatis-plus-generator.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven.compiler.version}</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<!-- 配置远程发布到私服,mvn deploy -->
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>nexus-releases</id>
|
||||
<url>http://172.30.1.44:8081/nexus/content/repositories/releases/</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>snapshots</id>
|
||||
<url>http://172.30.1.44:8081/nexus/content/repositories/snapshots/</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
</project>
|
|
@ -0,0 +1,139 @@
|
|||
package com.msph.cls.generate;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 代码生成配置类
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
public class GeneratorConfig {
|
||||
/**
|
||||
* 包结构类型,包含layer-module和module-layer两种类型
|
||||
* layer-module:先分层然后是模块(默认)
|
||||
* 示例:生成用户模块代码,包命名则为/service/user/
|
||||
* module-layer:先模块然后分层
|
||||
* 示例:生成用户模块代码,包命名则为/user/service/
|
||||
*/
|
||||
public static final String LAYER_MODULE = "layer-module";
|
||||
|
||||
/**
|
||||
* 作者
|
||||
*/
|
||||
private String author;
|
||||
|
||||
/**
|
||||
* 项目名称(同项目目录文件名保持一致)
|
||||
*/
|
||||
private String projectName;
|
||||
|
||||
/**
|
||||
* 分层名称(同分层模块目录文件名保持一致)
|
||||
*/
|
||||
private String layerName;
|
||||
|
||||
/**
|
||||
* 项目绝对路径
|
||||
*/
|
||||
private String projectPath;
|
||||
|
||||
/**
|
||||
* 是否覆盖文件
|
||||
*/
|
||||
private boolean fileOverride = false;
|
||||
|
||||
/**
|
||||
* 数据库驱动
|
||||
*/
|
||||
private String dbDriver = "com.mysql.jdbc.Driver";
|
||||
|
||||
/**
|
||||
* 数据库url
|
||||
*/
|
||||
private String dbUrl;
|
||||
|
||||
/**
|
||||
* 应用名称
|
||||
*/
|
||||
private String appName;
|
||||
|
||||
/**
|
||||
* 应用URL前缀
|
||||
*/
|
||||
private String appContextPath;
|
||||
|
||||
/**
|
||||
* 数据库用户
|
||||
*/
|
||||
private String dbUsername;
|
||||
|
||||
/**
|
||||
* 数据库密码
|
||||
*/
|
||||
private String dbPassword;
|
||||
|
||||
/**
|
||||
* 包结构类型: layer-module, module-layer
|
||||
*/
|
||||
private String packageStructType;
|
||||
|
||||
/**
|
||||
* 基本包
|
||||
*/
|
||||
private String basePackage;
|
||||
|
||||
/**
|
||||
* 模块包
|
||||
*/
|
||||
private String packageModule;
|
||||
|
||||
/**
|
||||
* 生产的表
|
||||
*/
|
||||
private String[] tables;
|
||||
|
||||
/**
|
||||
* 去掉表前缀
|
||||
*/
|
||||
private String[] tablePrefixs;
|
||||
|
||||
/**
|
||||
* 是否生产业务层和控制层
|
||||
*/
|
||||
private boolean generateServiceController;
|
||||
|
||||
/**
|
||||
* 是否生产POJO参数当generateServiceController=false生效
|
||||
*/
|
||||
private boolean generateXxxParams;
|
||||
|
||||
/**
|
||||
* 设置项目绝对路径
|
||||
*/
|
||||
public void setProjectPathByConfig() {
|
||||
if (null == this.projectName || this.projectName.trim().length() <= 0) {
|
||||
throw new IllegalArgumentException("配置projectName无效");
|
||||
}
|
||||
|
||||
String path = System.getProperty("user.dir"); // 当前工程路径
|
||||
//path = path.replace("\\doc", ""); // 处理工程引入问题
|
||||
String parentPath = File.separator + this.projectName;
|
||||
if (!(path + File.separator).contains(parentPath + File.separator)) {
|
||||
path += parentPath;
|
||||
}
|
||||
|
||||
if (this.layerName == null || "".equals(this.layerName)) {
|
||||
this.projectPath = path;
|
||||
return;
|
||||
}
|
||||
|
||||
String modulePart = File.separator + this.layerName;
|
||||
if (!path.contains(modulePart)) {
|
||||
path += modulePart;
|
||||
}
|
||||
this.projectPath = path;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,448 @@
|
|||
package com.msph.cls.generate;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.generator.AutoGenerator;
|
||||
import com.baomidou.mybatisplus.generator.InjectionConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.*;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.DateType;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
|
||||
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
|
||||
import lombok.extern.log4j.Log4j;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Mybatis Plus代码生成工具
|
||||
* 全局配置文件: mbp.properties
|
||||
* 作者信息配置文件: mbp.author
|
||||
*/
|
||||
@Log4j
|
||||
public class MBPGeneratorHelper {
|
||||
private static final String CONFIG_FILE = "mbp.properties";
|
||||
private static final String TEMPLATE_BASE_PATE = "/codeTemplate/";
|
||||
|
||||
|
||||
/**
|
||||
* 生成代码,盘Ta
|
||||
* @param args args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
run();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 执行代码生成,从配置文件mbp.properties加载配置,从控制台读取用户输入配置
|
||||
*/
|
||||
public static void run() {
|
||||
// 读取配置文件配置信息
|
||||
GeneratorConfig generatorConfig = readGeneratorPropertiesFromFile();
|
||||
|
||||
// 根据配置的projectName和layerName设置代码生成根路径
|
||||
generatorConfig.setProjectPathByConfig();
|
||||
|
||||
// 从控制台获取用户输入数据
|
||||
mergeGeneratorPropertiesFromConsole(generatorConfig);
|
||||
|
||||
// 根据配置信息和用户输入数据执行代码生成
|
||||
generate(generatorConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从配置文件读取配置
|
||||
* @return 代码生成配置类
|
||||
*/
|
||||
private static GeneratorConfig readGeneratorPropertiesFromFile() {
|
||||
Properties properties = new Properties();
|
||||
try (InputStream is = MBPGeneratorHelper.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) {
|
||||
if (is != null) {
|
||||
properties.load(is);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("[警告]: 配置文件" + CONFIG_FILE + "无效或不存在");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
String jsonText = JSON.toJSONString(properties);
|
||||
log.info("配置信息=" + jsonText);
|
||||
return JSON.parseObject(jsonText, GeneratorConfig.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从控制台获取用户输入数据
|
||||
* @param config 配置对象
|
||||
*/
|
||||
private static void mergeGeneratorPropertiesFromConsole(GeneratorConfig config) {
|
||||
printTips(config);
|
||||
String[] tables = inputTables();
|
||||
String moduleName = inputModuleName();
|
||||
boolean isGenerateServiceAndController = inputIsGenerateServiceAndController();
|
||||
boolean isGenerateXxxParams = true;
|
||||
if (!isGenerateServiceAndController) {
|
||||
isGenerateXxxParams = inputIsGenerateXxxParams();
|
||||
}
|
||||
String[] tablePrefixs = inputTablePrefix();
|
||||
|
||||
config.setTables(tables);
|
||||
config.setPackageModule(moduleName);
|
||||
config.setGenerateServiceController(isGenerateServiceAndController);
|
||||
config.setGenerateXxxParams(isGenerateXxxParams);
|
||||
config.setTablePrefixs(tablePrefixs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置信息和用户输入数据执行代码生成
|
||||
* @param config 配置对象
|
||||
*/
|
||||
public static void generate(GeneratorConfig config) {
|
||||
// 配置检查
|
||||
checkGeneratorConfig(config);
|
||||
// 获取项目绝对路径
|
||||
String projectPath = config.getProjectPath();
|
||||
// 创建mybatis-plus代码生成器
|
||||
AutoGenerator mpg = new AutoGenerator();
|
||||
|
||||
// 设置模板引擎(freemarker)
|
||||
mpg.setTemplateEngine(new FreemarkerTemplateEngine() {
|
||||
@Override
|
||||
public Map<String, Object> getObjectMap(TableInfo tableInfo) {
|
||||
tableInfo.setConvert(true);
|
||||
Map<String, Object> objectMap = super.getObjectMap(tableInfo);
|
||||
// 这里可以自定义属性放入到objectMap中,在模板中通过${属性名}获取属性值
|
||||
objectMap.put("date", DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm").format(LocalDateTime.now()));
|
||||
return objectMap;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 数据源配置
|
||||
DataSourceConfig dsc = new DataSourceConfig();
|
||||
dsc.setUrl(config.getDbUrl());
|
||||
dsc.setDriverName(config.getDbDriver());
|
||||
dsc.setUsername(config.getDbUsername());
|
||||
dsc.setPassword(config.getDbPassword());
|
||||
mpg.setDataSource(dsc);
|
||||
|
||||
// 包命名空间配置
|
||||
PackageConfig pc = new PackageConfig();
|
||||
// 设置基包
|
||||
pc.setParent(config.getBasePackage());
|
||||
String packageModule = config.getPackageModule();
|
||||
// 基包下面controller、service、dao、model的各自包名设置
|
||||
if (GeneratorConfig.LAYER_MODULE.equals(config.getPackageStructType())) {
|
||||
// pc.setController("controller." + packageModule);
|
||||
// pc.setService("service." + packageModule);
|
||||
// pc.setEntity("dao.model." + packageModule);
|
||||
// pc.setMapper("dao.mapper." + packageModule);
|
||||
pc.setController("controller");
|
||||
pc.setService("service");
|
||||
pc.setEntity("dao.domain");
|
||||
pc.setMapper("dao.mapper");
|
||||
} else {
|
||||
pc.setController(packageModule + ".controller");
|
||||
pc.setService(packageModule + ".service");
|
||||
pc.setEntity(packageModule + ".model");
|
||||
pc.setMapper(packageModule + ".mapper");
|
||||
}
|
||||
pc.setServiceImpl(pc.getService() + ".impl");
|
||||
pc.setXml("/mapper/" + config.getPackageModule());
|
||||
mpg.setPackageInfo(pc);
|
||||
|
||||
// 全局配置
|
||||
GlobalConfig gc = new GlobalConfig();
|
||||
gc.setAuthor(config.getAuthor()); // 作者
|
||||
gc.setOutputDir(config.getProjectPath() + "/src/main/java");
|
||||
gc.setDateType(DateType.ONLY_DATE);
|
||||
gc.setFileOverride(config.isFileOverride());
|
||||
gc.setSwagger2(true);
|
||||
gc.setBaseResultMap(true);
|
||||
gc.setBaseColumnList(true);
|
||||
// 设置service的名称
|
||||
gc.setServiceName("%sService");
|
||||
gc.setIdType(IdType.INPUT);
|
||||
mpg.setGlobalConfig(gc);
|
||||
|
||||
// 自定义配置
|
||||
InjectionConfig cfg = new InjectionConfig() {
|
||||
@Override
|
||||
public void initMap() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
// 查询参数
|
||||
map.put("superQueryParamsName", "PageQuery");
|
||||
map.put("superQueryParamsClass", "com.afe.ai.common.core.web.page.PageQuery");
|
||||
//map.put("paramPackage", pc.getParent() + ".po." + config.getPackageModule());
|
||||
map.put("paramPackage", pc.getParent() + ".api.po");
|
||||
map.put("clientPackage", pc.getParent() + ".client." + config.getPackageModule());
|
||||
map.put("clientSuffix", "Client");
|
||||
map.put("addParamsSuffix", "AddPO");
|
||||
map.put("updateParamsSuffix", "UpdatePO");
|
||||
map.put("queryParamsSuffix", "QueryPO");
|
||||
map.put("voSuffix", "VO"); // 展示层对象
|
||||
map.put("doSuffix", "DO"); // 持久化对象
|
||||
map.put("appContextPath", config.getAppContextPath());
|
||||
map.put("appName", config.getAppName());
|
||||
setMap(map);
|
||||
}
|
||||
};
|
||||
|
||||
List<FileOutConfig> focList = new ArrayList<>();
|
||||
// 生成mapper配置
|
||||
focList.add(new FileOutConfig(TEMPLATE_BASE_PATE + "mapper.xml.ftl") {
|
||||
@Override
|
||||
public String outputFile(TableInfo tableInfo) {
|
||||
String entityName = tableInfo.getEntityName();
|
||||
return projectPath + "/src/main/resources" + pc.getXml() + "/" + entityName + "Mapper.xml";
|
||||
}
|
||||
});
|
||||
// 生成DO对象
|
||||
focList.add(new FileOutConfig(TEMPLATE_BASE_PATE + "entityDO.java.ftl") {
|
||||
@Override
|
||||
public String outputFile(TableInfo tableInfo) {
|
||||
String entityName = tableInfo.getEntityName();
|
||||
String paramPackage = pc.getParent() + "." + pc.getEntity();
|
||||
String suffix = cfg.getMap().get("doSuffix").toString() + ".java";
|
||||
String paramPath = packageToPath(paramPackage);
|
||||
return projectPath + "/" + paramPath + entityName + suffix;
|
||||
}
|
||||
});
|
||||
|
||||
// 生成client配置
|
||||
focList.add(new FileOutConfig(TEMPLATE_BASE_PATE + "client.java.ftl") {
|
||||
@Override
|
||||
public String outputFile(TableInfo tableInfo) {
|
||||
String entityName = tableInfo.getEntityName();
|
||||
String paramPackage = pc.getParent() + ".client." + config.getPackageModule();
|
||||
String suffix = cfg.getMap().get("clientSuffix").toString() + ".java";
|
||||
String paramPath = packageToPath(paramPackage);
|
||||
return projectPath + paramPath + entityName + suffix;
|
||||
}
|
||||
});
|
||||
|
||||
boolean isGenerateServiceAndController = config.isGenerateServiceController();
|
||||
boolean isGenerateXxxParams = isGenerateServiceAndController || config.isGenerateXxxParams();
|
||||
// 生产POJO参数
|
||||
if (isGenerateXxxParams) {
|
||||
// 新增参数
|
||||
focList.add(new FileOutConfig(TEMPLATE_BASE_PATE + "entityAddParams.java.ftl") {
|
||||
@Override
|
||||
public String outputFile(TableInfo tableInfo) {
|
||||
String entityName = tableInfo.getEntityName();
|
||||
String paramPackage = cfg.getMap().get("paramPackage").toString();
|
||||
String suffix = cfg.getMap().get("addParamsSuffix").toString() + ".java";
|
||||
String paramPath = packageToPath(paramPackage);
|
||||
return projectPath + paramPath + entityName + suffix;
|
||||
}
|
||||
});
|
||||
// 修改参数
|
||||
focList.add(new FileOutConfig(TEMPLATE_BASE_PATE + "entityUpdateParams.java.ftl") {
|
||||
@Override
|
||||
public String outputFile(TableInfo tableInfo) {
|
||||
String entityName = tableInfo.getEntityName();
|
||||
String paramPackage = cfg.getMap().get("paramPackage").toString();
|
||||
String suffix = cfg.getMap().get("updateParamsSuffix").toString() + ".java";
|
||||
String paramPath = packageToPath(paramPackage);
|
||||
return projectPath + paramPath + entityName + suffix;
|
||||
}
|
||||
});
|
||||
// 查询参数
|
||||
focList.add(new FileOutConfig(TEMPLATE_BASE_PATE + "entityQueryParams.java.ftl") {
|
||||
@Override
|
||||
public String outputFile(TableInfo tableInfo) {
|
||||
String entityName = tableInfo.getEntityName();
|
||||
String paramPackage = cfg.getMap().get("paramPackage").toString();
|
||||
String suffix = cfg.getMap().get("queryParamsSuffix").toString() + ".java";
|
||||
String paramPath = packageToPath(paramPackage);
|
||||
return projectPath + paramPath + entityName + suffix;
|
||||
}
|
||||
});
|
||||
// 回参VO
|
||||
focList.add(new FileOutConfig(TEMPLATE_BASE_PATE + "entityVO.java.ftl") {
|
||||
@Override
|
||||
public String outputFile(TableInfo tableInfo) {
|
||||
String entityName = tableInfo.getEntityName();
|
||||
String paramPackage = cfg.getMap().get("paramPackage").toString();
|
||||
String suffix = cfg.getMap().get("voSuffix").toString() + ".java";
|
||||
String paramPath = packageToPath(paramPackage);
|
||||
return projectPath + paramPath + entityName + suffix;
|
||||
}
|
||||
});
|
||||
}
|
||||
cfg.setFileOutConfigList(focList);
|
||||
mpg.setCfg(cfg);
|
||||
|
||||
// 模版配置
|
||||
TemplateConfig template = new TemplateConfig();
|
||||
template.setEntity(null); // 原始的entity对象去掉,使用entityDO.java
|
||||
//template.setEntity(TEMPLATE_BASE_PATE + "entity.java");
|
||||
template.setService(TEMPLATE_BASE_PATE + "service.java");
|
||||
template.setServiceImpl(TEMPLATE_BASE_PATE + "serviceImpl.java");
|
||||
template.setMapper(TEMPLATE_BASE_PATE + "mapper.java");
|
||||
template.setController(TEMPLATE_BASE_PATE + "controller.java");
|
||||
template.setXml(null);
|
||||
if (!isGenerateServiceAndController) {
|
||||
template.setService(null);
|
||||
template.setServiceImpl(null);
|
||||
template.setController(null);
|
||||
}
|
||||
mpg.setTemplate(template);
|
||||
|
||||
// 策略配置
|
||||
StrategyConfig strategy = new StrategyConfig();
|
||||
strategy.setNaming(NamingStrategy.underline_to_camel);
|
||||
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
|
||||
strategy.setEntityLombokModel(true);
|
||||
strategy.setEntityTableFieldAnnotationEnable(true);
|
||||
strategy.setEntitySerialVersionUID(false);
|
||||
strategy.setInclude(config.getTables());
|
||||
strategy.setLogicDeleteFieldName("is_del"); // 逻辑删除字段
|
||||
|
||||
strategy.setTablePrefix(config.getTablePrefixs());
|
||||
mpg.setStrategy(strategy);
|
||||
|
||||
mpg.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置检查
|
||||
* @param config 配置
|
||||
*/
|
||||
private static void checkGeneratorConfig(GeneratorConfig config) {
|
||||
assertThat(config.getAuthor() != null && config.getAuthor().length() > 0, "author");
|
||||
assertThat(config.getProjectPath() != null && config.getProjectPath().length() > 0, "projectPath");
|
||||
assertThat(config.getDbDriver() != null && config.getDbDriver().length() > 0, "dbDriver");
|
||||
assertThat(config.getDbUrl() != null && config.getDbUrl().length() > 0, "dbUrl");
|
||||
assertThat(config.getAppName() != null && config.getAppName().length() > 0, "appName");
|
||||
assertThat(config.getProjectName() != null && config.getProjectName().length() > 0, "projectName");
|
||||
assertThat(config.getAppContextPath() != null && config.getAppContextPath().length() > 0, "appContextPath");
|
||||
assertThat(config.getDbUsername() != null && config.getDbUsername().length() > 0, "dbUsername");
|
||||
assertThat(config.getDbPassword() != null && config.getDbPassword().length() > 0, "dbPassword");
|
||||
assertThat(config.getPackageStructType() != null && config.getPackageStructType().length() > 0, "packageStructType");
|
||||
assertThat(config.getBasePackage() != null && config.getBasePackage().length() > 0, "basePackage");
|
||||
assertThat(config.getPackageModule() != null && config.getPackageModule().length() > 0, "packageModule");
|
||||
assertThat(config.getTables() != null && config.getTables().length > 0, "tables");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param condition 条件
|
||||
* @param paramName 名称
|
||||
*/
|
||||
private static void assertThat(boolean condition, String paramName) {
|
||||
if (!condition) {
|
||||
throw new IllegalArgumentException("配置" + paramName + "无效");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 讲包路径改为文档路径
|
||||
* @param packageStr 包路径
|
||||
* @return 文档路径
|
||||
*/
|
||||
private static String packageToPath(String packageStr) {
|
||||
if (StringUtils.isNotEmpty(packageStr)) {
|
||||
String path = packageStr.replace('.', '/');
|
||||
return "/src/main/java/" + path + "/";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 控制台输入提示信息
|
||||
* @param config 配置
|
||||
*/
|
||||
private static void printTips(GeneratorConfig config) {
|
||||
log.info("欢迎使用MybatisPlus代码生成器");
|
||||
log.info(String.format(" 作者: %s", config.getAuthor()));
|
||||
log.info(String.format(" 路径: %s", config.getProjectPath()));
|
||||
log.info(String.format(" 基包: %s", config.getBasePackage()));
|
||||
log.info("你只需要3~4步骤即生成代码!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取要生成的表
|
||||
* @return 表名
|
||||
*/
|
||||
private static String[] inputTables() {
|
||||
while (true) {
|
||||
String tables = scanner(" 1. 您要生成的表(多个逗号分隔): ");
|
||||
List<String> tableList = Arrays.stream(tables.split(",")).map(String::trim).filter(s -> !s.isEmpty()).collect(Collectors.toList());
|
||||
if (tableList.isEmpty()) continue;
|
||||
|
||||
String[] tableArrays = new String[tableList.size()];
|
||||
tableList.toArray(tableArrays);
|
||||
return tableArrays;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模块
|
||||
* @return 模块
|
||||
*/
|
||||
private static String inputModuleName() {
|
||||
while (true) {
|
||||
String module = scanner(" 2. 模块名: ").trim();
|
||||
if (module.isEmpty()) continue;
|
||||
return module;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取生成Controller和Service条件
|
||||
* @return true/false
|
||||
*/
|
||||
private static boolean inputIsGenerateServiceAndController() {
|
||||
String input = scanner(" 3. 生成Controller和Service代码(Y/N)?: ");
|
||||
return input.trim().toUpperCase().startsWith("Y");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表前缀
|
||||
* @return 表前缀
|
||||
*/
|
||||
private static String[] inputTablePrefix() {
|
||||
while (true) {
|
||||
String tablePrefix = scanner(" 4. 去前表前缀(多个逗号分隔): ").trim();
|
||||
List<String> tablePrefixList = Arrays.stream(tablePrefix.split(",")).map(String::trim).filter(s -> !s.isEmpty()).collect(Collectors.toList());
|
||||
if (tablePrefixList.isEmpty()) continue;
|
||||
|
||||
String[] tablePrefixArrays = new String[tablePrefixList.size()];
|
||||
tablePrefixList.toArray(tablePrefixArrays);
|
||||
return tablePrefixArrays;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成参数条件
|
||||
* @return true/false
|
||||
*/
|
||||
private static boolean inputIsGenerateXxxParams() {
|
||||
String input = scanner(" 4. 生成XxxParams参数对象(Y/N)?: ");
|
||||
return input.trim().toUpperCase().startsWith("Y");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取输入结果
|
||||
* @param tip 提示文本
|
||||
* @return 输入结果
|
||||
*/
|
||||
private static String scanner(String tip) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.print(tip);
|
||||
if (scanner.hasNext()) {
|
||||
String ipt = scanner.next();
|
||||
if (StringUtils.isNotEmpty(ipt)) {
|
||||
return ipt;
|
||||
}
|
||||
}
|
||||
throw new MybatisPlusException("代码生成中断");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package ${cfg.clientPackage};
|
||||
|
||||
import com.msph.cls.base.model.rest.RestResult;
|
||||
import ${cfg.paramPackage}.${entity}${cfg.addParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.updateParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.queryParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.voSuffix};
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.msph.cls.base.model.pojo.PageDataInfo;
|
||||
|
||||
/**
|
||||
* ${table.comment!}客户端
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
*/
|
||||
@FeignClient(name = "${cfg.appName}", path = "${cfg.appContextPath}", contextId = "${entity}Client")
|
||||
@RequestMapping("<#if package.ModuleName??>/client/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>client/${controllerMappingHyphen}<#else>client/${table.entityPath}</#if>")
|
||||
public interface ${entity}${cfg.clientSuffix} {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param params 新增对象
|
||||
* @return 统一响应对象
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
@ApiOperation("新增")
|
||||
RestResult<Void> add${entity}(@RequestBody ${entity}${cfg.addParamsSuffix} params);
|
||||
|
||||
/**
|
||||
* 删除,对象使用了@TableLogic注解时,为逻辑删除
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 统一响应对象
|
||||
*/
|
||||
@PostMapping("/delete/{id}")
|
||||
@ApiOperation("删除")
|
||||
RestResult<Void> delete${entity}(@PathVariable(value = "id") long id);
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*
|
||||
* @param params 修改对象
|
||||
* @return 统一响应对象
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@ApiOperation("修改")
|
||||
RestResult<Void> update${entity}(@RequestBody ${entity}${cfg.updateParamsSuffix} params);
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 统一响应对象
|
||||
*/
|
||||
@GetMapping("/detail/{id}")
|
||||
@ApiOperation("详情")
|
||||
RestResult<${entity}${cfg.voSuffix}> get${entity}(@PathVariable(value = "id") long id);
|
||||
|
||||
/**
|
||||
* 分页列表
|
||||
*
|
||||
* @param params 查询对象
|
||||
* @return 统一响应对象
|
||||
*/
|
||||
@PostMapping("/listPage")
|
||||
@ApiOperation("分页列表")
|
||||
RestResult<PageDataInfo<${entity}${cfg.voSuffix}>> list${entity}Page(@RequestBody ${entity}${cfg.queryParamsSuffix} params);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package ${package.Controller};
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ${cfg.clientPackage}.${entity}${cfg.clientSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.addParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.updateParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.queryParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.voSuffix};
|
||||
import ${package.Service}.${table.serviceName};
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.msph.cls.base.model.pojo.PageDataInfo;
|
||||
import com.msph.cls.base.model.rest.RestResult;
|
||||
|
||||
/**
|
||||
* ${table.comment!}控制层
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
*/
|
||||
@Api(tags = "${table.comment}")
|
||||
@Slf4j
|
||||
@RestController
|
||||
public class ${table.controllerName} implements ${entity}${cfg.clientSuffix} {
|
||||
|
||||
<#assign serviceInstanceName="${table.entityPath}Service" />
|
||||
@Autowired
|
||||
private ${table.serviceName} ${serviceInstanceName};
|
||||
|
||||
@Override
|
||||
public RestResult<Void> add${entity}(@RequestBody ${entity}${cfg.addParamsSuffix} params) {
|
||||
${serviceInstanceName}.save${entity}(params);
|
||||
return RestResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestResult<Void> delete${entity}(@PathVariable long id) {
|
||||
${serviceInstanceName}.removeById(id);
|
||||
return RestResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestResult<Void> update${entity}(@RequestBody ${entity}${cfg.updateParamsSuffix} params) {
|
||||
${serviceInstanceName}.update${entity}(params);
|
||||
return RestResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestResult<${entity}${cfg.voSuffix}> get${entity}(@PathVariable long id) {
|
||||
${entity}${cfg.doSuffix} data = ${serviceInstanceName}.getById(id);
|
||||
if (data == null) return RestResult.success();
|
||||
${entity}${cfg.voSuffix} result = new ${entity}${cfg.voSuffix}();
|
||||
BeanUtils.copyProperties(data, result);
|
||||
return RestResult.success(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestResult<PageDataInfo<${entity}${cfg.voSuffix}>> list${entity}Page(@RequestBody ${entity}${cfg.queryParamsSuffix} params) {
|
||||
PageDataInfo<${entity}${cfg.voSuffix}> data = ${serviceInstanceName}.list${entity}Page(params);
|
||||
return RestResult.success(data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
package ${package.Entity};
|
||||
|
||||
<#list table.importPackages as pkg>
|
||||
import ${pkg};
|
||||
</#list>
|
||||
<#if swagger2>
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
</#if>
|
||||
<#if table.convert>
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
</#if>
|
||||
<#if entityLombokModel>
|
||||
import lombok.Data;
|
||||
<#if superEntityClass??>
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
</#if>
|
||||
import lombok.experimental.Accessors;
|
||||
</#if>
|
||||
|
||||
/**
|
||||
* ${table.comment!}
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
*/
|
||||
<#if entityLombokModel>
|
||||
@Data
|
||||
<#if superEntityClass??>
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
</#if>
|
||||
@Accessors(chain = true)
|
||||
</#if>
|
||||
<#if table.convert>
|
||||
@TableName("${table.name}")
|
||||
</#if>
|
||||
<#if swagger2>
|
||||
@ApiModel(value = "${entity}对象", description = "${table.comment!}")
|
||||
<#else>
|
||||
/**
|
||||
* ${entity}对象 description=${table.comment!}
|
||||
*/
|
||||
</#if>
|
||||
<#if superEntityClass??>
|
||||
public class ${entity} extends ${superEntityClass} <#if activeRecord><${entity}></#if> {
|
||||
<#elseif activeRecord>
|
||||
public class ${entity} extends Model<${entity}> {
|
||||
<#else>
|
||||
public class ${entity} implements Serializable {
|
||||
</#if>
|
||||
<#if entitySerialVersionUID>
|
||||
private static final long serialVersionUID = 1L;
|
||||
</#if>
|
||||
<#-- ---------- BEGIN 字段循环遍历 ---------->
|
||||
<#list table.fields as field>
|
||||
|
||||
<#if field.keyFlag>
|
||||
<#assign keyPropertyName="${field.propertyName}"/>
|
||||
</#if>
|
||||
<#if field.comment!?length gt 0>
|
||||
<#if swagger2>
|
||||
@ApiModelProperty(value = "${field.comment}")
|
||||
<#else>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
</#if>
|
||||
</#if>
|
||||
<#if field.keyFlag>
|
||||
<#-- 主键 -->
|
||||
<#if field.keyIdentityFlag>
|
||||
@TableId(value = "${field.name}", type = IdType.AUTO)
|
||||
<#elseif idType??>
|
||||
@TableId(value = "${field.name}", type = IdType.${idType})
|
||||
<#elseif field.convert>
|
||||
@TableId("${field.name}")
|
||||
</#if>
|
||||
<#-- 普通字段 -->
|
||||
<#elseif field.fill??>
|
||||
<#-- ----- 存在字段填充设置 ----->
|
||||
<#if field.convert>
|
||||
@TableField(value = "${field.name}", fill = FieldFill.${field.fill})
|
||||
<#else>
|
||||
@TableField(fill = FieldFill.${field.fill})
|
||||
</#if>
|
||||
<#elseif field.convert>
|
||||
@TableField("${field.name}")
|
||||
</#if>
|
||||
<#-- 乐观锁注解 -->
|
||||
<#if (versionFieldName!"") == field.name>
|
||||
@Version
|
||||
</#if>
|
||||
<#-- 逻辑删除注解 -->
|
||||
<#if (logicDeleteFieldName!"") == field.name>
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
</#if>
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
</#list>
|
||||
<#------------ END 字段循环遍历 ---------->
|
||||
<#if !entityLombokModel>
|
||||
|
||||
<#list table.fields as field>
|
||||
<#if field.propertyType == "boolean">
|
||||
<#assign getprefix="is"/>
|
||||
<#else>
|
||||
<#assign getprefix="get"/>
|
||||
</#if>
|
||||
public ${field.propertyType} ${getprefix}${field.capitalName}() {
|
||||
return ${field.propertyName};
|
||||
}
|
||||
|
||||
<#if entityBuilderModel>
|
||||
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
<#else>
|
||||
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
</#if>
|
||||
this.${field.propertyName} = ${field.propertyName};
|
||||
<#if entityBuilderModel>
|
||||
return this;
|
||||
</#if>
|
||||
}
|
||||
</#list>
|
||||
</#if>
|
||||
<#if entityColumnConstant>
|
||||
|
||||
<#list table.fields as field>
|
||||
public static final String ${field.name?upper_case} = "${field.name}";
|
||||
</#list>
|
||||
</#if>
|
||||
<#if activeRecord>
|
||||
|
||||
@Override
|
||||
protected Serializable pkVal() {
|
||||
<#if keyPropertyName??>
|
||||
return this.${keyPropertyName};
|
||||
<#else>
|
||||
return null;
|
||||
</#if>
|
||||
}
|
||||
</#if>
|
||||
<#if !entityLombokModel>
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "${entity}{" +
|
||||
<#list table.fields as field>
|
||||
<#if field_index==0>
|
||||
"${field.propertyName}=" + ${field.propertyName} +
|
||||
<#else>
|
||||
", ${field.propertyName}=" + ${field.propertyName} +
|
||||
</#if>
|
||||
</#list>
|
||||
"}";
|
||||
}
|
||||
</#if>
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package ${cfg.paramPackage};
|
||||
|
||||
<#--<#list table.importPackages as pkg>-->
|
||||
<#--import ${pkg};-->
|
||||
<#--</#list>-->
|
||||
<#if swagger2>
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
</#if>
|
||||
<#if entityLombokModel>
|
||||
import lombok.Data;
|
||||
</#if>
|
||||
|
||||
/**
|
||||
* ${table.comment!}
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
*/
|
||||
<#if entityLombokModel>
|
||||
@Data
|
||||
<#if cfg.superOpsParamsClass??>
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
</#if>
|
||||
</#if>
|
||||
<#if swagger2>
|
||||
@ApiModel(value = "${entity}新增对象", description = "${table.comment!}")
|
||||
</#if>
|
||||
public class ${entity}${cfg.addParamsSuffix} implements Serializable {
|
||||
<#-- ---------- BEGIN 字段循环遍历 ---------->
|
||||
<#list table.fields as field>
|
||||
<#--逻辑删除字段不生成-->
|
||||
<#if (logicDeleteFieldName!"") != field.name>
|
||||
|
||||
<#if field.keyFlag>
|
||||
<#assign keyPropertyName="${field.propertyName}"/>
|
||||
</#if>
|
||||
<#if field.comment!?length gt 0>
|
||||
<#if swagger2>
|
||||
@ApiModelProperty(value = "${field.comment}")
|
||||
<#else>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
</#if>
|
||||
</#if>
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
</#if>
|
||||
</#list>
|
||||
<#------------ END 字段循环遍历 ---------->
|
||||
<#if !entityLombokModel>
|
||||
|
||||
<#list table.fields as field>
|
||||
<#if field.propertyType == "boolean">
|
||||
<#assign getprefix="is"/>
|
||||
<#else>
|
||||
<#assign getprefix="get"/>
|
||||
</#if>
|
||||
public ${field.propertyType} ${getprefix}${field.capitalName}() {
|
||||
return ${field.propertyName};
|
||||
}
|
||||
|
||||
<#if entityBuilderModel>
|
||||
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
<#else>
|
||||
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
</#if>
|
||||
this.${field.propertyName} = ${field.propertyName};
|
||||
<#if entityBuilderModel>
|
||||
return this;
|
||||
</#if>
|
||||
}
|
||||
</#list>
|
||||
</#if>
|
||||
<#if !entityLombokModel>
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "${entity}{" +
|
||||
<#list table.fields as field>
|
||||
<#if field_index==0>
|
||||
"${field.propertyName}=" + ${field.propertyName} +
|
||||
<#else>
|
||||
", ${field.propertyName}=" + ${field.propertyName} +
|
||||
</#if>
|
||||
</#list>
|
||||
"}";
|
||||
}
|
||||
</#if>
|
||||
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
package ${package.Entity};
|
||||
|
||||
<#list table.importPackages as pkg>
|
||||
import ${pkg};
|
||||
</#list>
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
<#--<#if swagger2>
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
</#if>-->
|
||||
<#if table.convert>
|
||||
<#--import com.baomidou.mybatisplus.annotation.convertconvert;-->
|
||||
</#if>
|
||||
<#if entityLombokModel>
|
||||
import lombok.Data;
|
||||
<#if superEntityClass??>
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
</#if>
|
||||
import lombok.experimental.Accessors;
|
||||
</#if>
|
||||
|
||||
/**
|
||||
* ${table.comment!} DO对象
|
||||
*
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
*/
|
||||
<#if entityLombokModel>
|
||||
@Data
|
||||
<#if superEntityClass??>
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
</#if>
|
||||
@Accessors(chain = true)
|
||||
</#if>
|
||||
<#if table.convert>
|
||||
@TableName("${table.name}")
|
||||
</#if>
|
||||
<#--<#if swagger2>
|
||||
@ApiModel(value = "${entity}对象", description = "${table.comment!}")
|
||||
</#if>-->
|
||||
<#if superEntityClass??>
|
||||
public class ${entity}${cfg.doSuffix} extends ${superEntityClass} <#if activeRecord><${entity}${cfg.doSuffix}></#if> {
|
||||
<#elseif activeRecord>
|
||||
public class ${entity}${cfg.doSuffix} extends Model<${entity}${cfg.doSuffix}> {
|
||||
<#else>
|
||||
public class ${entity}${cfg.doSuffix} implements Serializable {
|
||||
</#if>
|
||||
<#if entitySerialVersionUID>
|
||||
private static final long serialVersionUID = 1L;
|
||||
</#if>
|
||||
<#-- ---------- BEGIN 字段循环遍历 ---------->
|
||||
<#list table.fields as field>
|
||||
|
||||
<#if field.keyFlag>
|
||||
<#assign keyPropertyName="${field.propertyName}"/>
|
||||
</#if>
|
||||
<#if field.comment!?length gt 0>
|
||||
<#-- <#if swagger2>
|
||||
@ApiModelProperty(value = "${field.comment}")
|
||||
<#else>-->
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
<#-- </#if>-->
|
||||
</#if>
|
||||
<#if field.keyFlag>
|
||||
<#-- 主键 -->
|
||||
<#if field.keyIdentityFlag>
|
||||
@TableId(value = "${field.name}", type = IdType.AUTO)
|
||||
<#elseif idType??>
|
||||
@TableId(value = "${field.name}", type = IdType.${idType})
|
||||
<#elseif field.convert>
|
||||
@TableId("${field.name}")
|
||||
</#if>
|
||||
<#-- 普通字段 -->
|
||||
<#elseif field.fill??>
|
||||
<#-- ----- 存在字段填充设置 ----->
|
||||
<#if field.convert>
|
||||
@TableField(value = "${field.name}", fill = FieldFill.${field.fill})
|
||||
<#else>
|
||||
@TableField(fill = FieldFill.${field.fill})
|
||||
</#if>
|
||||
<#elseif field.convert>
|
||||
@TableField("${field.name}")
|
||||
</#if>
|
||||
<#-- 乐观锁注解 -->
|
||||
<#if (versionFieldName!"") == field.name>
|
||||
@Version
|
||||
</#if>
|
||||
<#-- 逻辑删除注解 -->
|
||||
<#if (logicDeleteFieldName!"") == field.name>
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
</#if>
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
</#list>
|
||||
<#------------ END 字段循环遍历 ---------->
|
||||
<#if !entityLombokModel>
|
||||
|
||||
<#list table.fields as field>
|
||||
<#if field.propertyType == "boolean">
|
||||
<#assign getprefix="is"/>
|
||||
<#else>
|
||||
<#assign getprefix="get"/>
|
||||
</#if>
|
||||
public ${field.propertyType} ${getprefix}${field.capitalName}() {
|
||||
return ${field.propertyName};
|
||||
}
|
||||
|
||||
<#if entityBuilderModel>
|
||||
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
<#else>
|
||||
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
</#if>
|
||||
this.${field.propertyName} = ${field.propertyName};
|
||||
<#if entityBuilderModel>
|
||||
return this;
|
||||
</#if>
|
||||
}
|
||||
</#list>
|
||||
</#if>
|
||||
<#if entityColumnConstant>
|
||||
|
||||
<#list table.fields as field>
|
||||
public static final String ${field.name?upper_case} = "${field.name}";
|
||||
</#list>
|
||||
</#if>
|
||||
<#if activeRecord>
|
||||
|
||||
@Override
|
||||
protected Serializable pkVal() {
|
||||
<#if keyPropertyName??>
|
||||
return this.${keyPropertyName};
|
||||
<#else>
|
||||
return null;
|
||||
</#if>
|
||||
}
|
||||
</#if>
|
||||
<#if !entityLombokModel>
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "${entity}{" +
|
||||
<#list table.fields as field>
|
||||
<#if field_index==0>
|
||||
"${field.propertyName}=" + ${field.propertyName} +
|
||||
<#else>
|
||||
", ${field.propertyName}=" + ${field.propertyName} +
|
||||
</#if>
|
||||
</#list>
|
||||
"}";
|
||||
}
|
||||
</#if>
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package ${cfg.paramPackage};
|
||||
|
||||
<#--<#list table.importPackages as pkg>-->
|
||||
<#--import ${pkg};-->
|
||||
<#--</#list>-->
|
||||
<#if swagger2>
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
</#if>
|
||||
<#if entityLombokModel>
|
||||
import lombok.Data;
|
||||
</#if>
|
||||
<#if cfg.superQueryParamsClass??>
|
||||
import ${cfg.superQueryParamsClass};
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
</#if>
|
||||
|
||||
/**
|
||||
* ${table.comment!}
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
*/
|
||||
<#if entityLombokModel>
|
||||
@Data
|
||||
<#if cfg.superQueryParamsClass??>
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
</#if>
|
||||
</#if>
|
||||
<#if swagger2>
|
||||
@ApiModel(value = "${entity}查询对象", description = "${table.comment!}")
|
||||
</#if>
|
||||
<#if cfg.superQueryParamsClass??>
|
||||
public class ${entity}${cfg.queryParamsSuffix} extends ${cfg.superQueryParamsName} {
|
||||
<#else>
|
||||
public class ${entity}${cfg.queryParamsSuffix} implements Serializable {
|
||||
</#if>
|
||||
<#-- ---------- BEGIN 字段循环遍历 ---------->
|
||||
<#list table.fields as field>
|
||||
<#--逻辑删除字段不生成-->
|
||||
<#if (logicDeleteFieldName!"") != field.name>
|
||||
|
||||
<#if field.keyFlag>
|
||||
<#assign keyPropertyName="${field.propertyName}"/>
|
||||
</#if>
|
||||
<#if field.comment!?length gt 0>
|
||||
<#if swagger2>
|
||||
@ApiModelProperty(value = "${field.comment}")
|
||||
<#else>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
</#if>
|
||||
</#if>
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
</#if>
|
||||
</#list>
|
||||
<#------------ END 字段循环遍历 ---------->
|
||||
<#if !entityLombokModel>
|
||||
|
||||
<#list table.fields as field>
|
||||
<#if field.propertyType == "boolean">
|
||||
<#assign getprefix="is"/>
|
||||
<#else>
|
||||
<#assign getprefix="get"/>
|
||||
</#if>
|
||||
public ${field.propertyType} ${getprefix}${field.capitalName}() {
|
||||
return ${field.propertyName};
|
||||
}
|
||||
|
||||
<#if entityBuilderModel>
|
||||
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
<#else>
|
||||
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
</#if>
|
||||
this.${field.propertyName} = ${field.propertyName};
|
||||
<#if entityBuilderModel>
|
||||
return this;
|
||||
</#if>
|
||||
}
|
||||
</#list>
|
||||
</#if>
|
||||
<#if !entityLombokModel>
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "${entity}{" +
|
||||
<#list table.fields as field>
|
||||
<#if field_index==0>
|
||||
"${field.propertyName}=" + ${field.propertyName} +
|
||||
<#else>
|
||||
", ${field.propertyName}=" + ${field.propertyName} +
|
||||
</#if>
|
||||
</#list>
|
||||
"}";
|
||||
}
|
||||
</#if>
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package ${cfg.paramPackage};
|
||||
|
||||
<#--<#list table.importPackages as pkg>-->
|
||||
<#--import ${pkg};-->
|
||||
<#--</#list>-->
|
||||
<#if swagger2>
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
</#if>
|
||||
<#if entityLombokModel>
|
||||
import lombok.Data;
|
||||
</#if>
|
||||
|
||||
/**
|
||||
* ${table.comment!}
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
*/
|
||||
<#if entityLombokModel>
|
||||
@Data
|
||||
<#if cfg.superOpsParamsClass??>
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
</#if>
|
||||
</#if>
|
||||
<#if swagger2>
|
||||
@ApiModel(value = "${entity}更新对象", description = "${table.comment!}")
|
||||
</#if>
|
||||
public class ${entity}${cfg.updateParamsSuffix} implements Serializable {
|
||||
<#-- ---------- BEGIN 字段循环遍历 ---------->
|
||||
<#list table.fields as field>
|
||||
<#--逻辑删除字段不生成-->
|
||||
<#if (logicDeleteFieldName!"") != field.name>
|
||||
|
||||
<#if field.keyFlag>
|
||||
<#assign keyPropertyName="${field.propertyName}"/>
|
||||
</#if>
|
||||
<#if field.comment!?length gt 0>
|
||||
<#if swagger2>
|
||||
@ApiModelProperty(value = "${field.comment}")
|
||||
<#else>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
</#if>
|
||||
</#if>
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
</#if>
|
||||
</#list>
|
||||
<#------------ END 字段循环遍历 ---------->
|
||||
<#if !entityLombokModel>
|
||||
|
||||
<#list table.fields as field>
|
||||
<#if field.propertyType == "boolean">
|
||||
<#assign getprefix="is"/>
|
||||
<#else>
|
||||
<#assign getprefix="get"/>
|
||||
</#if>
|
||||
public ${field.propertyType} ${getprefix}${field.capitalName}() {
|
||||
return ${field.propertyName};
|
||||
}
|
||||
|
||||
<#if entityBuilderModel>
|
||||
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
<#else>
|
||||
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
</#if>
|
||||
this.${field.propertyName} = ${field.propertyName};
|
||||
<#if entityBuilderModel>
|
||||
return this;
|
||||
</#if>
|
||||
}
|
||||
</#list>
|
||||
</#if>
|
||||
<#if !entityLombokModel>
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "${entity}{" +
|
||||
<#list table.fields as field>
|
||||
<#if field_index==0>
|
||||
"${field.propertyName}=" + ${field.propertyName} +
|
||||
<#else>
|
||||
", ${field.propertyName}=" + ${field.propertyName} +
|
||||
</#if>
|
||||
</#list>
|
||||
"}";
|
||||
}
|
||||
</#if>
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package ${cfg.paramPackage};
|
||||
|
||||
<#list table.importPackages as pkg>
|
||||
import ${pkg};
|
||||
</#list>
|
||||
<#if swagger2>
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
</#if>
|
||||
<#if entityLombokModel>
|
||||
import lombok.Data;
|
||||
</#if>
|
||||
|
||||
/**
|
||||
* ${table.comment!} VO对象
|
||||
*
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
*/
|
||||
<#if entityLombokModel>
|
||||
@Data
|
||||
<#if cfg.superOpsParamsClass??>
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
</#if>
|
||||
</#if>
|
||||
<#if swagger2>
|
||||
@ApiModel(value = "${entity} VO对象", description = "${table.comment!}")
|
||||
</#if>
|
||||
public class ${entity}${cfg.voSuffix} implements Serializable {
|
||||
<#-- ---------- BEGIN 字段循环遍历 ---------->
|
||||
<#list table.fields as field>
|
||||
|
||||
<#if field.keyFlag>
|
||||
<#assign keyPropertyName="${field.propertyName}"/>
|
||||
</#if>
|
||||
<#if field.comment!?length gt 0>
|
||||
<#if swagger2>
|
||||
@ApiModelProperty(value = "${field.comment}")
|
||||
<#else>
|
||||
/**
|
||||
* ${field.comment}
|
||||
*/
|
||||
</#if>
|
||||
</#if>
|
||||
private ${field.propertyType} ${field.propertyName};
|
||||
</#list>
|
||||
<#------------ END 字段循环遍历 ---------->
|
||||
<#if !entityLombokModel>
|
||||
|
||||
<#list table.fields as field>
|
||||
<#if field.propertyType == "boolean">
|
||||
<#assign getprefix="is"/>
|
||||
<#else>
|
||||
<#assign getprefix="get"/>
|
||||
</#if>
|
||||
public ${field.propertyType} ${getprefix}${field.capitalName}() {
|
||||
return ${field.propertyName};
|
||||
}
|
||||
|
||||
<#if entityBuilderModel>
|
||||
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
<#else>
|
||||
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
|
||||
</#if>
|
||||
this.${field.propertyName} = ${field.propertyName};
|
||||
<#if entityBuilderModel>
|
||||
return this;
|
||||
</#if>
|
||||
}
|
||||
</#list>
|
||||
</#if>
|
||||
<#if !entityLombokModel>
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "${entity}{" +
|
||||
<#list table.fields as field>
|
||||
<#if field_index==0>
|
||||
"${field.propertyName}=" + ${field.propertyName} +
|
||||
<#else>
|
||||
", ${field.propertyName}=" + ${field.propertyName} +
|
||||
</#if>
|
||||
</#list>
|
||||
"}";
|
||||
}
|
||||
</#if>
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package ${package.Mapper};
|
||||
|
||||
import ${package.Entity}.${entity}${cfg.doSuffix};
|
||||
import ${superMapperClassPackage};
|
||||
|
||||
/**
|
||||
* ${table.comment!}
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
*/
|
||||
public interface ${table.mapperName} extends ${superMapperClass}<${entity}${cfg.doSuffix}> {
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?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="${package.Mapper}.${table.mapperName}">
|
||||
<#if enableCache>
|
||||
<!-- 开启二级缓存 -->
|
||||
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
|
||||
</#if>
|
||||
|
||||
<#if baseResultMap>
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}${cfg.doSuffix}">
|
||||
<#list table.fields as field>
|
||||
<#--生成主键排在第一位-->
|
||||
<#if field.keyFlag>
|
||||
<id column="${field.name}" property="${field.propertyName}"/>
|
||||
</#if>
|
||||
</#list>
|
||||
<#--生成公共字段 -->
|
||||
<#list table.commonFields as field>
|
||||
<result column="${field.name}" property="${field.propertyName}"/>
|
||||
</#list>
|
||||
<#--生成普通字段 -->
|
||||
<#list table.fields as field>
|
||||
<#if !field.keyFlag>
|
||||
<result column="${field.name}" property="${field.propertyName}"/>
|
||||
</#if>
|
||||
</#list>
|
||||
</resultMap>
|
||||
</#if>
|
||||
|
||||
<#if baseColumnList>
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="BaseColumnList">
|
||||
<#list table.commonFields as field>
|
||||
${field.name},
|
||||
</#list>
|
||||
${table.fieldNames}
|
||||
</sql>
|
||||
</#if>
|
||||
</mapper>
|
|
@ -0,0 +1,42 @@
|
|||
package ${package.Service};
|
||||
|
||||
import ${superServiceClassPackage};
|
||||
import ${package.Entity}.${entity}${cfg.doSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.voSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.queryParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.addParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.updateParamsSuffix};
|
||||
import com.afe.ai.common.core.web.page.PageDataInfo;
|
||||
|
||||
/**
|
||||
* ${table.comment!}业务层
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
*/
|
||||
public interface ${table.serviceName} extends ${superServiceClass}<${entity}${cfg.doSuffix}> {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param params 新增对象
|
||||
* @return 添加结果
|
||||
*/
|
||||
int save${entity}(${entity}${cfg.addParamsSuffix} params);
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*
|
||||
* @param params 修改对象
|
||||
* @return 修改结果
|
||||
*/
|
||||
int update${entity}(${entity}${cfg.updateParamsSuffix} params);
|
||||
|
||||
/**
|
||||
* 分页列表
|
||||
*
|
||||
* @param params 查询对象
|
||||
* @return 分页对象
|
||||
*/
|
||||
PageDataInfo<${entity}${cfg.voSuffix}> list${entity}Page(${entity}${cfg.queryParamsSuffix} params);
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package ${package.ServiceImpl};
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.msph.cls.base.model.pojo.PageDataInfo;
|
||||
import ${package.Mapper}.${table.mapperName};
|
||||
import ${package.Service}.${table.serviceName};
|
||||
import ${package.Entity}.${entity}${cfg.doSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.queryParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.addParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.updateParamsSuffix};
|
||||
import ${cfg.paramPackage}.${entity}${cfg.voSuffix};
|
||||
import ${superServiceImplClassPackage};
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* ${table.comment!}业务层
|
||||
* @author ${author}
|
||||
* @date ${date}
|
||||
* <p>
|
||||
* <p>
|
||||
* Wrapper条件请使用lambda表达式拼接,避免字段修改影响到使用,如:
|
||||
* new UpdateWrapper<${entity}>()
|
||||
* .lambda()
|
||||
* .set(params.getUpdatetime() != null, ${entity}::getUpdatetime, params.getUpdatetime())
|
||||
* .eq(params.getSeqNo() != null, ${entity}::getSeqNo, params.getSeqNo());
|
||||
* 不推荐直接使用字符串,当字段修改时无法感知,如:
|
||||
* new QueryWrapper<${entity}>().eq("seq_no", params.getSeqNo());
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}${cfg.doSuffix}> implements ${table.serviceName} {
|
||||
|
||||
<#assign mapperInstanceName="${table.entityPath}Mapper" />
|
||||
|
||||
@Override
|
||||
public int save${entity}(${entity}${cfg.addParamsSuffix} params) {
|
||||
${entity}${cfg.doSuffix} entity = new ${entity}${cfg.doSuffix}();
|
||||
BeanUtils.copyProperties(params, entity);
|
||||
entity.setCreateTime(new Date());
|
||||
return getBaseMapper().insert(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update${entity}(${entity}${cfg.updateParamsSuffix} params) {
|
||||
${entity}${cfg.doSuffix} entity = new ${entity}${cfg.doSuffix}();
|
||||
BeanUtils.copyProperties(params, entity);
|
||||
entity.setUpdateTime(new Date());
|
||||
return getBaseMapper().updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageDataInfo<${entity}${cfg.voSuffix}> list${entity}Page(${entity}${cfg.queryParamsSuffix} params) {
|
||||
${entity}${cfg.doSuffix} entity = new ${entity}${cfg.doSuffix}();
|
||||
BeanUtils.copyProperties(params, entity);
|
||||
PageHelper.startPage(params.getPageNum(), params.getPageSize());
|
||||
List<${entity}${cfg.doSuffix}> data = getBaseMapper().selectList(new QueryWrapper<>(entity));
|
||||
|
||||
List<${entity}${cfg.voSuffix}> dataVoList = new ArrayList<>();
|
||||
data.forEach(entityDO -> {
|
||||
${entity}${cfg.voSuffix} vo = new ${entity}${cfg.voSuffix}();
|
||||
BeanUtils.copyProperties(entityDO, vo);
|
||||
dataVoList.add(vo);
|
||||
});
|
||||
return new PageDataInfo<>(PageInfo.of(data).getTotal(), dataVoList);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
author=system
|
||||
dbUrl=jdbc:mysql://127.0.0.1:3306/cls-core?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true
|
||||
dbUsername=root
|
||||
dbPassword=root
|
||||
packageStructType=layer-module
|
||||
basePackage=com.msph.cls.loans.dao
|
||||
projectName=loans
|
||||
layerName=loans-dao
|
||||
fileOverride=false
|
||||
appName=cls-loans
|
||||
appContextPath=/cls-loans
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||
|
||||
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
||||
<param name="target" value="System.out" />
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%d %-5p %.33t [%C{1}:%L] - %m%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<root>
|
||||
<priority value="info" />
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
</log4j:configuration>
|
|
@ -0,0 +1,11 @@
|
|||
author=bea.yang
|
||||
dbUrl=jdbc:mysql://127.0.0.1:3306/ai-news?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true
|
||||
dbUsername=root
|
||||
dbPassword=password
|
||||
packageStructType=layer-module
|
||||
basePackage=com.afe.ai.news
|
||||
projectName=news
|
||||
layerName=loans-dao
|
||||
fileOverride=false
|
||||
appName=ai-news
|
||||
appContextPath=/cls/loans
|
Loading…
Reference in New Issue