添加代码生成器

This commit is contained in:
六如
2025-01-17 09:25:57 +08:00
parent 7bc96d690b
commit 72f5420d4f
152 changed files with 9572 additions and 0 deletions

View File

@@ -0,0 +1,245 @@
<?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>org.noear</groupId>
<artifactId>solon-parent</artifactId>
<version>3.0.5</version>
<relativePath />
</parent>
<groupId>com.gitee.fmadmin</groupId>
<artifactId>sop-code-gen</artifactId>
<version>2.0.4</version>
<description>一款代码生成器</description>
<url>https://gitee.com/durcframework/code-gen</url>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.noear</groupId>
<artifactId>solon-boot-smarthttp</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon.boot.jdkhttp</artifactId>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon.web.cors</artifactId>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon.web.staticfiles</artifactId>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon.logging.logback</artifactId>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>mybatis-solon-plugin</artifactId>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-view-thymeleaf</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.34.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!--<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>8.4.1.jre8</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>12.1.0.1-atlassian-hosted</version>
</dependency>
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
<version>8.1.2.141</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.14</version>
</dependency>-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-test-junit4</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!-- 指定打包名称 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- compiler插件参数设置指定编码 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
<compilerArgument>-parameters</compilerArgument>
</configuration>
</plugin>
<!-- 打包时跳过测试 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<!-- 添加依赖输出控制 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<!-- 负责将应用程序打包成可执行的jar文件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!-- 指定classpath的前缀 -->
<classpathPrefix>lib/</classpathPrefix>
<!-- 指定主类的类名 -->
<mainClass>com.gitee.gen.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- 负责将整个项目按照自定义的目录结构打成最终的压缩包,方便实际部署 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly-zip.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,7 @@
# 代码生成工具
自动生成前后端代码,实现完整的增删改查功能。
参见com.gitee.gen.GenLocalTest
执行后代码自动生成到项目中

View File

@@ -0,0 +1,58 @@
<assembly>
<id>bin</id>
<formats>
<!--支持 ziptartar.gztar.bz2jardirwar 等 -->
<format>dir</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<!-- 启动文件 -->
<fileSet>
<directory>target</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>gen.jar</include>
</includes>
<fileMode>0644</fileMode>
</fileSet>
<!-- 执行脚本 -->
<fileSet>
<directory>src/main/assembly/bin</directory>
<outputDirectory>/</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<!-- 启动文件 -->
<fileSet>
<directory>target/lib</directory>
<outputDirectory>lib</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
<!-- 扩展文件 -->
<fileSet>
<directory>src/main/assembly</directory>
<includes>
<include>ext.md</include>
</includes>
<outputDirectory>ext</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
<!-- 配置文件 -->
<fileSet>
<directory>src/main/resources</directory>
<outputDirectory>conf</outputDirectory>
<includes>
<include>app.yml</include>
</includes>
<fileMode>0644</fileMode>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,3 @@
@echo off
java -Dsolon.config.add=conf/app.yml -Duser.timezone=Asia/Shanghai -jar -Xms64m -Xmx64m gen.jar

View File

@@ -0,0 +1,6 @@
#!/bin/sh
# 先关闭服务
sh shutdown.sh
nohup java -Dsolon.config.add=./conf/app.yml -Duser.timezone=Asia/Shanghai -jar -Xms64m -Xmx64m gen.jar >/dev/null 2>&1 &

View File

@@ -0,0 +1,10 @@
#!/bin/sh
# 关闭服务
app="gen"
pid=$(ps -ef | grep ${app}.jar | grep -v grep | awk '{print $2}')
if [ -n "$pid" ]; then
echo "stop ${app}.jar, pid:" "$pid"
kill -9 "$pid"
fi

View File

@@ -0,0 +1 @@
将数据库驱动放入该文件夹下

View File

@@ -0,0 +1,17 @@
package com.gitee.gen;
import org.noear.solon.Solon;
import org.noear.solon.web.cors.CrossFilter;
public class App {
public static void main(String[] args) {
Solon.start(App.class, args, app -> {
//例:增加全局处理(用过滤器模式)//对静态资源亦有效
app.filter(-1, new CrossFilter().allowedOrigins("*")); //加-1 优先级更高
});
}
}

View File

@@ -0,0 +1,33 @@
package com.gitee.gen.common;
/**
* @author tanghc
*/
public class Action {
private static final String CODE_SUCCESS = "0";
private static final String CODE_ERROR = "100";
private static Result ok = new Result();
static {
ok.setCode(CODE_SUCCESS);
}
public static Result ok() {
return ok;
}
public static Result ok(Object data) {
Result result = new Result();
result.setCode(CODE_SUCCESS);
result.setData(data);
return result;
}
public static Result err(String msg) {
Result result = new Result();
result.setCode(CODE_ERROR);
result.setMsg(msg);
return result;
}
}

View File

@@ -0,0 +1,91 @@
package com.gitee.gen.common;
import java.util.List;
public class GeneratorParam {
/** datasource_config主键 */
private int datasourceConfigId;
/** 表名 */
private List<String> tableNames;
/** template_config主键 */
private List<Integer> templateConfigIdList;
private String packageName;
private String delPrefix;
private String author;
private String charset = "UTF-8";
public int getDatasourceConfigId() {
return datasourceConfigId;
}
public void setDatasourceConfigId(int datasourceConfigId) {
this.datasourceConfigId = datasourceConfigId;
}
public List<String> getTableNames() {
return tableNames;
}
public void setTableNames(List<String> tableNames) {
this.tableNames = tableNames;
}
public List<Integer> getTemplateConfigIdList() {
return templateConfigIdList;
}
public void setTemplateConfigIdList(List<Integer> templateConfigIdList) {
this.templateConfigIdList = templateConfigIdList;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getDelPrefix() {
return delPrefix;
}
public void setDelPrefix(String delPrefix) {
this.delPrefix = delPrefix;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
@Override
public String toString() {
return "GeneratorParam{" +
"datasourceConfigId=" + datasourceConfigId +
", tableNames=" + tableNames +
", templateConfigIdList=" + templateConfigIdList +
", packageName='" + packageName + '\'' +
", delPrefix='" + delPrefix + '\'' +
", author='" + author + '\'' +
", charset='" + charset + '\'' +
'}';
}
}

View File

@@ -0,0 +1,133 @@
package com.gitee.gen.common;
public class IdWorker {
private static final IdWorker intance = new IdWorker(1, 1, 1);
//因为二进制里第一个 bit 为如果是 1那么都是负数但是我们生成的 id 都是正数,所以第一个 bit 统一都是 0。
//机器ID 2进制5位 32位减掉1位 31个
private long workerId;
//机房ID 2进制5位 32位减掉1位 31个
private long datacenterId;
//代表一毫秒内生成的多个id的最新序号 12位 4096 -1 = 4095 个
private long sequence;
//设置一个时间初始值 2^41 - 1 差不多可以用69年
private long twepoch = 1585644268888L;
//5位的机器id
private long workerIdBits = 5L;
//5位的机房id
private long datacenterIdBits = 5L;
//每毫秒内产生的id数 2 的 12次方
private long sequenceBits = 12L;
// 这个是二进制运算就是5 bit最多只能有31个数字也就是说机器id最多只能是32以内
private long maxWorkerId = -1L ^ (-1L << workerIdBits);
// 这个是一个意思就是5 bit最多只能有31个数字机房id最多只能是32以内
private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
private long workerIdShift = sequenceBits;
private long datacenterIdShift = sequenceBits + workerIdBits;
private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private long sequenceMask = -1L ^ (-1L << sequenceBits);
//记录产生时间毫秒数判断是否是同1毫秒
private long lastTimestamp = -1L;
public long getWorkerId(){
return workerId;
}
public long getDatacenterId() {
return datacenterId;
}
public long getTimestamp() {
return System.currentTimeMillis();
}
public static IdWorker getInstance() {
return intance;
}
public IdWorker(long workerId, long datacenterId, long sequence) {
// 检查机房id和机器id是否超过31 不能小于0
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(
String.format("worker Id can't be greater than %d or less than 0",maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(
String.format("datacenter Id can't be greater than %d or less than 0",maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
this.sequence = sequence;
}
// 这个是核心方法通过调用nextId()方法让当前这台机器上的snowflake算法程序生成一个全局唯一的id
public synchronized long nextId() {
// 这儿就是获取当前时间戳,单位是毫秒
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
System.err.printf(
"clock is moving backwards. Rejecting requests until %d.", lastTimestamp);
throw new RuntimeException(
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
lastTimestamp - timestamp));
}
// 下面是说假设在同一个毫秒内又发送了一个请求生成一个id
// 这个时候就得把seqence序号给递增1最多就是4096
if (lastTimestamp == timestamp) {
// 这个意思是说一个毫秒内最多只能有4096个数字无论你传递多少进来
//这个位运算保证始终就是在4096这个范围内避免你自己传递个sequence超过了4096这个范围
sequence = (sequence + 1) & sequenceMask;
//当某一毫秒的时间产生的id数 超过4095系统会进入等待直到下一毫秒系统继续产生ID
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}
// 这儿记录一下最近一次生成id的时间戳单位是毫秒
lastTimestamp = timestamp;
// 这儿就是最核心的二进制位运算操作生成一个64bit的id
// 先将当前时间戳左移放到41 bit那儿将机房id左移放到5 bit那儿将机器id左移放到5 bit那儿将序号放最后12 bit
// 最后拼接起来成一个64 bit的二进制数字转换成10进制就是个long型
return ((timestamp - twepoch) << timestampLeftShift) |
(datacenterId << datacenterIdShift) |
(workerId << workerIdShift) | sequence;
}
/**
* 当某一毫秒的时间产生的id数 超过4095系统会进入等待直到下一毫秒系统继续产生ID
* @param lastTimestamp
* @return
*/
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
//获取当前时间戳
private long timeGen(){
return System.currentTimeMillis();
}
/**
* main 测试类
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 22; i++) {
System.out.println(getInstance().nextId());
}
}
}

View File

@@ -0,0 +1,31 @@
package com.gitee.gen.common;
public class Result {
private String code;
private Object data;
private String msg;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

View File

@@ -0,0 +1,27 @@
package com.gitee.gen.config;
import com.gitee.gen.common.Action;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Handler;
import org.noear.solon.core.route.RouterInterceptor;
import org.noear.solon.core.route.RouterInterceptorChain;
import org.noear.solon.validation.ValidatorException;
@Component(index = 0) //index 为顺序位不加则默认为0
public class AppRouterInterceptor implements RouterInterceptor {
@Override
public void doIntercept(Context ctx, Handler mainHandler, RouterInterceptorChain chain) throws Throwable {
try {
chain.doIntercept(ctx, mainHandler);
if (mainHandler == null) {
ctx.render(Action.err("资源不存在"));
}
} catch (ValidatorException e) {
ctx.render(Action.err(e.getMessage())); //e.getResult().getDescription()
} catch (Throwable e) {
ctx.render(Action.err(e.getMessage()));
}
}
}

View File

@@ -0,0 +1,82 @@
package com.gitee.gen.config;
import com.gitee.gen.service.UpgradeService;
import com.gitee.gen.util.StringUtil;
import com.gitee.gen.util.SystemUtil;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang.StringUtils;
import org.noear.solon.Solon;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Condition;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Init;
import org.noear.solon.annotation.Inject;
import org.noear.solon.web.staticfiles.StaticMappings;
import org.noear.solon.web.staticfiles.repository.ClassPathStaticRepository;
import org.noear.solon.web.staticfiles.repository.FileStaticRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
@Configuration
public class Config {
static Logger log = LoggerFactory.getLogger(Config.class);
@Inject
UpgradeService upgradeService;
//此下的 db1 与 mybatis.db1 将对应在起来 //可以用 @Db("db1") 注入mapper
//typed=true表示默认数据源。@Db 可不带名字注入
@Bean(name = "db1", typed = true)
@Condition(onProperty = "${dbms.enable} = false")
public DataSource db1(@Inject("${gen.db1}") BasicDataSource ds) {
if (ds.getDriverClassName().contains("sqlite")) {
String url = ds.getUrl();
ds.setUrl(url + UpgradeService.getLocalDbPath());
}
log.info("使用本地数据库url:{}", ds.getUrl());
return ds;
}
@Bean(name = "db1", typed = true)
@Condition(onProperty = "${dbms.enable} = true")
public DataSource db2(@Inject("${gen.db2}") BasicDataSource ds) {
log.info("使用DBMS存储数据url={}", ds.getUrl());
return ds;
}
//调整 db1 的配置,或添加插件 (配置可以解决的,不需要这块代码)
//@Bean
//public void db1_cfg(@Db("db1") org.apache.ibatis.session.Configuration cfg) {
// cfg.setCacheEnabled(false);
//}
@Init
public void start() {
upgradeService.initDatabase();
upgradeService.init();
initStaticFile();
}
/**
* 初始化静态资源文件
*/
private static void initStaticFile() {
String frontLocation = Solon.context().cfg().get("gen.front-location", "");
String frontRoot;
if (StringUtils.isNotBlank(frontLocation)) {
frontRoot = StringUtil.trimTrailingCharacter(frontLocation, '/');
} else {
String homeDir = SystemUtil.getUserDir();
if ("/".equals(homeDir)) {
homeDir = "";
}
frontRoot = homeDir + "/dist";
}
log.info("前端资源目录:{}", frontRoot);
StaticMappings.add("/", new FileStaticRepository(frontRoot));
}
}

View File

@@ -0,0 +1,53 @@
package com.gitee.gen.config;
/**
* @author 六如
*/
public class ConnectConfig {
private String name;
private String driver;
private String url;
private String serviceName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
@Override
public String toString() {
return "ConnectConfig{" +
"name='" + name + '\'' +
", driver='" + driver + '\'' +
", url='" + url + '\'' +
'}';
}
}

View File

@@ -0,0 +1,33 @@
package com.gitee.gen.config;
import org.noear.solon.Solon;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;
import java.util.Map;
/**
* @author 六如
*/
@Configuration
public class DbTypeConfig {
@Inject("${connect}")
private Map<Integer, ConnectConfig> connectConfigMap;
public static DbTypeConfig getInstance() {
return Solon.context().getBean(DbTypeConfig.class);
}
public ConnectConfig getConnectConfig(Integer type) {
return connectConfigMap.get(type);
}
public Map<Integer, ConnectConfig> getConnectConfigMap() {
return connectConfigMap;
}
public void setConnectConfigMap(Map<Integer, ConnectConfig> connectConfigMap) {
this.connectConfigMap = connectConfigMap;
}
}

View File

@@ -0,0 +1,112 @@
package com.gitee.gen.controller;
import com.gitee.gen.common.Action;
import com.gitee.gen.common.Result;
import com.gitee.gen.config.DbTypeConfig;
import com.gitee.gen.entity.DatasourceConfig;
import com.gitee.gen.gen.DBConnect;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.SQLService;
import com.gitee.gen.gen.SQLServiceFactory;
import com.gitee.gen.gen.TableDefinition;
import com.gitee.gen.service.DatasourceConfigService;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.annotation.Path;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author tanghc
*/
@Controller
@Mapping("datasource")
public class DatasourceConfigController {
@Inject
private DatasourceConfigService datasourceConfigService;
@Mapping("/add")
public Result add(DatasourceConfig datasourceConfig) {
datasourceConfigService.insert(datasourceConfig);
return Action.ok();
}
@Mapping("/list")
public Result list() {
List<DatasourceConfig> datasourceConfigList = datasourceConfigService.listAll();
return Action.ok(datasourceConfigList);
}
@Mapping("/update")
public Result update(DatasourceConfig datasourceConfig) {
datasourceConfigService.update(datasourceConfig);
return Action.ok();
}
@Mapping("/del")
public Result del(DatasourceConfig datasourceConfig) {
datasourceConfigService.delete(datasourceConfig);
return Action.ok();
}
@Mapping("/table/{id}")
public Result listTable(@Path("id") int id) {
DatasourceConfig dataSourceConfig = datasourceConfigService.getById(id);
GeneratorConfig generatorConfig = GeneratorConfig.build(dataSourceConfig);
SQLService service = SQLServiceFactory.build(generatorConfig);
List<TableDefinition> list = service.getTableSelector(generatorConfig).getSimpleTableDefinitions();
return Action.ok(list);
}
@Mapping("/test")
public Result test(DatasourceConfig datasourceConfig) {
String error = DBConnect.testConnection(GeneratorConfig.build(datasourceConfig));
if (error != null) {
return Action.err(error);
}
return Action.ok();
}
@Mapping("/dbtype")
public Result dbType(DatasourceConfig datasourceConfig) {
List<DbTypeShow> dbTypeShowList = DbTypeConfig.getInstance()
.getConnectConfigMap()
.entrySet()
.stream()
.map(entry -> new DbTypeShow(entry.getValue().getName(), entry.getKey()))
.collect(Collectors.toList());
return Action.ok(dbTypeShowList);
}
private static class DbTypeShow {
private String label;
private Integer dbType;
public DbTypeShow(String label, Integer dbType) {
this.label = label;
this.dbType = dbType;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public Integer getDbType() {
return dbType;
}
public void setDbType(Integer dbType) {
this.dbType = dbType;
}
}
}

View File

@@ -0,0 +1,80 @@
package com.gitee.gen.controller;
import com.alibaba.fastjson.JSON;
import com.gitee.gen.common.Action;
import com.gitee.gen.common.GeneratorParam;
import com.gitee.gen.common.Result;
import com.gitee.gen.controller.vo.GenerateHistoryVO;
import com.gitee.gen.entity.DatasourceConfig;
import com.gitee.gen.entity.GenerateHistory;
import com.gitee.gen.entity.TemplateConfig;
import com.gitee.gen.service.DatasourceConfigService;
import com.gitee.gen.service.GenerateHistoryService;
import com.gitee.gen.service.TemplateConfigService;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Controller
@Mapping("history")
public class GenerateHistoryController {
@Inject
private GenerateHistoryService generateHistoryService;
@Inject
private DatasourceConfigService datasourceConfigService;
@Inject
private TemplateConfigService templateConfigService;
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
@Mapping("list")
public Result listAll() {
List<GenerateHistory> generateHistories = generateHistoryService.listAll();
List<GenerateHistoryVO> generateHistoryVOS = generateHistories.stream()
.map(generateHistory -> {
GenerateHistoryVO generateHistoryVO = new GenerateHistoryVO();
GeneratorParam generatorParam = JSON.parseObject(generateHistory.getConfigContent(), GeneratorParam.class);
String datasourceInfo = getDatasourceInfo(generatorParam.getDatasourceConfigId());
if (datasourceInfo == null) {
return null;
}
List<String> templateNames = this.listTemplateNames(generatorParam.getTemplateConfigIdList());
generateHistoryVO.setGenerateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(generateHistory.getGenerateTime()));
generateHistoryVO.setConfigContent(generatorParam);
generateHistoryVO.setDatasource(datasourceInfo);
generateHistoryVO.setTemplateNames(templateNames);
return generateHistoryVO;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
return Action.ok(generateHistoryVOS);
}
private String getDatasourceInfo(int datasourceConfigId) {
DatasourceConfig datasourceConfig = datasourceConfigService.getById(datasourceConfigId);
if (datasourceConfig == null) {
return null;
}
String tpl = "%s(%s:%s)";
return String.format(tpl, datasourceConfig.getDbName(), datasourceConfig.getHost(), datasourceConfig.getPort());
}
private List<String> listTemplateNames(List<Integer> idList) {
return templateConfigService.listTemplate(idList)
.stream()
.map(TemplateConfig::getName)
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,41 @@
package com.gitee.gen.controller;
import com.gitee.gen.common.Action;
import com.gitee.gen.common.GeneratorParam;
import com.gitee.gen.common.Result;
import com.gitee.gen.entity.DatasourceConfig;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.service.DatasourceConfigService;
import com.gitee.gen.service.GeneratorService;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
/**
* @author tanghc
*/
@Controller
@Mapping("generate")
public class GeneratorController {
@Inject
private DatasourceConfigService datasourceConfigService;
@Inject
private GeneratorService generatorService;
/**
* 生成代码
*
* @param generatorParam 生成参数
* @return 返回代码内容
*/
@Mapping("/code")
public Result code(GeneratorParam generatorParam) {
int datasourceConfigId = generatorParam.getDatasourceConfigId();
DatasourceConfig datasourceConfig = datasourceConfigService.getById(datasourceConfigId);
GeneratorConfig generatorConfig = GeneratorConfig.build(datasourceConfig);
return Action.ok(generatorService.generate(generatorParam, generatorConfig, null));
}
}

View File

@@ -0,0 +1,25 @@
package com.gitee.gen.controller;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Get;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.ModelAndView;
@Controller
public class HomeController {
private static final ModelAndView INDEX_VIEW = new ModelAndView("index.html");
@Get
@Mapping("/")
public void index(Context context) {
context.redirect("index.html");
}
@Mapping("/index")
public ModelAndView index2() {
return INDEX_VIEW;
}
}

View File

@@ -0,0 +1,90 @@
package com.gitee.gen.controller;
import com.gitee.gen.common.Action;
import com.gitee.gen.common.Result;
import com.gitee.gen.entity.TemplateConfig;
import com.gitee.gen.entity.TemplateGroup;
import com.gitee.gen.service.TemplateConfigService;
import com.gitee.gen.service.TemplateGroupService;
import com.gitee.gen.util.TemplateMetaUtils;
import org.apache.commons.lang.StringUtils;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.annotation.Path;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author tanghc
*/
@Controller
@Mapping("template")
public class TemplateConfigController {
@Inject
private TemplateConfigService templateConfigService;
@Inject
private TemplateGroupService templateGroupService;
@Mapping("/add")
public Result add(TemplateConfig templateConfig) {
templateConfigService.insert(templateConfig);
return Action.ok(templateConfig);
}
@Mapping("/get/{id}")
public Result get(@Path("id") int id) {
return Action.ok(templateConfigService.getById(id));
}
@Mapping("/list")
public Result list(String groupId) {
List<TemplateConfig> templateConfigs = null;
if(StringUtils.isEmpty(groupId)){
templateConfigs = templateConfigService.listAll();
}else {
templateConfigs = templateConfigService.listByGroupId(groupId);
}
Map<Integer, String> idMap = templateGroupService.listAll()
.stream()
.collect(Collectors.toMap(TemplateGroup::getId, TemplateGroup::getGroupName));
for (TemplateConfig templateConfig : templateConfigs) {
Integer gid = templateConfig.getGroupId();
if (gid != null) {
String groupName = idMap.getOrDefault(gid, "");
templateConfig.setGroupName(groupName);
}
templateConfig.setContent(TemplateMetaUtils.generateMetaContent(templateConfig));
}
return Action.ok(templateConfigs);
}
@Mapping("/update")
public Result update(TemplateConfig templateConfig) {
templateConfigService.update(templateConfig);
return Action.ok();
}
@Mapping("/del")
public Result del(TemplateConfig templateConfig) {
templateConfigService.delete(templateConfig);
return Action.ok();
}
@Mapping("/save")
public Result save(TemplateConfig templateConfig) {
templateConfigService.save(templateConfig);
return Action.ok();
}
@Mapping("/copy")
public Result copy(TemplateConfig templateConfig) {
templateConfigService.copy(templateConfig);
return Action.ok();
}
}

View File

@@ -0,0 +1,95 @@
package com.gitee.gen.controller;
import com.gitee.gen.common.Action;
import com.gitee.gen.common.Result;
import com.gitee.gen.entity.TemplateGroup;
import com.gitee.gen.service.TemplateGroupService;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.annotation.Path;
import java.util.List;
import java.util.Objects;
/**
* @author : zsljava
* @date Date : 2020-12-15 9:51
* @Description: TODO
*/
@Controller
@Mapping("group")
public class TemplateGroupController {
@Inject
private TemplateGroupService templateGroupService;
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
@Mapping("list")
public Result listAll() {
List<TemplateGroup> templateGroups = templateGroupService.listAll();
return Action.ok(templateGroups);
}
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
@Mapping("get/{id}")
public Result get(@Path("id") int id) {
TemplateGroup group = templateGroupService.getById(id);
return Action.ok(group);
}
/**
* 新增忽略null字段
*
* @param templateGroup 新增的记录
* @return 返回影响行数
*/
@Mapping("add")
public Result insert(TemplateGroup templateGroup) {
TemplateGroup group = templateGroupService.getByName(templateGroup.getGroupName());
if (group != null) {
throw new RuntimeException(templateGroup.getGroupName() + " 已存在");
}
templateGroupService.insertIgnoreNull(templateGroup);
return Action.ok(templateGroup);
}
/**
* 修改忽略null字段
*
* @param templateGroup 修改的记录
* @return 返回影响行数
*/
@Mapping("update")
public Result update(TemplateGroup templateGroup) {
TemplateGroup group = templateGroupService.getByName(templateGroup.getGroupName());
if (group != null && !Objects.equals(group.getId(), templateGroup.getId())) {
throw new RuntimeException(templateGroup.getGroupName() + " 已存在");
}
templateGroupService.updateIgnoreNull(templateGroup);
return Action.ok();
}
/**
* 删除记录
*
* @param templateGroup 待删除的记录
* @return 返回影响行数
*/
@Mapping("del")
public Result delete(TemplateGroup templateGroup) {
templateGroupService.deleteGroup(templateGroup);
return Action.ok();
}
}

View File

@@ -0,0 +1,56 @@
package com.gitee.gen.controller;
import com.gitee.gen.common.Action;
import com.gitee.gen.common.Result;
import com.gitee.gen.entity.TypeConfig;
import com.gitee.gen.service.TypeConfigService;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
import java.util.List;
@Controller
@Mapping("type")
public class TypeConfigController {
@Inject
private TypeConfigService typeConfigService;
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
@Mapping("list")
public Result listAll() {
return Action.ok(typeConfigService.listAll());
}
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
@Mapping("getById")
public TypeConfig getById(Integer id) {
return typeConfigService.getById(id);
}
/**
* 修改忽略null字段
*
* @param typeConfigList 修改的记录
* @return 返回影响行数
*/
@Mapping("update")
public Result update(List<TypeConfig> typeConfigList) {
for (TypeConfig typeConfig : typeConfigList) {
typeConfigService.updateIgnoreNull(typeConfig);
}
return Action.ok();
}
}

View File

@@ -0,0 +1,66 @@
package com.gitee.gen.controller.vo;
import com.gitee.gen.common.GeneratorParam;
import java.util.List;
/**
* @author tanghc
*/
public class GenerateHistoryVO {
/*
{
"datasourceConfigId": 1,
"tableNames": [
"datasource_config",
"generate_history"
],
"templateConfigIdList": [
1
],
"packageName": "com.gitee.gen",
"delPrefix": "template_",
"groupId": "",
"groupName": "JPA"
}
*/
private GeneratorParam configContent;
private String generateTime;
private String datasource;
private List<String> templateNames;
public GeneratorParam getConfigContent() {
return configContent;
}
public void setConfigContent(GeneratorParam configContent) {
this.configContent = configContent;
}
public String getGenerateTime() {
return generateTime;
}
public void setGenerateTime(String generateTime) {
this.generateTime = generateTime;
}
public String getDatasource() {
return datasource;
}
public void setDatasource(String datasource) {
this.datasource = datasource;
}
public List<String> getTemplateNames() {
return templateNames;
}
public void setTemplateNames(List<String> templateNames) {
this.templateNames = templateNames;
}
}

View File

@@ -0,0 +1,27 @@
package com.gitee.gen.entity;
/**
* @author tanghc
*/
public class ColumnInfo {
/** 字段名 */
private String name;
/** 字段类型 */
private String type;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}

View File

@@ -0,0 +1,219 @@
package com.gitee.gen.entity;
import java.util.Objects;
/**
* 数据源配置表
*/
public class DatasourceConfig {
private Integer id;
/**
* 数据库类型
*/
private Integer dbType;
/** 数据库驱动 */
private String driverClass;
/** 数据库别名 */
private String dbDesc;
/** 数据库名称 */
private String dbName;
/** schema(PGSQL专用) */
private String schemaName;
/** 数据库host */
private String host;
/** 数据库端口 */
private Integer port;
/** 数据库用户名 */
private String username;
/** 数据库密码 */
private String password;
/** 是否已删除1已删除0未删除 */
private Integer isDeleted;
/** 包名*/
private String packageName;
/** 删除的前缀*/
private String delPrefix;
/** 代码生成器模板组id*/
private Integer groupId;
/** 作者名*/
private String author;
/** 数据库分组名称 */
private String dbGroupName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getDbType() {
return dbType;
}
public void setDbType(Integer dbType) {
this.dbType = dbType;
}
public String getDriverClass() {
return driverClass;
}
public void setDriverClass(String driverClass) {
this.driverClass = driverClass;
}
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getIsDeleted() {
return isDeleted;
}
public void setIsDeleted(Integer isDeleted) {
this.isDeleted = isDeleted;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getDelPrefix() {
return delPrefix;
}
public void setDelPrefix(String delPrefix) {
this.delPrefix = delPrefix;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public String getSchemaName() {
return schemaName;
}
public void setSchemaName(String schemaName) {
this.schemaName = schemaName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getDbDesc() {
return dbDesc;
}
public void setDbDesc(String dbDesc) {
this.dbDesc = dbDesc;
}
public String getDbGroupName() {
return dbGroupName;
}
public void setDbGroupName(String dbGroupName) {
this.dbGroupName = dbGroupName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DatasourceConfig that = (DatasourceConfig) o;
return Objects.equals(id, that.id) &&
Objects.equals(dbDesc, that.dbDesc) &&
Objects.equals(dbType, that.dbType) &&
Objects.equals(driverClass, that.driverClass) &&
Objects.equals(dbName, that.dbName) &&
Objects.equals(host, that.host) &&
Objects.equals(port, that.port) &&
Objects.equals(username, that.username) &&
Objects.equals(password, that.password) &&
Objects.equals(isDeleted, that.isDeleted) &&
Objects.equals(packageName, that.packageName) &&
Objects.equals(delPrefix, that.delPrefix) &&
Objects.equals(groupId, that.groupId) &&
Objects.equals(author, that.author) &&
Objects.equals(dbGroupName, that.dbGroupName);
}
@Override
public int hashCode() {
return Objects.hash(id, dbType, dbDesc, driverClass, dbName, host, port, username, password, isDeleted, packageName, delPrefix, groupId, author, dbGroupName);
}
@Override
public String toString() {
return "DatasourceConfig{" +
"id=" + id +
", dbType=" + dbType +
", dbDesc=" + dbDesc +
", driverClass='" + driverClass + '\'' +
", dbName='" + dbName + '\'' +
", host='" + host + '\'' +
", port=" + port +
", username='" + username + '\'' +
", password='" + password + '\'' +
", isDeleted=" + isDeleted +
", packageName='" + packageName + '\'' +
", delPrefix='" + delPrefix + '\'' +
", groupId='" + groupId + '\'' +
", author='" + author + '\'' +
", dbGroupName='" + dbGroupName + '\'' +
'}';
}
}

View File

@@ -0,0 +1,67 @@
package com.gitee.gen.entity;
import java.util.Date;
public class GenerateHistory {
private Integer id;
private String configContent;
private String md5Value;
private Date generateTime;
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return this.id;
}
public void setConfigContent(String configContent) {
this.configContent = configContent;
}
public String getConfigContent() {
return this.configContent;
}
public void setMd5Value(String md5Value) {
this.md5Value = md5Value;
}
public String getMd5Value() {
return this.md5Value;
}
public Date getGenerateTime() {
return generateTime;
}
public void setGenerateTime(Date generateTime) {
this.generateTime = generateTime;
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) {return false;}
GenerateHistory that = (GenerateHistory) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return java.util.Objects.hash(id);
}
@Override
public String toString() {
return "GenerateHistory{" +
"id=" + id +
",configContent='" + configContent + "'" +
",md5Value='" + md5Value + "'" +
",generateTime='" + generateTime + "'" +
'}';
}
}

View File

@@ -0,0 +1,72 @@
package com.gitee.gen.entity;
/**
* 系统配置表
*/
public class SystemConfig {
private Integer id;
/** 配置项 */
private String configKey;
/** 配置值 */
private String configValue;
/** 备注 */
private String remark;
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return this.id;
}
public void setConfigKey(String configKey) {
this.configKey = configKey;
}
public String getConfigKey() {
return this.configKey;
}
public void setConfigValue(String configValue) {
this.configValue = configValue;
}
public String getConfigValue() {
return this.configValue;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getRemark() {
return this.remark;
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) {return false;}
SystemConfig that = (SystemConfig) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return java.util.Objects.hash(id);
}
@Override
public String toString() {
return "SystemConfig{" +
",id='" + id + "'" +
",configKey='" + configKey + "'" +
",configValue='" + configValue + "'" +
",remark='" + remark + "'" +
'}';
}
}

View File

@@ -0,0 +1,149 @@
package com.gitee.gen.entity;
/**
* 模板表
*/
public class TemplateConfig {
private Integer id;
private Integer groupId;
private String groupName;
/** 模板名称 */
private String name;
/**
* 目录
*/
private String folder;
/** 文件名称 */
private String fileName;
/** 内容 */
private String content;
/** 是否删除1已删除0未删除 */
private Integer isDeleted;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Integer getIsDeleted() {
return isDeleted;
}
public void setIsDeleted(Integer isDeleted) {
this.isDeleted = isDeleted;
}
public String getFolder() {
return folder;
}
public void setFolder(String folder) {
this.folder = folder;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof TemplateConfig)) {
return false;
}
TemplateConfig that = (TemplateConfig) o;
if (id != null ? !id.equals(that.id) : that.id != null) {
return false;
}
if (groupId != null ? !groupId.equals(that.groupId) : that.groupId != null) {
return false;
}
if (groupName != null ? !groupName.equals(that.groupName) : that.groupName != null) {
return false;
}
if (name != null ? !name.equals(that.name) : that.name != null) {
return false;
}
if (folder != null ? !folder.equals(that.folder) : that.folder != null) {
return false;
}
if (fileName != null ? !fileName.equals(that.fileName) : that.fileName != null) {
return false;
}
if (content != null ? !content.equals(that.content) : that.content != null) {
return false;
}
return isDeleted != null ? isDeleted.equals(that.isDeleted) : that.isDeleted == null;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (groupId != null ? groupId.hashCode() : 0);
result = 31 * result + (groupName != null ? groupName.hashCode() : 0);
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (folder != null ? folder.hashCode() : 0);
result = 31 * result + (fileName != null ? fileName.hashCode() : 0);
result = 31 * result + (content != null ? content.hashCode() : 0);
result = 31 * result + (isDeleted != null ? isDeleted.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "TemplateConfig{" +
"id=" + id +
", groupId=" + groupId +
", groupName='" + groupName + '\'' +
", name='" + name + '\'' +
", folder='" + folder + '\'' +
", fileName='" + fileName + '\'' +
", content='" + content + '\'' +
", isDeleted=" + isDeleted +
'}';
}
}

View File

@@ -0,0 +1,60 @@
package com.gitee.gen.entity;
/**
* @author : zsljava
* @date Date : 2020-12-15 9:49
* @Description: TODO
*/
public class TemplateGroup {
private Integer id;
private String groupName;
private Integer isDeleted;
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return this.id;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getGroupName() {
return this.groupName;
}
public void setIsDeleted(Integer isDeleted) {
this.isDeleted = isDeleted;
}
public Integer getIsDelete() {
return this.isDeleted;
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) {return false;}
TemplateGroup that = (TemplateGroup) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return java.util.Objects.hash(id);
}
@Override
public String toString() {
return "TemplateGroup{" +
"id=" + id +
",groupName='" + groupName + "'" +
",isDelete='" + isDeleted + "'" +
'}';
}
}

View File

@@ -0,0 +1,72 @@
package com.gitee.gen.entity;
/**
* 字段类型配置表
*/
public class TypeConfig {
private Integer id;
/** 数据库类型 */
private String dbType;
/** 基本类型 */
private String baseType;
/** 装箱类型 */
private String boxType;
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return this.id;
}
public void setDbType(String dbType) {
this.dbType = dbType;
}
public String getDbType() {
return this.dbType;
}
public void setBaseType(String baseType) {
this.baseType = baseType;
}
public String getBaseType() {
return this.baseType;
}
public void setBoxType(String boxType) {
this.boxType = boxType;
}
public String getBoxType() {
return this.boxType;
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) {return false;}
TypeConfig that = (TypeConfig) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return java.util.Objects.hash(id);
}
@Override
public String toString() {
return "TypeConfig{" +
"id=" + id +
",dbType='" + dbType + "'" +
",baseType='" + baseType + "'" +
",boxType='" + boxType + "'" +
'}';
}
}

View File

@@ -0,0 +1,33 @@
package com.gitee.gen.gen;
public class CodeFile {
private String folder;
private String fileName;
private String content;
public String getFolder() {
return folder;
}
public void setFolder(String folder) {
this.folder = folder;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@@ -0,0 +1,328 @@
package com.gitee.gen.gen;
import com.gitee.gen.gen.converter.ColumnTypeConverter;
import com.gitee.gen.util.FieldUtil;
import com.gitee.gen.util.SqlTypeUtil;
import com.gitee.gen.util.StringUtil;
import org.apache.commons.lang.StringUtils;
/**
* 表字段信息
*/
public class ColumnDefinition {
/**
* 数据库字段名
*/
private String columnName;
/**
* 数据库类型
*/
private String type;
/**
* 是否自增
*/
private Boolean isIdentity;
/**
* 是否主键
*/
private Boolean isPk;
/**
* 字段注释
*/
private String comment;
/**
* 字段长度
*/
private Integer maxLength;
/**
* 小数位长度
*/
private Integer scale;
/**
* 字段是否允许为null
*/
private boolean isNullable;
private ColumnTypeConverter columnTypeConverter;
public void setColumnTypeConverter(ColumnTypeConverter columnTypeConverter) {
this.columnTypeConverter = columnTypeConverter;
}
/**
* 数据库字段名首字母小写
* @return
*/
public String getColumnNameLF() {
return FieldUtil.lowerFirstLetter(this.columnName);
}
public String getLabel() {
return StringUtils.isNotBlank(comment) ? comment : getNameCamel();
}
public void setMaxLength(Integer maxLength) {
this.maxLength = maxLength;
}
public void setScale(Integer scale) {
this.scale = scale;
}
public Integer getMaxLength() {
return maxLength;
}
public Integer getScale() {
return scale;
}
/**
* 获得基本类型,int,float
*
* @return 返回基本类型
*/
public String getFieldType() {
return getColumnTypeConverter().convertType(type);
}
/**
* 获得基本类型,int,float
*
* @return 返回基本类型
*/
public String getTypeBase() {
return getFieldType();
}
/**
* 获得装箱类型,Integer,Float
*
* @return 返回装箱类型
*/
public String getFieldTypeBox() {
return getColumnTypeConverter().convertTypeBox(getType());
}
/**
* 获得装箱类型,Integer,Float
*
* @return 返回装箱类型
*/
public String getTypeBox() {
return getFieldTypeBox();
}
public String getMybatisJdbcType() {
return SqlTypeUtil.TYPE_MYBATIS_MAP.getOrDefault(getType(), "VARCHAR");
}
/**
* 返回java字段名,并且第一个字母大写
*
* @return 返回字段名
* @see #getNamePascal()
*/
@Deprecated
public String getJavaFieldNameUF() {
return FieldUtil.upperFirstLetter(getJavaFieldName());
}
// ---- name start ----
/**
* 返回表字段名
* @return
*/
public String getName() {
return getColumnName();
}
/**
* 返回java字段
*
* @return 返回java字段
* @see #getNameCamel()
*/
@Deprecated
public String getJavaFieldName() {
String fieldName = FieldUtil.underlineFilter(getColumnName());
if(StringUtils.isEmpty(fieldName)){
return fieldName;
}
fieldName = fieldName.replaceAll("_", "");
return FieldUtil.lowerFirstLetter(fieldName);
}
/**
* 小驼峰命名userAge
* @return
*/
public String getNameCamel() {
return getJavaFieldName();
}
/**
* 大驼峰命名UserAge
* @return
*/
public String getNamePascal() {
return FieldUtil.upperFirstLetter(getJavaFieldName());
}
/**
* 蛇形命名user_age
* @return
*/
public String getNameSnake() {
String name = getColumnName();
name = StringUtil.trimTrailingCharacter(name, '_');
name = StringUtil.trimLeadingCharacter(name, '_');
return name.toLowerCase();
}
/**
* 蛇形命名大写USER_AGE
* @return
*/
public String getNameSnakeBig() {
return getNameSnake().toUpperCase();
}
/**
* 烤串命名user-name
* @return
*/
public String getNameKebab() {
String name = this.getNameSnake();
return name.replace('_', '-');
}
/**
* 烤串命名大写USER-AGE
* @return
*/
public String getNameKebabBig() {
return this.getNameKebab().toUpperCase();
}
/**
* 帕斯卡蛇形命名User_Age
* @return
*/
public String getNamePascalSnake() {
String fieldNameSnake = this.getNameSnake();
String[] split = fieldNameSnake.split("_");
for (int i = 0; i < split.length; i++) {
split[i] = FieldUtil.upperFirstLetter(split[i]);
}
return String.join("_", split);
}
/**
* 帕斯卡烤串命名User-Age
* @return
*/
public String getNamePascalKebab() {
String fieldNameSnake = this.getNameSnake();
String[] split = fieldNameSnake.split("_");
for (int i = 0; i < split.length; i++) {
split[i] = FieldUtil.upperFirstLetter(split[i]);
}
return String.join("-", split);
}
// ---- name end ----
/**
* 获得基本类型,int,float
*
* @return 返回基本类型
*/
public String getJavaType() {
return getFieldType();
}
/**
* 获得装箱类型,Integer,Float
*
* @return 返回装箱类型
*/
public String getJavaTypeBox() {
return getFieldTypeBox();
}
/**
* 是否是自增主键
*
* @return true, 是自增主键
*/
public boolean getIsIdentityPk() {
return getIsPk() && getIsIdentity();
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Boolean getIsIdentity() {
return isIdentity;
}
public void setIsIdentity(Boolean isIdentity) {
this.isIdentity = isIdentity;
}
public Boolean getIsPk() {
return isPk;
}
public void setIsPk(Boolean isPk) {
this.isPk = isPk;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
if (comment == null) {
comment = "";
}
this.comment = comment;
}
public ColumnTypeConverter getColumnTypeConverter() {
return columnTypeConverter;
}
public Boolean getIsNullable() {
return isNullable;
}
public void setIsNullable(Boolean isNullable) {
this.isNullable = isNullable;
}
}

View File

@@ -0,0 +1,52 @@
package com.gitee.gen.gen;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 表信息查询
*/
public abstract class ColumnSelector {
private GeneratorConfig generatorConfig;
public ColumnSelector(GeneratorConfig generatorConfig){
this.generatorConfig = generatorConfig;
}
/**
* 返回查询表字段信息的SQL语句,不同的数据查询表信息不一样
* 如mysql是DESC tableName
* @return
*/
protected abstract String getColumnInfoSQL(String tableName);
/**
* 构建列信息
* @param rowMap
* @return
*/
protected abstract ColumnDefinition buildColumnDefinition(Map<String, Object> rowMap);
public List<ColumnDefinition> getColumnDefinitions(String tableName) {
List<Map<String, Object>> resultList = SqlHelper.runSql(this.getGeneratorConfig(), getColumnInfoSQL(tableName));
List<ColumnDefinition> columnDefinitionList = new ArrayList<ColumnDefinition>(resultList.size());
// 构建columnDefinition
for (Map<String, Object> rowMap : resultList) {
columnDefinitionList.add(buildColumnDefinition(rowMap));
}
return columnDefinitionList;
}
public GeneratorConfig getGeneratorConfig() {
return generatorConfig;
}
public void setGeneratorConfig(GeneratorConfig generatorConfig) {
this.generatorConfig = generatorConfig;
}
}

View File

@@ -0,0 +1,27 @@
package com.gitee.gen.gen;
import com.gitee.gen.gen.converter.ColumnTypeConverter;
import com.gitee.gen.gen.converter.CsharpColumnTypeConverter;
import com.gitee.gen.util.FieldUtil;
/**
* 提供C# Velocity变量
* @author tanghc
*/
public class CsharpColumnDefinition extends ColumnDefinition {
private static final ColumnTypeConverter COLUMN_TYPE_CONVERTER = new CsharpColumnTypeConverter();
public String getField() {
return FieldUtil.underlineFilter(getColumnName());
}
public String getProperty() {
return FieldUtil.upperFirstLetter(getField());
}
@Override
public ColumnTypeConverter getColumnTypeConverter() {
return COLUMN_TYPE_CONVERTER;
}
}

View File

@@ -0,0 +1,50 @@
package com.gitee.gen.gen;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConnect {
public static Connection getConnection(GeneratorConfig config) throws ClassNotFoundException, SQLException {
Class.forName(config.getDriverClass());
return DriverManager.getConnection(config.getJdbcUrl(),
config.getUsername(), config.getPassword());
}
/**
* 测试连接,返回错误信息,无返回内容说明连接成功
*
* @param generatorConfig 数据源配置
* @return 返回错误信息, 无返回内容说明连接成功
*/
public static String testConnection(GeneratorConfig generatorConfig) {
Connection con = null;
String ret = null;
try {
con = DBConnect.getConnection(generatorConfig);
// 不为空说明连接成功
if (con == null) {
ret = generatorConfig.getDbName() + "连接失败";
}
} catch (ClassNotFoundException e) {
ret = generatorConfig.getDbName() + "连接失败" + ""
+ "找不到驱动" + generatorConfig.getDriverClass();
} catch (SQLException e) {
ret = generatorConfig.getDbName() + "连接失败" + ""
+ e.getMessage();
} finally {
if (con != null) {
try {
con.close(); // 关闭连接,该连接无实际用处
} catch (SQLException e) {
e.printStackTrace();
ret = e.getMessage();
}
}
}
return ret;
}
}

View File

@@ -0,0 +1,77 @@
package com.gitee.gen.gen;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author tanghc
*/
public class DataSourceManager {
private static final Logger logger = LoggerFactory.getLogger(DataSourceManager.class);
private static final Map<String, DataSource> DATA_SOURCE_MAP = new ConcurrentHashMap<>(16);
public static Connection getConnection(GeneratorConfig generatorConfig) {
try {
return getDataSource(generatorConfig).getConnection();
} catch (SQLException e) {
logger.error("获取Connection失败, jdbcUrl:{}", generatorConfig.getJdbcUrl(), e);
throw new RuntimeException("获取Connection失败", e);
}
}
public static void closeConnection(Connection connection) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
logger.error("close connection error", e);
}
}
}
public static DataSource getDataSource(GeneratorConfig generatorConfig) {
String jdbcUrl = generatorConfig.getJdbcUrl() + ":" + generatorConfig.getUsername();
DataSource dataSource = DATA_SOURCE_MAP.computeIfAbsent(jdbcUrl, key -> {
Properties properties = new Properties();
properties.put("driverClassName", generatorConfig.getDriverClass());
properties.put("url", generatorConfig.getJdbcUrl());
properties.put("username", generatorConfig.getUsername());
properties.put("password", generatorConfig.getPassword());
// 初始连接数
properties.put("initialSize", 1);
// 最大活跃数
properties.put("maxTotal", 30);
properties.put("minIdle", 5);
properties.put("maxIdle", 10);
// 最长等待时间(毫秒)
properties.put("maxWaitMillis", 1000);
// 程序中的连接不使用后是否被连接池回收
properties.put("removeAbandonedOnMaintenance", true);
properties.put("removeAbandonedOnBorrow", true);
// 连接在所指定的秒数内未使用才会被删除(秒)
properties.put("removeAbandonedTimeout", 5);
try {
return BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
logger.error("create datasource error, jdbcUr={}", jdbcUrl, e);
return null;
}
});
if (dataSource == null) {
throw new RuntimeException("连接数据库失败");
}
return dataSource;
}
}

View File

@@ -0,0 +1,73 @@
package com.gitee.gen.gen;
/**
* 改成配在app.yml中
*
* @author tanghc
*/
@Deprecated
public enum DbType {
MYSQL(1,
"MySQL",
"com.mysql.cj.jdbc.Driver",
"jdbc:mysql://%s:%s/%s?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"
),
ORACLE(2,
"Oracle",
"oracle.jdbc.driver.OracleDriver",
"jdbc:oracle:thin:@%s:%s%s"),
SQL_SERVER(3,
"SQL Server",
"com.microsoft.sqlserver.jdbc.SQLServerDriver",
"jdbc:sqlserver://%s:%s;DatabaseName=%s;trustServerCertificate=true"),
POSTGRE_SQL(4,
"PostgreSQL",
"org.postgresql.Driver",
"jdbc:postgresql://%s:%s/%s"),
DM(5,
"DM",
"dm.jdbc.driver.DmDriver",
"jdbc:dm://%s:%s/%s"),
;
private final int type;
private final String displayName;
private final String driverClass;
private final String jdbcUrl;
DbType(int type, String displayName, String driverClass, String jdbcUrl) {
this.type = type;
this.displayName = displayName;
this.driverClass = driverClass;
this.jdbcUrl = jdbcUrl;
}
public static DbType of(int type) {
for (DbType value : DbType.values()) {
if (value.type == type) {
return value;
}
}
return null;
}
public String getDisplayName() {
return displayName;
}
public String getJdbcUrl() {
return jdbcUrl;
}
public int getType() {
return type;
}
public String getDriverClass() {
return driverClass;
}
}

View File

@@ -0,0 +1,128 @@
package com.gitee.gen.gen;
import com.gitee.gen.config.ConnectConfig;
import com.gitee.gen.config.DbTypeConfig;
import com.gitee.gen.entity.DatasourceConfig;
import org.noear.snack.core.utils.StringUtil;
public class GeneratorConfig {
private Integer dbType;
/** 数据库名称 */
private String dbName;
/** schema(PGSQL专用) */
private String schemaName;
/**
* 驱动class
*/
private String driverClass;
/** 数据库host */
private String host;
/** 数据库端口 */
private Integer port;
/** 数据库用户名 */
private String username;
/** 数据库密码 */
private String password;
public static GeneratorConfig build(DatasourceConfig datasourceConfig) {
GeneratorConfig generatorConfig = new GeneratorConfig();
generatorConfig.setDbName(datasourceConfig.getDbName());
generatorConfig.setDbType(datasourceConfig.getDbType());
generatorConfig.setHost(datasourceConfig.getHost());
generatorConfig.setPort(datasourceConfig.getPort());
generatorConfig.setUsername(datasourceConfig.getUsername());
generatorConfig.setPassword(datasourceConfig.getPassword());
generatorConfig.setSchemaName(datasourceConfig.getSchemaName());
String driver = datasourceConfig.getDriverClass();
if (StringUtil.isEmpty(driver)) {
ConnectConfig connectConfig = DbTypeConfig.getInstance().getConnectConfig(datasourceConfig.getDbType());
driver = connectConfig.getDriver();
}
generatorConfig.setDriverClass(driver);
return generatorConfig;
}
public String getJdbcUrl() {
ConnectConfig connectConfig = DbTypeConfig.getInstance().getConnectConfig(dbType);
if (dbType == null) {
throw new RuntimeException("不支持数据库类型" + this.dbType + ",请在 app.yml 中配置");
}
String jdbcUrl = connectConfig.getUrl();
// jdbc:mysql://{HOST}:{PORT}/{DB_NAME}?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
jdbcUrl = jdbcUrl.replace("{HOST}", host);
jdbcUrl = jdbcUrl.replace("{PORT}", String.valueOf(port));
jdbcUrl = jdbcUrl.replace("{DB_NAME}", dbName);
return jdbcUrl;
}
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public Integer getDbType() {
return dbType;
}
public void setDbType(Integer dbType) {
this.dbType = dbType;
}
public void setPort(Integer port) {
this.port = port;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSchemaName() {
return schemaName;
}
public void setSchemaName(String schemaName) {
this.schemaName = schemaName;
}
public void setDriverClass(String driverClass) {
this.driverClass = driverClass;
}
public String getDriverClass() {
return driverClass;
}
}

View File

@@ -0,0 +1,86 @@
package com.gitee.gen.gen;
import com.gitee.gen.gen.converter.ColumnTypeConverter;
import com.gitee.gen.gen.converter.JavaColumnTypeConverter;
import com.gitee.gen.util.FieldUtil;
import org.apache.commons.lang.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @author tanghc
*/
public class JavaColumnDefinition extends ColumnDefinition {
private static final JavaColumnTypeConverter COLUMN_TYPE_CONVERTER = new JavaColumnTypeConverter();
private static final Map<String, String> TYPE_MYBATIS_MAP = new HashMap<>(64);
static {
TYPE_MYBATIS_MAP.put(TypeEnum.BIT.getType(), "BOOLEAN");
TYPE_MYBATIS_MAP.put(TypeEnum.BOOLEAN.getType(), "BOOLEAN");
TYPE_MYBATIS_MAP.put(TypeEnum.TINYINT.getType(), "TINYINT");
TYPE_MYBATIS_MAP.put(TypeEnum.SMALLINT.getType(), "INTEGER");
TYPE_MYBATIS_MAP.put(TypeEnum.INT.getType(), "INTEGER");
TYPE_MYBATIS_MAP.put(TypeEnum.BIGINT.getType(), "BIGINT");
TYPE_MYBATIS_MAP.put(TypeEnum.FLOAT.getType(), "FLOAT");
TYPE_MYBATIS_MAP.put(TypeEnum.DOUBLE.getType(), "DOUBLE");
TYPE_MYBATIS_MAP.put(TypeEnum.DECIMAL.getType(), "DECIMAL");
TYPE_MYBATIS_MAP.put(TypeEnum.VARCHAR.getType(), "VARCHAR");
TYPE_MYBATIS_MAP.put(TypeEnum.DATETIME.getType(), "TIMESTAMP");
TYPE_MYBATIS_MAP.put(TypeEnum.BLOB.getType(), "BLOB");
}
public String getMybatisJdbcType() {
return TYPE_MYBATIS_MAP.getOrDefault(getType(), "VARCHAR");
}
/**
* 返回java字段名,并且第一个字母大写
*
* @return 返回字段名
*/
public String getJavaFieldNameUF() {
return FieldUtil.upperFirstLetter(getJavaFieldName());
}
/**
* 返回java字段
*
* @return 返回java字段
*/
public String getJavaFieldName() {
String fieldName = FieldUtil.underlineFilter(getColumnName());
if(StringUtils.isEmpty(fieldName)){
return fieldName;
}
fieldName = fieldName.replaceAll("_", "");
return fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
}
/**
* 获得基本类型,int,float
*
* @return 返回基本类型
*/
public String getJavaType() {
return getFieldType();
}
/**
* 获得装箱类型,Integer,Float
*
* @return 返回装箱类型
*/
public String getJavaTypeBox() {
return getFieldTypeBox();
}
@Override
public ColumnTypeConverter getColumnTypeConverter() {
return COLUMN_TYPE_CONVERTER;
}
}

View File

@@ -0,0 +1,299 @@
package com.gitee.gen.gen;
import com.gitee.gen.common.IdWorker;
import com.gitee.gen.util.FieldUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.RandomUtils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Properties;
import java.util.UUID;
/**
* SQL上下文,这里可以取到表,字段信息<br>
* 最终会把SQL上下文信息放到velocity中
*/
public class SQLContext {
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
private final LocalDateTime localDateTime = LocalDateTime.now();
/**
* 表结构定义
*/
private final TableDefinition tableDefinition;
private final ColumnDefinition javaPkColumn;
/**
* 包名
*/
private String packageName;
/**
* 包的子路径
*/
private String packageSubPath;
/**
* 删除的前缀
*/
private String delPrefix;
/**
* 数据库名
*/
private String dbName;
/**
* 作者名
*/
private String author;
private Properties extConfig;
public SQLContext(TableDefinition tableDefinition) {
this.tableDefinition = tableDefinition;
// 默认为全字母小写的类名
this.packageName = getJavaBeanName().toLowerCase();
this.javaPkColumn = this.tableDefinition.getPkColumn();
}
public String getDbNameCamel() {
return FieldUtil.underlineFilter(getDbName());
}
/**
* 干净的库名(移除下划线,横杠,点)并小写
* @return
*/
public String getDbNameClean() {
return getDbName().replace("_", "")
.replace("-", "")
.replace(".", "").toLowerCase();
}
public String getDatetime() {
return localDateTime.format(DATE_TIME_FORMATTER);
}
public String getDate() {
return localDateTime.format(DATE_FORMATTER);
}
public String getTime() {
return localDateTime.format(TIME_FORMATTER);
}
public int getRandomInt() {
return RandomUtils.nextInt(Integer.MAX_VALUE);
}
public long getRandomLong() {
return RandomUtils.nextLong();
}
public boolean getRandomBoolean() {
return RandomUtils.nextBoolean();
}
public String getUuid() {
return UUID.randomUUID().toString();
}
public long getNextId() {
return IdWorker.getInstance().nextId();
}
/**
* 返回Java类名
*
* @return
*/
public String getJavaBeanName() {
return getClassName();
}
/**
* 返回类名 UserInfo
* @return
*/
public String getClassName() {
String tableName = getJavaBeanNameLF();
return FieldUtil.upperFirstLetter(tableName);
}
/**
* 返回Java类名且首字母小写
*
* @return
*/
public String getJavaBeanNameLF() {
String tableName = tableDefinition.getTableName();
if(delPrefix != null){
String[] split = delPrefix.split("\\s*,\\s*");
for (String prefix : split){
tableName = StringUtils.removeStart(tableName, prefix);
}
}
tableName = FieldUtil.underlineFilter(tableName);
tableName = FieldUtil.dotFilter(tableName);
return FieldUtil.lowerFirstLetter(tableName);
}
/**
* 返回类名UserInfo
* @return 类名
*/
public String getClassNamePascal() {
return getClassName();
}
/**
* 返回类名且首字母小写userInfo
* @return 类名
*/
public String getClassNameCamel() {
return getJavaBeanNameLF();
}
/**
* 返回类名且小写userinfo
* @return 类名
*/
public String getClassNameLower() {
return getClassName().toLowerCase();
}
/**
* 小写类名且横杠相连user-info
* @return 类名
*/
public String getClassNameKebab() {
return getJavaBeanNameHB();
}
/**
* 返回类名且横杠相连User-Info
* @return 类名
*/
public String getClassNamePascalKebab() {
String tableName = tableDefinition.getTableName();
String[] split = tableName.split("_");
for (int i = 0; i < split.length; i++) {
split[i] = FieldUtil.upperFirstLetter(split[i]);
}
return String.join("-", split);
}
/**
* 返回Java类名全小写
*
* @return
*/
public String getJavaBeanNameL() {
return getJavaBeanNameLF().toLowerCase();
}
/**
* 返回Java类名驼峰转横杠
*
* @return User-Info
*/
public String getJavaBeanNameHB() {
String tableName = tableDefinition.getTableName();
if(delPrefix != null){
String[] split = delPrefix.split("\\s*,\\s*");
for (String prefix : split){
tableName = StringUtils.removeStart(tableName, prefix);
}
}
tableName = tableName.replace("_","-");
tableName = FieldUtil.dotFilter(tableName);
return tableName;
}
public String getPkName() {
if (javaPkColumn != null) {
return javaPkColumn.getColumnName();
}
return "";
}
public String getJavaPkName() {
if (javaPkColumn != null) {
return javaPkColumn.getJavaFieldName();
}
return "";
}
public String getJavaPkType() {
if (javaPkColumn != null) {
return javaPkColumn.getJavaType();
}
return "";
}
public String getMybatisPkType() {
if (javaPkColumn != null) {
return javaPkColumn.getMybatisJdbcType();
}
return "";
}
public TableDefinition getTableDefinition() {
return tableDefinition;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getDelPrefix() {
return delPrefix;
}
public void setDelPrefix(String delPrefix) {
this.delPrefix = delPrefix;
}
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPackageSubPath() {
return packageSubPath;
}
public void setPackageSubPath(String packageSubPath) {
this.packageSubPath = packageSubPath;
}
public Properties getExtConfig() {
return extConfig;
}
public void setExtConfig(Properties extConfig) {
this.extConfig = extConfig;
}
}

View File

@@ -0,0 +1,8 @@
package com.gitee.gen.gen;
public interface SQLService {
TableSelector getTableSelector(GeneratorConfig generatorConfig);
}

View File

@@ -0,0 +1,28 @@
package com.gitee.gen.gen;
import com.gitee.gen.config.ConnectConfig;
import com.gitee.gen.config.DbTypeConfig;
import org.noear.solon.core.util.ClassUtil;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SQLServiceFactory {
private static final Map<Integer, SQLService> SERVICE_CONFIG = new ConcurrentHashMap<>(16);
public static SQLService build(GeneratorConfig generatorConfig) {
Integer dbType = generatorConfig.getDbType();
return SERVICE_CONFIG.computeIfAbsent(dbType, k -> {
ConnectConfig connectConfig = DbTypeConfig.getInstance().getConnectConfig(dbType);
String className = connectConfig.getServiceName();
Class<?> aClass = ClassUtil.loadClass(className);
if (aClass == null) {
throw new RuntimeException("找不到数据库服务类:" + className);
}
return ClassUtil.newInstance(aClass);
});
}
}

View File

@@ -0,0 +1,106 @@
package com.gitee.gen.gen;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.ibatis.jdbc.SqlRunner;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
import org.apache.ibatis.scripting.xmltags.TextSqlNode;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 执行SQL语句的帮助类
*
* @author hc.tang
*/
public class SqlHelper {
private static final Logger logger = LoggerFactory.getLogger(SqlHelper.class);
/**
* <pre>
* String sql = "SELECT * FROM datasource_config WHERE dc_id=${id}";
*
* DataSourceConfig dataSourceConfig = new DataSourceConfig();
* dataSourceConfig.setDriverClass("com.mysql.cj.jdbc.Driver");
* dataSourceConfig.setJdbcUrl("jdbc:mysql://localhost:3306/auto_code");
* dataSourceConfig.setUsername("root");
* dataSourceConfig.setPassword("root");
*
* Map<String, Object> params = new HashMap<String, Object>();
* params.put("id", 2);
*
* List<Map<String, Object>> map = SqlHelper.runSql(dataSourceConfig, sql,params);
* </pre>
*
* @param generatorConfig 配置
* @param sql sql
* @param params 参数
* @return 返回查询结果
*/
public static List<Map<String, Object>> runSql(GeneratorConfig generatorConfig, String sql,
Map<String, Object> params) {
DataSource dataSource = DataSourceManager.getDataSource(generatorConfig);
String runSql = buildSqlWithParams(dataSource, sql, params);
String[] sqls = runSql.split(";");
Connection conn = null;
try {
conn = DataSourceManager.getConnection(generatorConfig);
SqlRunner runner = buildSqlRunner(conn);
int sqlCount = sqls.length;
if (sqlCount == 1) {
return runner.selectAll(sqls[0]);
} else {
for (int i = 0; i < sqlCount - 1; i++) {
runner.run(sqls[i]);
}
return runner.selectAll(sqls[sqlCount - 1]);
}
} catch (SQLException e1) {
logger.error("生成代码错误", e1);
throw new RuntimeException("生成代码错误");
} finally {
DataSourceManager.closeConnection(conn);
}
}
/**
* 参数绑定
*
* @param dataSource 数据源
* @param sql sql模板
* @param params 参数
* @return 构建好的耍起莱
*/
private static String buildSqlWithParams(DataSource dataSource, String sql, Map<String, Object> params) {
Configuration configuration = buildConfiguration(dataSource);
TextSqlNode node = new TextSqlNode(sql);
DynamicSqlSource dynamicSqlSource = new DynamicSqlSource(configuration, node);
BoundSql boundSql = dynamicSqlSource.getBoundSql(params);
return boundSql.getSql();
}
public static List<Map<String, Object>> runSql(GeneratorConfig dataBaseConfig, String sql) {
return runSql(dataBaseConfig, sql, null);
}
private static SqlRunner buildSqlRunner(Connection connection) {
return new SqlRunner(connection);
}
private static Configuration buildConfiguration(DataSource dataSource) {
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development",
transactionFactory, dataSource);
return new Configuration(environment);
}
}

View File

@@ -0,0 +1,19 @@
package com.gitee.gen.gen;
public class TableBean {
public TableBean(String tableName) {
this.tableName = tableName;
}
private String tableName;
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
}

View File

@@ -0,0 +1,190 @@
package com.gitee.gen.gen;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* 数据库表定义,从这里可以获取表名,字段信息
*/
public class TableDefinition {
/**
* PSSQL对应的schema
*/
private String schema;
/**
* 表名
*/
private String tableName;
/**
* 表注释
*/
private String comment;
/** Java相关字段 */
private transient List<ColumnDefinition> columnDefinitions = Collections.emptyList();
/** C#相关字段 */
private transient List<CsharpColumnDefinition> csharpColumnDefinitions = Collections.emptyList();
public TableDefinition() {
}
public TableDefinition(String tableName) {
this.tableName = tableName;
}
/**
* 返回字段数量
*
* @return 字段数量,>=0
*/
public int getColumnCount() {
return columnDefinitions.size();
}
/**
* 是否有时间字段
* @return true
*/
public boolean getHasDateColumn() {
for (ColumnDefinition definition : columnDefinitions) {
if (TypeEnum.DATETIME.getType().equalsIgnoreCase(definition.getType())) {
return true;
}
}
return false;
}
/**
* 是否含有时间字段
*
* @return
*/
public boolean getHasDateField() {
for (ColumnDefinition definition : columnDefinitions) {
if (Date.class.getSimpleName().equals((definition).getJavaType())) {
return true;
}
}
return false;
}
public boolean getHasLocalDateField() {
for (ColumnDefinition definition : columnDefinitions) {
if (LocalDate.class.getSimpleName().equals((definition).getJavaType())) {
return true;
}
}
return false;
}
public boolean getHasLocalDateTimeField() {
for (ColumnDefinition definition : columnDefinitions) {
if (LocalDateTime.class.getSimpleName().equals((definition).getJavaType())) {
return true;
}
}
return false;
}
/**
* 是否含有BigDecimal字段
*
* @return
*/
public boolean getHasBigDecimalField() {
for (ColumnDefinition definition : columnDefinitions) {
if ("BigDecimal".equals((definition).getJavaType())) {
return true;
}
}
return false;
}
public boolean getHasJsonbField() {
for (ColumnDefinition definition : columnDefinitions) {
if ("jsonb".equals(definition.getType())) {
return true;
}
}
return false;
}
/**
* 是否含有Long字段
*
* @return
*/
public boolean getHasLongField() {
for (ColumnDefinition definition : columnDefinitions) {
if ("Long".equals((definition).getJavaType())) {
return true;
}
}
return false;
}
/**
* 获取主键信息
*
* @return 返回主键信息,如果没有则抛出异常
*/
public ColumnDefinition getPkColumn() {
ColumnDefinition pk = null;
for (ColumnDefinition column : columnDefinitions) {
if (column.getColumnName().equalsIgnoreCase("id")) {
pk = column;
}
if (column.getIsPk()) {
return column;
}
}
return pk;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public List<ColumnDefinition> getColumnDefinitions() {
return columnDefinitions;
}
public void setColumnDefinitions(List<ColumnDefinition> columnDefinitions) {
this.columnDefinitions = columnDefinitions;
}
public List<CsharpColumnDefinition> getCsharpColumnDefinitions() {
return csharpColumnDefinitions;
}
public void setCsharpColumnDefinitions(List<CsharpColumnDefinition> csharpColumnDefinitions) {
this.csharpColumnDefinitions = csharpColumnDefinitions;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
}

View File

@@ -0,0 +1,125 @@
package com.gitee.gen.gen;
import com.gitee.gen.gen.converter.ColumnTypeConverter;
import org.noear.solon.Utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public abstract class TableSelector {
private ColumnSelector columnSelector;
private GeneratorConfig generatorConfig;
private List<String> schTableNames;
private ColumnTypeConverter columnTypeConverter;
public TableSelector(ColumnSelector columnSelector, GeneratorConfig generatorConfig) {
this.generatorConfig = generatorConfig;
this.columnSelector = columnSelector;
}
/**
* 查询数据库表的SQL
* 1.如果是oracle的話則應該傳入用戶名oracle是根據用戶去管理數據的
* 2.mysql的话是传入数据库名mysql和sqlserver是根据数据库去管理的
* @param generatorConfig 配置
* @return 返回获取表信息的sql
*/
protected abstract String getShowTablesSQL(GeneratorConfig generatorConfig);
protected abstract TableDefinition buildTableDefinition(Map<String, Object> tableMap);
public List<TableDefinition> getTableDefinitions() {
List<Map<String, Object>> resultList = SqlHelper.runSql(getGeneratorConfig(), getShowTablesSQL(generatorConfig));
List<TableDefinition> tablesList = new ArrayList<TableDefinition>(resultList.size());
for (Map<String, Object> rowMap : resultList) {
TableDefinition tableDefinition = this.buildTableDefinition(rowMap);
String tableName = tableDefinition.getTableName();
List<ColumnDefinition> columnDefinitions = columnSelector.getColumnDefinitions(tableName);
tableDefinition.setColumnDefinitions(buildRealColumnDefinitions(columnDefinitions, ColumnDefinition::new));
tableDefinition.setCsharpColumnDefinitions(buildRealColumnDefinitions(columnDefinitions, CsharpColumnDefinition::new));
tablesList.add(tableDefinition);
}
return tablesList;
}
private <T extends ColumnDefinition> List<T> buildRealColumnDefinitions(List<ColumnDefinition> columnDefinitions, Supplier<T> supplier) {
return columnDefinitions.stream()
.map(columnDefinition -> {
T t = supplier.get();
t.setMaxLength(columnDefinition.getMaxLength());
t.setScale(columnDefinition.getScale());
t.setColumnName(columnDefinition.getColumnName());
t.setType(columnDefinition.getType());
t.setIsIdentity(columnDefinition.getIsIdentity());
t.setIsPk(columnDefinition.getIsPk());
t.setComment(columnDefinition.getComment());
t.setIsNullable(columnDefinition.getIsNullable());
t.setColumnTypeConverter(columnTypeConverter);
return t;
})
.collect(Collectors.toList());
}
public List<TableDefinition> getSimpleTableDefinitions() {
List<Map<String, Object>> resultList = SqlHelper.runSql(getGeneratorConfig(), getShowTablesSQL(generatorConfig));
List<TableDefinition> tablesList = new ArrayList<TableDefinition>(resultList.size());
for (Map<String, Object> rowMap : resultList) {
tablesList.add(this.buildTableDefinition(rowMap));
}
return tablesList;
}
public List<String> wrapTableNames() {
List<String> schTableNames = this.getSchTableNames();
if (Utils.isEmpty(schTableNames)) {
return Collections.emptyList();
}
return schTableNames.stream()
.map(this::wrapValue)
.collect(Collectors.toList());
}
protected String wrapValue(String tableName) {
return String.format("'%s'", tableName);
}
public GeneratorConfig getGeneratorConfig() {
return generatorConfig;
}
public void setGeneratorConfig(GeneratorConfig generatorConfig) {
this.generatorConfig = generatorConfig;
}
public ColumnSelector getColumnSelector() {
return columnSelector;
}
public void setColumnSelector(ColumnSelector columnSelector) {
this.columnSelector = columnSelector;
}
public List<String> getSchTableNames() {
return schTableNames;
}
public void setSchTableNames(List<String> schTableNames) {
this.schTableNames = schTableNames;
}
public void setColumnTypeConverter(ColumnTypeConverter columnTypeConverter) {
this.columnTypeConverter = columnTypeConverter;
}
}

View File

@@ -0,0 +1,47 @@
package com.gitee.gen.gen;
/**
* 统一类型枚举
*
* @author tanghc
*/
public enum TypeEnum {
BIT("bit"),
BOOLEAN("boolean"),
TINYINT("tinyint"),
SMALLINT("smallint"),
INT("int"),
BIGINT("bigint"),
FLOAT("float"),
DOUBLE("double"),
DECIMAL("decimal"),
VARCHAR("varchar"),
DATETIME("datetime"),
DATE("date"),
BLOB("blob"),
JSONB("jsonb")
;
private final String type;
TypeEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,89 @@
package com.gitee.gen.gen;
import org.apache.commons.lang.StringUtils;
import java.util.List;
/**
* 将各数据库类型格式化成统一的类型
* @see TypeEnum
* @author tanghc
*/
public interface TypeFormatter {
default String format(String columnType) {
if (isBit(columnType)) {
return TypeEnum.BIT.getType();
}
if (isBoolean(columnType)) {
return TypeEnum.BOOLEAN.getType();
}
if (isTinyint(columnType)) {
return TypeEnum.TINYINT.getType();
}
if (isSmallint(columnType)) {
return TypeEnum.SMALLINT.getType();
}
if (isInt(columnType)) {
return TypeEnum.INT.getType();
}
if (isLong(columnType)) {
return TypeEnum.BIGINT.getType();
}
if (isFloat(columnType)) {
return TypeEnum.FLOAT.getType();
}
if (isDouble(columnType)) {
return TypeEnum.DOUBLE.getType();
}
if (isDecimal(columnType)) {
return TypeEnum.DECIMAL.getType();
}
if(isJsonb(columnType)){
return TypeEnum.JSONB.getType();
}
if (isVarchar(columnType)) {
return TypeEnum.VARCHAR.getType();
}
if (isDatetime(columnType)) {
return TypeEnum.DATETIME.getType();
}
if (isDate(columnType)) {
return TypeEnum.DATE.getType();
}
if (isBlob(columnType)) {
return TypeEnum.BLOB.getType();
}
return TypeEnum.VARCHAR.getType();
}
default boolean contains(List<String> columnTypes, String type) {
for (String columnType : columnTypes) {
if (type.equalsIgnoreCase(columnType)) {
return true;
}
}
for (String columnType : columnTypes) {
if (StringUtils.containsIgnoreCase(type, columnType)) {
return true;
}
}
return false;
}
boolean isBit(String columnType);
boolean isBoolean(String columnType);
boolean isTinyint(String columnType);
boolean isSmallint(String columnType);
boolean isInt(String columnType);
boolean isLong(String columnType);
boolean isFloat(String columnType);
boolean isDouble(String columnType);
boolean isDecimal(String columnType);
boolean isVarchar(String columnType);
boolean isDatetime(String columnType);
boolean isDate(String columnType);
boolean isBlob(String columnType);
boolean isJsonb(String columnType);
}

View File

@@ -0,0 +1,24 @@
package com.gitee.gen.gen.converter;
/**
* 将数据库类型转换成各语言对应的类型
* @see com.gitee.gen.gen.TypeEnum
* @author tanghc
*/
public interface ColumnTypeConverter {
/**
* 将数据库类型转成基本类型
* @param type 数据库类型
* @return 基本类型
*/
String convertType(String type);
/**
* 将数据库类型转成装箱类型
* @param type 数据库类型
* @return 装箱类型
*/
String convertTypeBox(String type);
}

View File

@@ -0,0 +1,39 @@
package com.gitee.gen.gen.converter;
import com.gitee.gen.gen.TypeEnum;
import java.util.HashMap;
import java.util.Map;
/**
* @author tanghc
*/
public class CsharpColumnTypeConverter implements ColumnTypeConverter {
private static final Map<String, String> TYPE_MAP = new HashMap<>(64);
static {
TYPE_MAP.put(TypeEnum.BIT.getType(), "bool");
TYPE_MAP.put(TypeEnum.BOOLEAN.getType(), "bool");
TYPE_MAP.put(TypeEnum.TINYINT.getType(), "int");
TYPE_MAP.put(TypeEnum.SMALLINT.getType(), "int");
TYPE_MAP.put(TypeEnum.INT.getType(), "int");
TYPE_MAP.put(TypeEnum.BIGINT.getType(), "long");
TYPE_MAP.put(TypeEnum.FLOAT.getType(), "float");
TYPE_MAP.put(TypeEnum.DOUBLE.getType(), "double");
TYPE_MAP.put(TypeEnum.DECIMAL.getType(), "decimal");
TYPE_MAP.put(TypeEnum.VARCHAR.getType(), "string");
TYPE_MAP.put(TypeEnum.DATETIME.getType(), "DateTime");
TYPE_MAP.put(TypeEnum.BLOB.getType(), "byte[]");
}
@Override
public String convertType(String type) {
return TYPE_MAP.getOrDefault(type, "string");
}
@Override
public String convertTypeBox(String type) {
return this.convertType(type);
}
}

View File

@@ -0,0 +1,36 @@
package com.gitee.gen.gen.converter;
import com.gitee.gen.entity.TypeConfig;
import java.util.Map;
/**
* @author thc
*/
public class DbColumnTypeConverter implements ColumnTypeConverter {
private static TypeConfig DEF = new TypeConfig();
static {
DEF.setBaseType("String");
DEF.setBoxType("String");
}
// db_type
private final Map<String, TypeConfig> typeMap;
public DbColumnTypeConverter(Map<String, TypeConfig> typeMap) {
this.typeMap = typeMap;
}
@Override
public String convertType(String type) {
return typeMap.getOrDefault(type, DEF).getBaseType();
}
@Override
public String convertTypeBox(String type) {
return typeMap.getOrDefault(type, DEF).getBoxType();
}
}

View File

@@ -0,0 +1,57 @@
package com.gitee.gen.gen.converter;
import com.gitee.gen.gen.TypeEnum;
import java.util.HashMap;
import java.util.Map;
/**
* @author tanghc
*/
public class JavaColumnTypeConverter implements ColumnTypeConverter {
private static final Map<String, String> TYPE_MAP = new HashMap<>(64);
private static final Map<String, String> TYPE_BOX_MAP = new HashMap<>(64);
static {
TYPE_MAP.put(TypeEnum.BIT.getType(), "boolean");
TYPE_MAP.put(TypeEnum.BOOLEAN.getType(), "boolean");
TYPE_MAP.put(TypeEnum.TINYINT.getType(), "int");
TYPE_MAP.put(TypeEnum.SMALLINT.getType(), "int");
TYPE_MAP.put(TypeEnum.INT.getType(), "int");
TYPE_MAP.put(TypeEnum.BIGINT.getType(), "long");
TYPE_MAP.put(TypeEnum.FLOAT.getType(), "float");
TYPE_MAP.put(TypeEnum.DOUBLE.getType(), "double");
TYPE_MAP.put(TypeEnum.DECIMAL.getType(), "BigDecimal");
TYPE_MAP.put(TypeEnum.VARCHAR.getType(), "string");
TYPE_MAP.put(TypeEnum.DATETIME.getType(), "LocalDateTime");
TYPE_MAP.put(TypeEnum.DATE.getType(), "LocalDate");
TYPE_MAP.put(TypeEnum.BLOB.getType(), "byte[]");
TYPE_MAP.put(TypeEnum.JSONB.getType(), "Map<String, Object>");
TYPE_BOX_MAP.put(TypeEnum.BIT.getType(), "Boolean");
TYPE_BOX_MAP.put(TypeEnum.BOOLEAN.getType(), "Boolean");
TYPE_BOX_MAP.put(TypeEnum.TINYINT.getType(), "Integer");
TYPE_BOX_MAP.put(TypeEnum.SMALLINT.getType(), "Integer");
TYPE_BOX_MAP.put(TypeEnum.INT.getType(), "Integer");
TYPE_BOX_MAP.put(TypeEnum.BIGINT.getType(), "Long");
TYPE_BOX_MAP.put(TypeEnum.FLOAT.getType(), "Float");
TYPE_BOX_MAP.put(TypeEnum.DOUBLE.getType(), "Double");
TYPE_BOX_MAP.put(TypeEnum.DECIMAL.getType(), "BigDecimal");
TYPE_BOX_MAP.put(TypeEnum.VARCHAR.getType(), "String");
TYPE_BOX_MAP.put(TypeEnum.DATETIME.getType(), "LocalDateTime");
TYPE_BOX_MAP.put(TypeEnum.DATE.getType(), "LocalDate");
TYPE_BOX_MAP.put(TypeEnum.BLOB.getType(), "Byte[]");
TYPE_BOX_MAP.put(TypeEnum.JSONB.getType(), "Map<String, Object>");
}
@Override
public String convertType(String type) {
String string = TYPE_MAP.getOrDefault(type, "String");
return string;
}
@Override
public String convertTypeBox(String type) {
return TYPE_BOX_MAP.getOrDefault(type, "String");
}
}

View File

@@ -0,0 +1,89 @@
package com.gitee.gen.gen.dm;
import com.gitee.gen.gen.ColumnDefinition;
import com.gitee.gen.gen.ColumnSelector;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.TypeFormatter;
import com.gitee.gen.util.FieldUtil;
import org.apache.commons.lang.StringUtils;
import java.util.Map;
import java.util.Set;
/**
* dm表信息查询
*
*/
public class DmColumnSelector extends ColumnSelector {
private static final TypeFormatter TYPE_FORMATTER = new DmTypeFormatter();
private static final String COLUMN_SQL = " SELECT " +
" atc.COLUMN_NAME FIELD, atc.DATA_TYPE TYPE, atc.DATA_SCALE SCALE, atc.DATA_LENGTH MAXLENGTH, " +
" CASE atc.NULLABLE WHEN 'N' THEN '否' ELSE '是' END 可空, " +
" atc.DATA_DEFAULT 默认值, acc.COMMENTS COMMENTS, atc.TABLE_NAME 表名, " +
" CASE atc.COLUMN_NAME " +
" WHEN " +
" ( SELECT col.column_name FROM user_constraints con " +
" LEFT JOIN user_cons_columns col ON con.table_name = col.table_name " +
" AND con.OWNER = col.OWNER AND con.CONSTRAINT_NAME = col.CONSTRAINT_NAME " +
" WHERE con.constraint_type = 'P' " +
" AND col.table_name = '%s' ) " +
" THEN 'true' ELSE 'false' END AS KEY " +
" FROM USER_TAB_COLUMNS atc " +
" LEFT JOIN USER_COL_COMMENTS acc " +
" ON acc.TABLE_NAME = atc.TABLE_NAME AND acc.COLUMN_NAME = atc.COLUMN_NAME " +
" WHERE atc.TABLE_NAME = '%s' " +
" ORDER BY atc.COLUMN_ID ";
public DmColumnSelector(GeneratorConfig generatorConfig) {
super(generatorConfig);
}
@Override
protected String getColumnInfoSQL(String tableName) {
return String.format(COLUMN_SQL, tableName, tableName);
}
@Override
protected ColumnDefinition buildColumnDefinition(Map<String, Object> rowMap){
Set<String> columnSet = rowMap.keySet();
for (String columnInfo : columnSet) {
rowMap.put(columnInfo.toUpperCase(), rowMap.get(columnInfo));
}
ColumnDefinition columnDefinition = new ColumnDefinition();
columnDefinition.setColumnName(FieldUtil.convertString(rowMap.get("FIELD")));
columnDefinition.setIsIdentity(false);
boolean isPk = "true".equalsIgnoreCase(FieldUtil.convertString(rowMap.get("KEY")));
columnDefinition.setIsPk(isPk);
String type = FieldUtil.convertString(rowMap.get("TYPE"));
// 如果是number
if (StringUtils.containsIgnoreCase(type, "number")) {
// 有精度则为decimal否则是int
Object scaleCol = rowMap.get("SCALE");
if (scaleCol == null) {
scaleCol = 0;
}
String scale = String.valueOf(scaleCol);
type = "0".equals(scale) ? "int" : "decimal";
}
columnDefinition.setType(TYPE_FORMATTER.format(type));
columnDefinition.setComment(FieldUtil.convertString(rowMap.get("COMMENTS")));
String maxLength = FieldUtil.convertString(rowMap.get("MAXLENGTH"));
columnDefinition.setMaxLength(new Integer(StringUtils.isEmpty(maxLength) ? "0" : maxLength));
String scale = FieldUtil.convertString(rowMap.get("SCALE"));
columnDefinition.setScale(new Integer(StringUtils.isEmpty(scale) ? "0" : scale));
return columnDefinition;
}
}

View File

@@ -0,0 +1,14 @@
package com.gitee.gen.gen.dm;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.SQLService;
import com.gitee.gen.gen.TableSelector;
public class DmService implements SQLService {
@Override
public TableSelector getTableSelector(GeneratorConfig generatorConfig) {
return new DmTableSelector(new DmColumnSelector(generatorConfig), generatorConfig);
}
}

View File

@@ -0,0 +1,54 @@
package com.gitee.gen.gen.dm;
import com.gitee.gen.gen.ColumnSelector;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.TableDefinition;
import com.gitee.gen.gen.TableSelector;
import java.util.Map;
import static com.gitee.gen.util.FieldUtil.convertString;
/**
* 查询mysql数据库表
*/
public class DmTableSelector extends TableSelector {
public DmTableSelector(ColumnSelector columnSelector,
GeneratorConfig dataBaseConfig) {
super(columnSelector, dataBaseConfig);
}
/**
* SELECT a.TABLE_NAME,b.COMMENTS
* FROM ALL_TABLES a,USER_TAB_COMMENTS b
* WHERE a.TABLE_NAME=b.TABLE_NAME
* AND a.OWNER='SYSTEM'
* @param generatorConfig generatorConfig
* @return
*/
@Override
protected String getShowTablesSQL(GeneratorConfig generatorConfig) {
String owner = generatorConfig.getSchemaName().toUpperCase();
StringBuilder sb = new StringBuilder("");
sb.append("SELECT a.TABLE_NAME AS NAME,b.COMMENTS FROM USER_TABLES a left join USER_TAB_COMMENTS b on a.TABLE_NAME = b.TABLE_NAME ");
sb.append(" WHERE 1=1 ");
if(this.getSchTableNames() != null && this.getSchTableNames().size() > 0) {
StringBuilder tables = new StringBuilder();
for (String table : this.getSchTableNames()) {
tables.append(",'").append(table).append("'");
}
sb.append(" AND a.TABLE_NAME IN (" + tables.substring(1) + ")");
}
return sb.toString();
}
@Override
protected TableDefinition buildTableDefinition(Map<String, Object> tableMap) {
TableDefinition tableDefinition = new TableDefinition();
tableDefinition.setTableName(convertString(tableMap.get("NAME")));
tableDefinition.setComment(convertString(tableMap.get("COMMENTS")));
return tableDefinition;
}
}

View File

@@ -0,0 +1,82 @@
package com.gitee.gen.gen.dm;
import com.gitee.gen.gen.TypeFormatter;
import java.util.Arrays;
import java.util.Collections;
/**
* @author tanghc
*/
public class DmTypeFormatter implements TypeFormatter {
@Override
public boolean isBit(String columnType) {
return contains(Collections.singletonList("bit"), columnType);
}
@Override
public boolean isBoolean(String columnType) {
return contains(Collections.singletonList("boolean"), columnType);
}
@Override
public boolean isTinyint(String columnType) {
return contains(Collections.singletonList("tinyint"), columnType);
}
@Override
public boolean isSmallint(String columnType) {
return false;
}
@Override
public boolean isInt(String columnType) {
return !isLong(columnType) && contains(Arrays.asList("int", "integer"), columnType);
}
@Override
public boolean isLong(String columnType) {
return !isVarchar(columnType) && contains(Collections.singletonList("bigint"), columnType);
}
@Override
public boolean isFloat(String columnType) {
return contains(Collections.singletonList("float"), columnType);
}
@Override
public boolean isDouble(String columnType) {
return contains(Collections.singletonList("double"), columnType);
}
@Override
public boolean isDecimal(String columnType) {
return contains(Collections.singletonList("decimal"), columnType);
}
@Override
public boolean isVarchar(String columnType) {
return contains(Arrays.asList("CHAR", "VARCHAR", "VARCHAR2", "NVARCHAR2", "TEXT", "NCHAR"), columnType);
}
@Override
public boolean isDatetime(String columnType) {
return contains(Arrays.asList("TIME", "DATETIME", "TIMESTAMP"), columnType);
}
@Override
public boolean isDate(String columnType) {
return contains(Collections.singletonList("DATE"), columnType);
}
@Override
public boolean isBlob(String columnType) {
return contains(Collections.singletonList("blob"), columnType);
}
@Override
public boolean isJsonb(String columnType) {
return false;
}
}

View File

@@ -0,0 +1,89 @@
package com.gitee.gen.gen.mysql;
import com.gitee.gen.gen.ColumnDefinition;
import com.gitee.gen.gen.ColumnSelector;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.TypeFormatter;
import com.gitee.gen.util.FieldUtil;
import org.apache.commons.lang.StringUtils;
import java.util.Map;
import java.util.Set;
/**
* mysql表信息查询
*
*/
public class MySqlColumnSelector extends ColumnSelector {
private static final TypeFormatter TYPE_FORMATTER = new MySqlTypeFormatter();
private static final String SHOW_SQL = " SELECT " +
" COLUMN_NAME AS 'Field', " +
" COLUMN_DEFAULT AS 'Default', " +
" IS_NULLABLE AS 'Null', " +
" DATA_TYPE AS 'DataType', " +
" CASE DATA_TYPE " +
" WHEN 'int' THEN NUMERIC_PRECISION " +
" WHEN 'varchar' THEN CHARACTER_MAXIMUM_LENGTH " +
" END AS 'MaxLength', " +
" IFNULL(NUMERIC_SCALE,0) AS 'Scale', " +
" COLUMN_TYPE AS 'Type', " +
" COLUMN_KEY 'KEY', " +
" EXTRA AS 'Extra', " +
" COLUMN_COMMENT AS 'Comment' " +
" FROM information_schema.`COLUMNS` " +
" WHERE 1=1 AND TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s' " +
" ORDER BY ORDINAL_POSITION";
public MySqlColumnSelector(GeneratorConfig generatorConfig) {
super(generatorConfig);
}
/**
* SHOW FULL COLUMNS FROM 表名
*/
@Override
protected String getColumnInfoSQL(String tableName) {
return String.format(SHOW_SQL, getGeneratorConfig().getDbName(), tableName);
}
/*
* {FIELD=username, EXTRA=, COMMENT=用户名, COLLATION=utf8_general_ci, PRIVILEGES=select,insert,update,references, KEY=PRI, NULL=NO, DEFAULT=null, TYPE=varchar(20)}
*/
@Override
protected ColumnDefinition buildColumnDefinition(Map<String, Object> rowMap){
Set<String> columnSet = rowMap.keySet();
for (String columnInfo : columnSet) {
rowMap.put(columnInfo.toUpperCase(), rowMap.get(columnInfo));
}
ColumnDefinition columnDefinition = new ColumnDefinition();
columnDefinition.setColumnName(FieldUtil.convertString(rowMap.get("FIELD")));
boolean isIdentity = "auto_increment".equalsIgnoreCase(FieldUtil.convertString(rowMap.get("EXTRA")));
columnDefinition.setIsIdentity(isIdentity);
boolean isPk = "PRI".equalsIgnoreCase(FieldUtil.convertString(rowMap.get("KEY")));
columnDefinition.setIsPk(isPk);
String type = FieldUtil.convertString(rowMap.get("TYPE"));
columnDefinition.setType(TYPE_FORMATTER.format(type));
columnDefinition.setComment(FieldUtil.convertString(rowMap.get("COMMENT")));
String maxLength = FieldUtil.convertString(rowMap.get("MAXLENGTH"));
columnDefinition.setMaxLength(new Integer(StringUtils.isEmpty(maxLength) ? "0" : maxLength));
String scale = FieldUtil.convertString(rowMap.get("SCALE"));
columnDefinition.setScale(new Integer(StringUtils.isEmpty(scale) ? "0" : scale));
String isNullable = FieldUtil.convertString(rowMap.get("NULL"));
columnDefinition.setIsNullable("YES".equalsIgnoreCase(isNullable));
return columnDefinition;
}
}

View File

@@ -0,0 +1,14 @@
package com.gitee.gen.gen.mysql;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.SQLService;
import com.gitee.gen.gen.TableSelector;
public class MySqlService implements SQLService {
@Override
public TableSelector getTableSelector(GeneratorConfig generatorConfig) {
return new MySqlTableSelector(new MySqlColumnSelector(generatorConfig), generatorConfig);
}
}

View File

@@ -0,0 +1,48 @@
package com.gitee.gen.gen.mysql;
import com.gitee.gen.gen.ColumnSelector;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.TableDefinition;
import com.gitee.gen.gen.TableSelector;
import java.util.Map;
import static com.gitee.gen.util.FieldUtil.convertString;
/**
* 查询mysql数据库表
*/
public class MySqlTableSelector extends TableSelector {
public MySqlTableSelector(ColumnSelector columnSelector,
GeneratorConfig dataBaseConfig) {
super(columnSelector, dataBaseConfig);
}
@Override
protected String getShowTablesSQL(GeneratorConfig generatorConfig) {
String dbName = generatorConfig.getDbName();
// 兼容dbName包含特殊字符会报错的情况
if (!(dbName.startsWith("`") && dbName.endsWith("`"))) {
dbName = String.format("`%s`",dbName);
}
String sql = "SHOW TABLE STATUS FROM " + dbName;
if(this.getSchTableNames() != null && this.getSchTableNames().size() > 0) {
StringBuilder tables = new StringBuilder();
for (String table : this.getSchTableNames()) {
tables.append(",'").append(table).append("'");
}
sql += " WHERE NAME IN (" + tables.substring(1) + ")";
}
return sql;
}
@Override
protected TableDefinition buildTableDefinition(Map<String, Object> tableMap) {
TableDefinition tableDefinition = new TableDefinition();
tableDefinition.setTableName(convertString(tableMap.get("NAME")));
tableDefinition.setComment(convertString(tableMap.get("COMMENT")));
return tableDefinition;
}
}

View File

@@ -0,0 +1,82 @@
package com.gitee.gen.gen.mysql;
import com.gitee.gen.gen.TypeFormatter;
import java.util.Arrays;
import java.util.Collections;
/**
* @author tanghc
*/
public class MySqlTypeFormatter implements TypeFormatter {
@Override
public boolean isBit(String columnType) {
return contains(Collections.singletonList("bit"), columnType);
}
@Override
public boolean isBoolean(String columnType) {
return contains(Collections.singletonList("boolean"), columnType);
}
@Override
public boolean isTinyint(String columnType) {
return contains(Collections.singletonList("tinyint"), columnType);
}
@Override
public boolean isSmallint(String columnType) {
return contains(Collections.singletonList("smallint"), columnType);
}
@Override
public boolean isInt(String columnType) {
return !isLong(columnType) && contains(Arrays.asList("int", "integer"), columnType);
}
@Override
public boolean isLong(String columnType) {
return !isVarchar(columnType) && contains(Collections.singletonList("bigint"), columnType);
}
@Override
public boolean isFloat(String columnType) {
return contains(Collections.singletonList("float"), columnType);
}
@Override
public boolean isDouble(String columnType) {
return contains(Collections.singletonList("double"), columnType);
}
@Override
public boolean isDecimal(String columnType) {
return contains(Collections.singletonList("decimal"), columnType);
}
@Override
public boolean isVarchar(String columnType) {
return contains(Arrays.asList("CHAR", "VARCHAR", "TEXT"), columnType);
}
@Override
public boolean isDatetime(String columnType) {
return contains(Arrays.asList("TIME", "DATETIME", "TIMESTAMP"), columnType);
}
@Override
public boolean isDate(String columnType) {
return contains(Collections.singletonList("DATE"), columnType);
}
@Override
public boolean isBlob(String columnType) {
return contains(Collections.singletonList("blob"), columnType);
}
@Override
public boolean isJsonb(String columnType) {
return false;
}
}

View File

@@ -0,0 +1,115 @@
package com.gitee.gen.gen.oracle;
import com.gitee.gen.gen.ColumnDefinition;
import com.gitee.gen.gen.ColumnSelector;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.TypeFormatter;
import com.gitee.gen.util.FieldUtil;
import org.apache.commons.lang.StringUtils;
import java.util.Map;
import java.util.Set;
/**
* oracle表信息查询
*/
public class OracleColumnSelector extends ColumnSelector {
private static final TypeFormatter TYPE_FORMATTER = new OracleTypeFormatter();
// private static final String COLUMN_SQL = "select "
// + " utc.column_name as FIELD,utc.data_type TYPE, utc.data_scale SCALE, utc.data_length MAXLENGTH, "
// + " CASE utc.nullable WHEN 'N' THEN '否' ELSE '是' END 可空, "
// + " utc.data_default 默认值,ucc.comments COMMENTS,UTC.table_name 表名, "
// + " CASE UTC.COLUMN_NAME "
// + " WHEN (select "
// + " col.column_name "
// + " from "
// + " user_constraints con,user_cons_columns col "
// + " where "
// + " con.constraint_name=col.constraint_name and con.constraint_type='P' "
// + " and col.table_name='%s') THEN 'true' ELSE 'false' END AS KEY "
// + " from "
// + " user_tab_columns utc,user_col_comments ucc "
// + " where "
// + " utc.table_name = ucc.table_name "
// + " and utc.column_name = ucc.column_name "
// + " and utc.table_name = '%s' "
// + " order by "
// + " column_id ";
private static final String COLUMN_SQL = " SELECT " +
" atc.COLUMN_NAME FIELD, atc.DATA_TYPE TYPE, atc.DATA_SCALE SCALE, atc.DATA_LENGTH MAXLENGTH, " +
" atc.NULLABLE NULLABLE , " +
" atc.DATA_DEFAULT 默认值, acc.COMMENTS COMMENTS, atc.TABLE_NAME 表名, " +
" CASE atc.COLUMN_NAME " +
" WHEN " +
" ( SELECT col.column_name FROM all_constraints con " +
" LEFT JOIN all_cons_columns col ON con.table_name = col.table_name " +
" AND con.OWNER = col.OWNER AND con.CONSTRAINT_NAME = col.CONSTRAINT_NAME " +
" WHERE con.constraint_type = 'P' " +
" AND col.table_name = '%s' AND con.OWNER = '%s' AND col.column_name = atc.COLUMN_NAME ) " +
" THEN 'true' ELSE 'false' END AS KEY " +
" FROM ALL_TAB_COLUMNS atc " +
" LEFT JOIN ALL_COL_COMMENTS acc " +
" ON acc.TABLE_NAME = atc.TABLE_NAME AND acc.COLUMN_NAME = atc.COLUMN_NAME " +
" AND acc.OWNER = atc.OWNER " +
" WHERE atc.TABLE_NAME = '%s' AND atc.OWNER = '%s' " +
" ORDER BY atc.COLUMN_ID ";
public OracleColumnSelector(GeneratorConfig generatorConfig) {
super(generatorConfig);
}
@Override
protected String getColumnInfoSQL(String tableName) {
String owner = this.getGeneratorConfig().getSchemaName();
return String.format(COLUMN_SQL, tableName, owner, tableName, owner);
}
@Override
protected ColumnDefinition buildColumnDefinition(Map<String, Object> rowMap){
Set<String> columnSet = rowMap.keySet();
for (String columnInfo : columnSet) {
rowMap.put(columnInfo.toUpperCase(), rowMap.get(columnInfo));
}
ColumnDefinition columnDefinition = new ColumnDefinition();
columnDefinition.setColumnName(FieldUtil.convertString(rowMap.get("FIELD")));
columnDefinition.setIsIdentity(false);
boolean isPk = "true".equalsIgnoreCase(FieldUtil.convertString(rowMap.get("KEY")));
columnDefinition.setIsPk(isPk);
String type = FieldUtil.convertString(rowMap.get("TYPE"));
// 如果是number
if (StringUtils.containsIgnoreCase(type, "number")) {
// 有精度则为decimal否则是int
Object scaleCol = rowMap.get("SCALE");
if (scaleCol == null) {
scaleCol = 0;
}
String scale = String.valueOf(scaleCol);
type = "0".equals(scale) ? "int" : "decimal";
}
columnDefinition.setType(TYPE_FORMATTER.format(type));
columnDefinition.setComment(FieldUtil.convertString(rowMap.get("COMMENTS")));
String maxLength = FieldUtil.convertString(rowMap.get("MAXLENGTH"));
columnDefinition.setMaxLength(new Integer(StringUtils.isEmpty(maxLength) ? "0" : maxLength));
String scale = FieldUtil.convertString(rowMap.get("SCALE"));
columnDefinition.setScale(new Integer(StringUtils.isEmpty(scale) ? "0" : scale));
String isNullable = FieldUtil.convertString(rowMap.get("NULLABLE"));
columnDefinition.setIsNullable(!"N".equalsIgnoreCase(isNullable));
return columnDefinition;
}
}

View File

@@ -0,0 +1,14 @@
package com.gitee.gen.gen.oracle;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.SQLService;
import com.gitee.gen.gen.TableSelector;
public class OracleService implements SQLService {
@Override
public TableSelector getTableSelector(GeneratorConfig generatorConfig) {
return new OracleTableSelector(new OracleColumnSelector(generatorConfig), generatorConfig);
}
}

View File

@@ -0,0 +1,55 @@
package com.gitee.gen.gen.oracle;
import com.gitee.gen.gen.ColumnSelector;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.TableDefinition;
import com.gitee.gen.gen.TableSelector;
import java.util.Map;
import static com.gitee.gen.util.FieldUtil.convertString;
/**
* 查询oracle数据库表
*/
public class OracleTableSelector extends TableSelector {
public OracleTableSelector(ColumnSelector columnSelector,
GeneratorConfig dataBaseConfig) {
super(columnSelector, dataBaseConfig);
}
/**
* SELECT a.TABLE_NAME,b.COMMENTS
* FROM ALL_TABLES a,USER_TAB_COMMENTS b
* WHERE a.TABLE_NAME=b.TABLE_NAME
* AND a.OWNER='SYSTEM'
* @param generatorConfig generatorConfig
* @return
*/
@Override
protected String getShowTablesSQL(GeneratorConfig generatorConfig) {
StringBuilder sb = new StringBuilder("");
sb.append(" SELECT a.TABLE_NAME as NAME,b.COMMENTS" +
" FROM ALL_TABLES a,USER_TAB_COMMENTS b" +
" WHERE a.TABLE_NAME=b.TABLE_NAME");
sb.append(" AND 1=1 ");
if(this.getSchTableNames() != null && this.getSchTableNames().size() > 0) {
StringBuilder tables = new StringBuilder();
for (String table : this.getSchTableNames()) {
tables.append(",'").append(table).append("'");
}
sb.append(" AND a.TABLE_NAME IN (" + tables.substring(1) + ")");
}
return sb.toString();
}
@Override
protected TableDefinition buildTableDefinition(Map<String, Object> tableMap) {
TableDefinition tableDefinition = new TableDefinition();
tableDefinition.setTableName(convertString(tableMap.get("NAME")));
tableDefinition.setComment(convertString(tableMap.get("COMMENTS")));
return tableDefinition;
}
}

View File

@@ -0,0 +1,82 @@
package com.gitee.gen.gen.oracle;
import com.gitee.gen.gen.TypeFormatter;
import java.util.Arrays;
import java.util.Collections;
/**
* @author tanghc
*/
public class OracleTypeFormatter implements TypeFormatter {
@Override
public boolean isBit(String columnType) {
return contains(Collections.singletonList("bit"), columnType);
}
@Override
public boolean isBoolean(String columnType) {
return contains(Collections.singletonList("boolean"), columnType);
}
@Override
public boolean isTinyint(String columnType) {
return contains(Collections.singletonList("tinyint"), columnType);
}
@Override
public boolean isSmallint(String columnType) {
return false;
}
@Override
public boolean isInt(String columnType) {
return contains(Arrays.asList("int", "integer"), columnType);
}
@Override
public boolean isLong(String columnType) {
return !isVarchar(columnType) && contains(Collections.singletonList("long"), columnType);
}
@Override
public boolean isFloat(String columnType) {
return contains(Collections.singletonList("float"), columnType);
}
@Override
public boolean isDouble(String columnType) {
return contains(Collections.singletonList("double"), columnType);
}
@Override
public boolean isDecimal(String columnType) {
return contains(Collections.singletonList("decimal"), columnType);
}
@Override
public boolean isVarchar(String columnType) {
return contains(Arrays.asList("CHAR", "VARCHAR", "VARCHAR2", "NVARCHAR2", "TEXT", "NCHAR"), columnType);
}
@Override
public boolean isDatetime(String columnType) {
return contains(Arrays.asList("TIME", "DATETIME", "TIMESTAMP"), columnType);
}
@Override
public boolean isDate(String columnType) {
return contains(Collections.singletonList("DATE"), columnType);
}
@Override
public boolean isBlob(String columnType) {
return contains(Collections.singletonList("blob"), columnType);
}
@Override
public boolean isJsonb(String columnType) {
return false;
}
}

View File

@@ -0,0 +1,106 @@
package com.gitee.gen.gen.postgresql;
import com.gitee.gen.gen.ColumnDefinition;
import com.gitee.gen.gen.ColumnSelector;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.util.FieldUtil;
import org.apache.commons.lang.StringUtils;
import java.util.Map;
import java.util.Set;
import static com.gitee.gen.util.FieldUtil.convertString;
/**
* @author tanghc
*/
public class PostgreSqlColumnSelector extends ColumnSelector {
private static final PostgreSqlTypeFormatter SQL_TYPE_FORMATTER = new PostgreSqlTypeFormatter();
public PostgreSqlColumnSelector(GeneratorConfig dataBaseConfig) {
super(dataBaseConfig);
}
private static final String SHOW_COLUMN_SQL = "SELECT " +
" pg_attribute.attname AS colname, " +
" atttypid::regtype AS type, " +
" pg_attribute.atttypmod - 4 AS type_length, " +
" numeric_scale as SCALE, " +
" C.is_nullable as NULLABLE, " +
" col_description ( pg_attribute.attrelid, pg_attribute.attnum ) AS cmt, " +
" pg_attribute.attnum = pg_constraint.conkey [ 1 ] AS is_pk, " +
"CASE WHEN POSITION ( 'nextval' IN column_default ) > 0 THEN 1 ELSE 0 END AS is_identity " +
"FROM " +
" pg_constraint " +
" RIGHT JOIN pg_class ON pg_constraint.conrelid = pg_class.oid and pg_constraint.contype = 'p' " +
" RIGHT JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid " +
" RIGHT JOIN pg_type ON pg_type.oid = pg_attribute.atttypid " +
" RIGHT JOIN information_schema.COLUMNS C ON C.TABLE_NAME = pg_class.relname " +
" AND C.COLUMN_NAME = pg_attribute.attname " +
"WHERE " +
" pg_class.relname = '%s' " +
// " and pg_constraint.contype = 'p' " +
" AND pg_attribute.attnum > 0";
@Override
protected String getColumnInfoSQL(String tableName) {
return String.format(SHOW_COLUMN_SQL, tableName);
}
/*
"colname" "type" "cmt" "is_pk" "is_identity"
"id" "integer" "自增主键" "t" "1"
"user_id" "integer" "用户id" "f" "0"
"city" "character varying" "城市" "f" "0"
"address" "character varying" "街道" "f" "0"
"status" "character varying" "类型" "f" "0"
"create_time" "timestamp without time zone" "添加时间" "f" "0"
"update_time" "timestamp without time zone" "修改时间" "f" "0"
*/
@Override
protected ColumnDefinition buildColumnDefinition(Map<String, Object> rowMap) {
Set<String> columnSet = rowMap.keySet();
for (String columnInfo : columnSet) {
rowMap.put(columnInfo.toUpperCase(), rowMap.get(columnInfo));
}
ColumnDefinition columnDefinition = new ColumnDefinition();
columnDefinition.setColumnName(convertString(rowMap.get("COLNAME")));
boolean isIdentity = "1".equals(convertString(rowMap.get("IS_IDENTITY")));
columnDefinition.setIsIdentity(isIdentity);
boolean isPk = (Boolean) (rowMap.get("IS_PK") != null ? rowMap.get("IS_PK") : false);
columnDefinition.setIsPk(isPk);
String type = convertString(rowMap.get("TYPE"));
// 如果是number
if (StringUtils.containsIgnoreCase(type, "numeric")) {
// 有精度则为decimal否则是int
Object scaleCol = rowMap.get("SCALE");
if (scaleCol == null) {
scaleCol = 0;
}
String scale = String.valueOf(scaleCol);
type = "0".equals(scale) ? "integer" : "decimal";
}
columnDefinition.setType(SQL_TYPE_FORMATTER.format(type));
String maxLength = FieldUtil.convertString(rowMap.get("TYPE_LENGTH"));
int length = Integer.parseInt((StringUtils.isEmpty(maxLength) ? "0" : maxLength));
columnDefinition.setMaxLength(Math.max(length, 0));
columnDefinition.setComment(convertString(rowMap.get("CMT")));
String isNullable = FieldUtil.convertString(rowMap.get("NULLABLE"));
columnDefinition.setIsNullable(!"NO".equalsIgnoreCase(isNullable));
return columnDefinition;
}
}

View File

@@ -0,0 +1,16 @@
package com.gitee.gen.gen.postgresql;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.SQLService;
import com.gitee.gen.gen.TableSelector;
/**
* @author tanghc
*/
public class PostgreSqlService implements SQLService {
@Override
public TableSelector getTableSelector(GeneratorConfig generatorConfig) {
return new PostgreSqlTableSelector(new PostgreSqlColumnSelector(generatorConfig), generatorConfig);
}
}

View File

@@ -0,0 +1,63 @@
package com.gitee.gen.gen.postgresql;
import com.gitee.gen.gen.ColumnSelector;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.TableDefinition;
import com.gitee.gen.gen.TableSelector;
import org.apache.commons.lang.StringUtils;
import java.util.List;
import java.util.Map;
import static com.gitee.gen.util.FieldUtil.convertString;
/**
* @author tanghc
*/
public class PostgreSqlTableSelector extends TableSelector {
private static final String DEFAULT_SCHEMA = "public";
public PostgreSqlTableSelector(ColumnSelector columnSelector, GeneratorConfig generatorConfig) {
super(columnSelector, generatorConfig);
}
private static final String SHOW_TABLE_SQL =
"SELECT " +
" t.schemaname, t.tablename, t2.cmt " +
"FROM " +
" pg_tables t LEFT JOIN " +
" ( " +
" SELECT C.relname as tablename, obj_description(C.oid) as cmt, n.nspname as schemaname " +
" FROM pg_class C join pg_namespace n on n.oid = C.relnamespace " +
" WHERE C.relkind='r' AND C.relname NOT LIKE 'pg_%%' AND C.relname NOT LIKE 'sql_%%' AND C.relchecks=0 " +
" ORDER BY relname " +
") t2 ON t.tablename = t2.tablename and t.schemaname = t2.schemaname " +
"WHERE t.schemaname != 'pg_catalog' AND t.schemaname != 'information_schema' %s %s";
@Override
protected String getShowTablesSQL(GeneratorConfig generatorConfig) {
String schema = generatorConfig.getSchemaName();
if (schema == null) {
schema = "";
}
if (StringUtils.isNotBlank(schema)) {
schema = String.format("AND t.schemaname = '%s'", schema);
}
List<String> tableNames = wrapTableNames();
String and = "";
if (!tableNames.isEmpty()) {
and = String.format("AND t.tablename in (%s)", String.join(",", tableNames));
}
return String.format(SHOW_TABLE_SQL, schema, and);
}
@Override
protected TableDefinition buildTableDefinition(Map<String, Object> tableMap) {
TableDefinition tableDefinition = new TableDefinition();
tableDefinition.setSchema(convertString(tableMap.get("SCHEMANAME")));
tableDefinition.setTableName(convertString(tableMap.get("TABLENAME")));
tableDefinition.setComment(convertString(tableMap.get("CMT")));
return tableDefinition;
}
}

View File

@@ -0,0 +1,82 @@
package com.gitee.gen.gen.postgresql;
import com.gitee.gen.gen.TypeFormatter;
import java.util.Arrays;
import java.util.Collections;
/**
* @author tanghc
*/
public class PostgreSqlTypeFormatter implements TypeFormatter {
@Override
public boolean isBit(String columnType) {
return contains(Collections.singletonList("bit"), columnType);
}
@Override
public boolean isBoolean(String columnType) {
return contains(Collections.singletonList("boolean"), columnType);
}
@Override
public boolean isTinyint(String columnType) {
return false;
}
@Override
public boolean isSmallint(String columnType) {
return contains(Arrays.asList("int2", "serial2", "smallint"), columnType);
}
@Override
public boolean isInt(String columnType) {
return contains(Arrays.asList("int4", "serial4", "integer"), columnType);
}
@Override
public boolean isLong(String columnType) {
return !isVarchar(columnType) && contains(Arrays.asList("int8", "serial8", "bigint"), columnType);
}
@Override
public boolean isFloat(String columnType) {
return contains(Arrays.asList("float", "real"), columnType);
}
@Override
public boolean isDouble(String columnType) {
return contains(Collections.singletonList("double"), columnType);
}
@Override
public boolean isDecimal(String columnType) {
return contains(Arrays.asList("decimal","numeric"), columnType);
}
@Override
public boolean isVarchar(String columnType) {
return contains(Arrays.asList("CHAR", "VARCHAR", "TEXT", "character", "json"), columnType);
}
@Override
public boolean isDatetime(String columnType) {
return contains(Arrays.asList("TIME", "DATETIME", "TIMESTAMP"), columnType);
}
@Override
public boolean isDate(String columnType) {
return contains(Collections.singletonList("DATE"), columnType);
}
@Override
public boolean isBlob(String columnType) {
return contains(Collections.singletonList("blob"), columnType);
}
@Override
public boolean isJsonb(String columnType) {
return contains(Collections.singletonList("jsonb"), columnType);
}
}

View File

@@ -0,0 +1,122 @@
package com.gitee.gen.gen.sqlserver;
import com.gitee.gen.gen.ColumnDefinition;
import com.gitee.gen.gen.ColumnSelector;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.util.FieldUtil;
import org.apache.commons.lang.StringUtils;
import java.util.Map;
import java.util.Set;
public class SqlServerColumnSelector extends ColumnSelector {
private static final SqlServerTypeFormatter TYPE_FORMATTER = new SqlServerTypeFormatter();
// https://blog.csdn.net/qq_14880455/article/details/92842329
private static String TABKE_DETAIL_SQL = new StringBuilder()
.append("SELECT")
.append(" col.name AS column_name")
.append(" , col.max_length AS MaxLength") //sqlserver 字段长度
.append(" , col.scale AS Scale") //sqlserver 字段精度
.append(" , col.is_nullable AS NULLABLE") //1 =列可以为空。
.append(" , bt.name AS type")
.append(" , col.is_identity")
.append(" , ext.value AS comment")
.append(" ,(")
.append(" SELECT COUNT(1) FROM sys.indexes IDX ")
.append(" INNER JOIN sys.index_columns IDXC ")
.append(" ON IDX.[object_id]=IDXC.[object_id] ")
.append(" AND IDX.index_id=IDXC.index_id ")
.append(" LEFT JOIN sys.key_constraints KC ")
.append(" ON IDX.[object_id]=KC.[parent_object_id] ")
.append(" AND IDX.index_id=KC.unique_index_id ")
.append(" INNER JOIN sys.objects O ")
.append(" ON O.[object_id]=IDX.[object_id] ")
.append(" WHERE O.[object_id]=col.[object_id] ")
.append(" AND O.type='U' ")
.append(" AND O.is_ms_shipped=0 ")
.append(" AND IDX.is_primary_key=1 ")
.append(" AND IDXC.Column_id=col.column_id ")
.append(" ) AS is_pk ")
.append("FROM sys.columns col ")
.append("LEFT OUTER JOIN sys.types bt on bt.user_type_id = col.system_type_id ")
.append("LEFT JOIN sys.extended_properties ext ON ext.major_id = col.object_id AND ext.minor_id = col.column_id ")
.append("WHERE col.object_id = object_id('%s') ")
.append("ORDER BY col.column_id").toString();
public SqlServerColumnSelector(GeneratorConfig generatorConfig) {
super(generatorConfig);
}
/* SELECT
col.name AS column_name
, bt.name AS type
, col.is_identity
, ext.value as comment
,(
SELECT COUNT(1) FROM sys.indexes IDX
INNER JOIN sys.index_columns IDXC
ON IDX.[object_id]=IDXC.[object_id]
AND IDX.index_id=IDXC.index_id
LEFT JOIN sys.key_constraints KC
ON IDX.[object_id]=KC.[parent_object_id]
AND IDX.index_id=KC.unique_index_id
INNER JOIN sys.objects O
ON O.[object_id]=IDX.[object_id]
WHERE O.[object_id]=col.[object_id]
AND O.type='U'
AND O.is_ms_shipped=0
AND IDX.is_primary_key=1
AND IDXC.Column_id=col.column_id
) AS is_pk
FROM sys.columns col
LEFT OUTER JOIN sys.types bt on bt.user_type_id = col.system_type_id
LEFT JOIN sys.extended_properties ext ON ext.major_id = col.object_id AND ext.minor_id = col.column_id
WHERE col.object_id = object_id('front.bar')
ORDER BY col.column_id;
*/
@Override
protected String getColumnInfoSQL(String tableName) {
return String.format(TABKE_DETAIL_SQL, tableName);
}
/*
* rowMap:
* {COLUMN_NAME=barId, IS_IDENTITY=true, COMMENT=网吧ID, IS_PK=1, TYPE=int}
*/
@Override
protected ColumnDefinition buildColumnDefinition(Map<String, Object> rowMap) {
Set<String> columnSet = rowMap.keySet();
for (String columnInfo : columnSet) {
rowMap.put(columnInfo.toUpperCase(), rowMap.get(columnInfo));
}
ColumnDefinition columnDefinition = new ColumnDefinition();
columnDefinition.setColumnName(FieldUtil.convertString(rowMap.get("COLUMN_NAME")));
columnDefinition.setIsIdentity((Boolean)rowMap.get("IS_IDENTITY"));
boolean isPk = (Integer)rowMap.get("IS_PK") == 1;
columnDefinition.setIsPk(isPk);
String type = FieldUtil.convertString( rowMap.get("TYPE"));
columnDefinition.setType(TYPE_FORMATTER.format(type));
columnDefinition.setComment(FieldUtil.convertString(rowMap.get("COMMENT")));
//sqlserver 字段长度
String maxLength = FieldUtil.convertString(rowMap.get("MAXLENGTH"));
columnDefinition.setMaxLength(Integer.parseInt(StringUtils.isEmpty(maxLength) ? "0" : maxLength));
//sqlserver 字段精度
String scale = FieldUtil.convertString(rowMap.get("SCALE"));
columnDefinition.setScale(Integer.parseInt(StringUtils.isEmpty(scale) ? "0" : scale));
String isNullable = FieldUtil.convertString(rowMap.get("NULLABLE"));
columnDefinition.setIsNullable("1".equalsIgnoreCase(isNullable));
return columnDefinition;
}
}

View File

@@ -0,0 +1,14 @@
package com.gitee.gen.gen.sqlserver;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.SQLService;
import com.gitee.gen.gen.TableSelector;
public class SqlServerService implements SQLService {
@Override
public TableSelector getTableSelector(GeneratorConfig generatorConfig) {
return new SqlServerTableSelector(new SqlServerColumnSelector(generatorConfig), generatorConfig);
}
}

View File

@@ -0,0 +1,60 @@
package com.gitee.gen.gen.sqlserver;
import com.gitee.gen.gen.ColumnSelector;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.TableDefinition;
import com.gitee.gen.gen.TableSelector;
import java.util.Map;
import static com.gitee.gen.util.FieldUtil.convertString;
public class SqlServerTableSelector extends TableSelector {
public SqlServerTableSelector(ColumnSelector columnSelector,
GeneratorConfig dataBaseConfig) {
super(columnSelector, dataBaseConfig);
}
@Override
protected String getShowTablesSQL(GeneratorConfig generatorConfig) {
return "SELECT SS.name + '.' + t.name AS table_name " +
",CONVERT(varchar(50),ISNULL(ext.value, '')) as comment " +
"FROM sysobjects t " +
"INNER JOIN sys.objects SO ON t.name = SO.name " +
"INNER JOIN sys.schemas SS ON SO.schema_id = SS.schema_id " +
"LEFT JOIN sys.extended_properties ext ON ext.major_id = SO.object_id and ext.minor_id=0 " +
"WHERE t.xtype='u' " +
this.buildTableSchWhere() +
" ORDER BY SS.name ASC,t.name ASC";
}
// and ( (t.name = 'bar' and SS.name = 'front') or (t.name = 'adjustBatch' and SS.name = 'account') )
private String buildTableSchWhere() {
if(this.getSchTableNames() != null && this.getSchTableNames().size() > 0) {
int i = 0;
StringBuilder tables = new StringBuilder(" and ( ");
for (String table : this.getSchTableNames()) {
String[] tableArr = table.split("\\.");
if(i > 0) {
tables.append(" or ");
}
tables.append("(SS.name='").append(tableArr[0]).append("' and t.name='").append(tableArr[1]).append("') ");
i++;
}
tables.append(" )");
return tables.toString();
}
return "";
}
// {TABLE_NAME=account.adjustBatch, COMMENT=}
@Override
protected TableDefinition buildTableDefinition(Map<String, Object> tableMap) {
TableDefinition tableDefinition = new TableDefinition();
tableDefinition.setTableName(convertString(tableMap.get("TABLE_NAME")));
tableDefinition.setComment(convertString(tableMap.get("COMMENT")));
return tableDefinition;
}
}

View File

@@ -0,0 +1,82 @@
package com.gitee.gen.gen.sqlserver;
import com.gitee.gen.gen.TypeFormatter;
import java.util.Arrays;
import java.util.Collections;
/**
* @author tanghc
*/
public class SqlServerTypeFormatter implements TypeFormatter {
@Override
public boolean isBit(String columnType) {
return contains(Collections.singletonList("bit"), columnType);
}
@Override
public boolean isBoolean(String columnType) {
return contains(Collections.singletonList("boolean"), columnType);
}
@Override
public boolean isTinyint(String columnType) {
return contains(Collections.singletonList("tinyint"), columnType);
}
@Override
public boolean isSmallint(String columnType) {
return contains(Collections.singletonList("smallint"), columnType);
}
@Override
public boolean isInt(String columnType) {
return !isLong(columnType) && contains(Arrays.asList("int", "integer"), columnType);
}
@Override
public boolean isLong(String columnType) {
return !isVarchar(columnType) && contains(Collections.singletonList("bigint"), columnType);
}
@Override
public boolean isFloat(String columnType) {
return contains(Arrays.asList("float", "real"), columnType);
}
@Override
public boolean isDouble(String columnType) {
return contains(Collections.singletonList("double"), columnType);
}
@Override
public boolean isDecimal(String columnType) {
return contains(Arrays.asList("decimal", "numeric", "money", "smallmoney"), columnType);
}
@Override
public boolean isVarchar(String columnType) {
return contains(Arrays.asList("CHAR", "VARCHAR", "TEXT", "nchar", "nvarchar", "ntext"), columnType);
}
@Override
public boolean isDatetime(String columnType) {
return contains(Arrays.asList("TIME", "DATETIME", "TIMESTAMP", "datetime2", "smalldatetime", "datetimeoffset"), columnType);
}
@Override
public boolean isDate(String columnType) {
return contains(Collections.singletonList("DATE"), columnType);
}
@Override
public boolean isBlob(String columnType) {
return contains(Arrays.asList("blob", "binary", "varbinary"), columnType);
}
@Override
public boolean isJsonb(String columnType) {
return false;
}
}

View File

@@ -0,0 +1,67 @@
package com.gitee.gen.mapper;
import com.gitee.gen.entity.DatasourceConfig;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface DatasourceConfigMapper {
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
List<DatasourceConfig> listAll();
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
DatasourceConfig getById(Integer id);
/**
* 新增,插入所有字段
*
* @param datasourceConfig 新增的记录
* @return 返回影响行数
*/
int insert(DatasourceConfig datasourceConfig);
/**
* 新增忽略null字段
*
* @param datasourceConfig 新增的记录
* @return 返回影响行数
*/
int insertIgnoreNull(DatasourceConfig datasourceConfig);
/**
* 修改,修改所有字段
*
* @param datasourceConfig 修改的记录
* @return 返回影响行数
*/
int update(DatasourceConfig datasourceConfig);
/**
* 修改忽略null字段
*
* @param datasourceConfig 修改的记录
* @return 返回影响行数
*/
int updateIgnoreNull(DatasourceConfig datasourceConfig);
/**
* 删除记录
*
* @param datasourceConfig 待删除的记录
* @return 返回影响行数
*/
int delete(DatasourceConfig datasourceConfig);
}

View File

@@ -0,0 +1,76 @@
package com.gitee.gen.mapper;
import com.gitee.gen.entity.GenerateHistory;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface GenerateHistoryMapper {
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
List<GenerateHistory> listAll();
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
GenerateHistory getById(Integer id);
/**
* 新增,插入所有字段
*
* @param generateHistory 新增的记录
* @return 返回影响行数
*/
int insert(GenerateHistory generateHistory);
/**
* 新增忽略null字段
*
* @param generateHistory 新增的记录
* @return 返回影响行数
*/
int insertIgnoreNull(GenerateHistory generateHistory);
/**
* 修改,修改所有字段
*
* @param generateHistory 修改的记录
* @return 返回影响行数
*/
int update(GenerateHistory generateHistory);
/**
* 修改忽略null字段
*
* @param generateHistory 修改的记录
* @return 返回影响行数
*/
int updateIgnoreNull(GenerateHistory generateHistory);
/**
* 删除记录
*
* @param generateHistory 待删除的记录
* @return 返回影响行数
*/
int delete(GenerateHistory generateHistory);
/**
* 根据md5查询
*
* @param md5 md5
* @return 返回记录没有返回null
*/
GenerateHistory getByMd5(@Param("md5") String md5);
}

View File

@@ -0,0 +1,70 @@
package com.gitee.gen.mapper;
import java.util.List;
import com.gitee.gen.entity.SystemConfig;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface SystemConfigMapper {
SystemConfig getByKey(@Param("key") String key);
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
List<SystemConfig> listAll();
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
SystemConfig getById(Integer id);
/**
* 新增,插入所有字段
*
* @param systemConfig 新增的记录
* @return 返回影响行数
*/
int insert(SystemConfig systemConfig);
/**
* 新增忽略null字段
*
* @param systemConfig 新增的记录
* @return 返回影响行数
*/
int insertIgnoreNull(SystemConfig systemConfig);
/**
* 修改,修改所有字段
*
* @param systemConfig 修改的记录
* @return 返回影响行数
*/
int update(SystemConfig systemConfig);
/**
* 修改忽略null字段
*
* @param systemConfig 修改的记录
* @return 返回影响行数
*/
int updateIgnoreNull(SystemConfig systemConfig);
/**
* 删除记录
*
* @param systemConfig 待删除的记录
* @return 返回影响行数
*/
int delete(SystemConfig systemConfig);
}

View File

@@ -0,0 +1,79 @@
package com.gitee.gen.mapper;
import com.gitee.gen.entity.TemplateConfig;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface TemplateConfigMapper {
TemplateConfig getByName(@Param("name") String name, @Param("groupId") Integer groupId);
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
List<TemplateConfig> listAll();
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
TemplateConfig getById(Integer id);
/**
* 新增,插入所有字段
*
* @param templateConfig 新增的记录
* @return 返回影响行数
*/
int insert(TemplateConfig templateConfig);
/**
* 新增忽略null字段
*
* @param templateConfig 新增的记录
* @return 返回影响行数
*/
int insertIgnoreNull(TemplateConfig templateConfig);
/**
* 修改,修改所有字段
*
* @param templateConfig 修改的记录
* @return 返回影响行数
*/
int update(TemplateConfig templateConfig);
/**
* 修改忽略null字段
*
* @param templateConfig 修改的记录
* @return 返回影响行数
*/
int updateIgnoreNull(TemplateConfig templateConfig);
/**
* 删除记录
*
* @param templateConfig 待删除的记录
* @return 返回影响行数
*/
int delete(TemplateConfig templateConfig);
List<TemplateConfig> listByGroupId(String groupId);
List<TemplateConfig> listByGroupName(String groupName);
int updateGroupNameByGroupId(Integer groupId, String groupName);
int deleteByGroupId(Integer id);
List<TemplateConfig> listTemplate(@Param("idList") List<Integer> idList);
}

View File

@@ -0,0 +1,80 @@
package com.gitee.gen.mapper;
import com.gitee.gen.entity.TemplateGroup;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author : zsljava
* @date Date : 2020-12-15 9:50
* @Description: TODO
*/
@Mapper
public interface TemplateGroupMapper {
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
List<TemplateGroup> listAll();
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
TemplateGroup getById(Integer id);
/**
* 根据name查询
*
* @param name name
* @return 返回记录没有返回null
*/
TemplateGroup getByName(String name);
/**
* 新增,插入所有字段
*
* @param templateGroup 新增的记录
* @return 返回影响行数
*/
int insert(TemplateGroup templateGroup);
/**
* 新增忽略null字段
*
* @param templateGroup 新增的记录
* @return 返回影响行数
*/
int insertIgnoreNull(TemplateGroup templateGroup);
/**
* 修改,修改所有字段
*
* @param templateGroup 修改的记录
* @return 返回影响行数
*/
int update(TemplateGroup templateGroup);
/**
* 修改忽略null字段
*
* @param templateGroup 修改的记录
* @return 返回影响行数
*/
int updateIgnoreNull(TemplateGroup templateGroup);
/**
* 删除记录
*
* @param templateGroup 待删除的记录
* @return 返回影响行数
*/
int delete(TemplateGroup templateGroup);
}

View File

@@ -0,0 +1,67 @@
package com.gitee.gen.mapper;
import com.gitee.gen.entity.TypeConfig;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface TypeConfigMapper {
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
List<TypeConfig> listAll();
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
TypeConfig getById(Integer id);
/**
* 新增,插入所有字段
*
* @param typeConfig 新增的记录
* @return 返回影响行数
*/
int insert(TypeConfig typeConfig);
/**
* 新增忽略null字段
*
* @param typeConfig 新增的记录
* @return 返回影响行数
*/
int insertIgnoreNull(TypeConfig typeConfig);
/**
* 修改,修改所有字段
*
* @param typeConfig 修改的记录
* @return 返回影响行数
*/
int update(TypeConfig typeConfig);
/**
* 修改忽略null字段
*
* @param typeConfig 修改的记录
* @return 返回影响行数
*/
int updateIgnoreNull(TypeConfig typeConfig);
/**
* 删除记录
*
* @param typeConfig 待删除的记录
* @return 返回影响行数
*/
int delete(TypeConfig typeConfig);
}

View File

@@ -0,0 +1,63 @@
package com.gitee.gen.mapper;
import com.gitee.gen.entity.ColumnInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author tanghc
*/
@Mapper
public interface UpgradeMapper {
void runSql(@Param("sql") String sql);
/**
* 新增表字段
* @param tableName 表名
* @param columnName 字段名
* @param type 类型
*/
void addColumn(@Param("tableName") String tableName, @Param("columnName")String columnName,@Param("type") String type);
/**
* 新增dm表字段
* @param tableName 表名
* @param columnName 字段名
* @param type 类型
*/
void addColumnDm(@Param("tableName") String tableName, @Param("columnName")String columnName,@Param("type") String type);
/**
* 新增mysql表字段
* @param tableName 表名
* @param columnName 字段名
* @param type 类型
*/
void addColumnMysql(@Param("tableName") String tableName, @Param("columnName")String columnName,@Param("type") String type);
/**
* 查看表字段信息
* @param tableName 表名
* @return 返回字段信息
*/
List<ColumnInfo> listColumnInfo(@Param("tableName") String tableName);
/**
* 查看DM表字段信息
* @param tableName 表名
* @return 返回字段信息
*/
List<ColumnInfo> listColumnInfoDm(@Param("tableName") String tableName);
/**
* 查看MYSQL表字段信息
* @param tableName 表名
* @return 返回字段信息
*/
List<ColumnInfo> listColumnInfoMysql(@Param("tableName") String tableName, @Param("dbName") String dbName);
List<String> listTableName();
List<String> listTableNameDm();
List<String> listTableNameMysql();
}

View File

@@ -0,0 +1,45 @@
package com.gitee.gen.service;
import com.gitee.gen.config.ConnectConfig;
import com.gitee.gen.config.DbTypeConfig;
import com.gitee.gen.entity.DatasourceConfig;
import com.gitee.gen.mapper.DatasourceConfigMapper;
import org.apache.ibatis.solon.annotation.Db;
import org.noear.solon.annotation.Component;
import java.util.List;
/**
* @author tanghc
*/
@Component
public class DatasourceConfigService {
@Db
private DatasourceConfigMapper datasourceConfigMapper;
public DatasourceConfig getById(int id) {
return datasourceConfigMapper.getById(id);
}
public List<DatasourceConfig> listAll() {
return datasourceConfigMapper.listAll();
}
public void insert(DatasourceConfig templateConfig) {
templateConfig.setIsDeleted(0);
ConnectConfig connectConfig = DbTypeConfig.getInstance().getConnectConfig(templateConfig.getDbType());
if (connectConfig != null) {
templateConfig.setDriverClass(connectConfig.getDriver());
}
datasourceConfigMapper.insert(templateConfig);
}
public void update(DatasourceConfig templateConfig) {
datasourceConfigMapper.update(templateConfig);
}
public void delete(DatasourceConfig templateConfig) {
datasourceConfigMapper.delete(templateConfig);
}
}

View File

@@ -0,0 +1,106 @@
package com.gitee.gen.service;
import com.alibaba.fastjson.JSON;
import com.gitee.gen.common.GeneratorParam;
import com.gitee.gen.entity.GenerateHistory;
import com.gitee.gen.mapper.GenerateHistoryMapper;
import org.apache.ibatis.solon.annotation.Db;
import org.noear.solon.Utils;
import org.noear.solon.annotation.Component;
import java.util.Date;
import java.util.List;
@Component
public class GenerateHistoryService {
@Db
private GenerateHistoryMapper generateHistoryMapper;
public void saveHistory(GeneratorParam param) {
String content = JSON.toJSONString(param);
String md5 = Utils.md5(content);
GenerateHistory history = generateHistoryMapper.getByMd5(md5);
if (history != null) {
history.setGenerateTime(new Date());
generateHistoryMapper.updateIgnoreNull(history);
return;
}
GenerateHistory generateHistory = new GenerateHistory();
generateHistory.setConfigContent(content);
generateHistory.setMd5Value(md5);
generateHistory.setGenerateTime(new Date());
this.insertIgnoreNull(generateHistory);
}
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
public List<GenerateHistory> listAll() {
return generateHistoryMapper.listAll();
}
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
public GenerateHistory getById(Integer id) {
return generateHistoryMapper.getById(id);
}
/**
* 新增,插入所有字段
*
* @param generateHistory 新增的记录
* @return 返回影响行数
*/
public int insert(GenerateHistory generateHistory) {
return generateHistoryMapper.insert(generateHistory);
}
/**
* 新增忽略null字段
*
* @param generateHistory 新增的记录
* @return 返回影响行数
*/
public int insertIgnoreNull(GenerateHistory generateHistory) {
return generateHistoryMapper.insertIgnoreNull(generateHistory);
}
/**
* 修改,修改所有字段
*
* @param generateHistory 修改的记录
* @return 返回影响行数
*/
public int update(GenerateHistory generateHistory) {
return generateHistoryMapper.update(generateHistory);
}
/**
* 修改忽略null字段
*
* @param generateHistory 修改的记录
* @return 返回影响行数
*/
public int updateIgnoreNull(GenerateHistory generateHistory) {
return generateHistoryMapper.updateIgnoreNull(generateHistory);
}
/**
* 删除记录
*
* @param generateHistory 待删除的记录
* @return 返回影响行数
*/
public int delete(GenerateHistory generateHistory) {
return generateHistoryMapper.delete(generateHistory);
}
}

View File

@@ -0,0 +1,182 @@
package com.gitee.gen.service;
import com.gitee.gen.common.GeneratorParam;
import com.gitee.gen.entity.TemplateConfig;
import com.gitee.gen.gen.CodeFile;
import com.gitee.gen.gen.GeneratorConfig;
import com.gitee.gen.gen.SQLContext;
import com.gitee.gen.gen.SQLService;
import com.gitee.gen.gen.SQLServiceFactory;
import com.gitee.gen.gen.TableDefinition;
import com.gitee.gen.gen.TableSelector;
import com.gitee.gen.util.FormatUtil;
import com.gitee.gen.util.VelocityUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.VelocityContext;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 生成代码逻辑
*/
@Component
public class GeneratorService {
static ExecutorService executorService = Executors.newFixedThreadPool(2);
@Inject
private TemplateConfigService templateConfigService;
@Inject
private GenerateHistoryService generateHistoryService;
@Inject
private TypeConfigService typeConfigService;
@Inject("${gen.format-xml:false}")
private String formatXml;
/**
* 生成代码内容,map的
*
* @param generatorParam 生成参数
* @param generatorConfig 数据源配置
* @return 一张表对应多个模板
*/
public List<CodeFile> generate(GeneratorParam generatorParam, GeneratorConfig generatorConfig, Properties extConfig) {
List<SQLContext> contextList = this.buildSQLContextList(generatorParam, generatorConfig);
List<CodeFile> codeFileList = new ArrayList<>();
for (SQLContext sqlContext : contextList) {
sqlContext.setExtConfig(extConfig);
setPackageName(sqlContext, generatorParam.getPackageName());
setDelPrefix(sqlContext, generatorParam.getDelPrefix());
setAuthor(sqlContext, generatorParam.getAuthor());
for (int tcId : generatorParam.getTemplateConfigIdList()) {
TemplateConfig template = templateConfigService.getById(tcId);
String folder = template.getFolder();
if (StringUtils.isEmpty(folder)) {
folder = template.getName();
}else{
//文件目录可以使用变量
folder = doGenerator(sqlContext, folder);
}
setFolder(sqlContext, folder);
//获取文件名
String fileName = doGenerator(sqlContext, template.getFileName());
String content = doGenerator(sqlContext, template.getContent());
content = this.formatCode(fileName, content);
CodeFile codeFile = new CodeFile();
codeFile.setFolder(folder);
codeFile.setFileName(fileName);
codeFile.setContent(content);
codeFileList.add(codeFile);
}
}
executorService.execute(() -> {
generateHistoryService.saveHistory(generatorParam);
});
return codeFileList;
}
// 格式化代码
private String formatCode(String fileName, String content) {
if (Objects.equals("true", formatXml) && fileName.endsWith(".xml")) {
return FormatUtil.formatXml(content);
}
return content;
}
/**
* 返回SQL上下文列表
*
* @param generatorParam 参数
* @param generatorConfig 配置
* @return 返回SQL上下文
*/
private List<SQLContext> buildSQLContextList(GeneratorParam generatorParam, GeneratorConfig generatorConfig) {
List<String> tableNames = generatorParam.getTableNames();
List<SQLContext> contextList = new ArrayList<>();
SQLService service = SQLServiceFactory.build(generatorConfig);
TableSelector tableSelector = service.getTableSelector(generatorConfig);
tableSelector.setSchTableNames(tableNames);
tableSelector.setColumnTypeConverter(typeConfigService.buildColumnTypeConverter());
List<TableDefinition> tableDefinitions = tableSelector.getTableDefinitions();
for (TableDefinition tableDefinition : tableDefinitions) {
SQLContext sqlContext = new SQLContext(tableDefinition);
sqlContext.setDbName(generatorConfig.getDbName());
contextList.add(sqlContext);
}
return contextList;
}
private void setPackageName(SQLContext sqlContext, String packageName) {
if (StringUtils.isNotBlank(packageName)) {
sqlContext.setPackageName(packageName);
}
}
private void setFolder(SQLContext sqlContext, String folder) {
if (StringUtils.isNotBlank(folder)) {
sqlContext.setPackageSubPath(folder);
}
}
private void setDelPrefix(SQLContext sqlContext, String delPrefix) {
if (StringUtils.isNotBlank(delPrefix)) {
sqlContext.setDelPrefix(delPrefix);
}
}
private void setAuthor(SQLContext sqlContext, String author) {
if (StringUtils.isNotBlank(author)) {
sqlContext.setAuthor(author);
}
}
private String doGenerator(SQLContext sqlContext, String template) {
if (template == null) {
return "";
}
VelocityContext context = new VelocityContext();
Object pkColumn = sqlContext.getTableDefinition().getPkColumn();
if (pkColumn == null) {
pkColumn = Collections.emptyMap();
}
context.put("context", sqlContext);
context.put("table", sqlContext.getTableDefinition());
context.put("pk", pkColumn);
context.put("columns", sqlContext.getTableDefinition().getColumnDefinitions());
context.put("csharpColumns", sqlContext.getTableDefinition().getCsharpColumnDefinitions());
Properties extConfig = sqlContext.getExtConfig();
if (extConfig != null) {
for (Map.Entry<Object, Object> entry : extConfig.entrySet()) {
context.put(String.valueOf(entry.getKey()), entry.getValue());
}
}
return VelocityUtil.generate(context, template);
}
}

View File

@@ -0,0 +1,115 @@
package com.gitee.gen.service;
import com.gitee.gen.common.GeneratorParam;
import com.gitee.gen.entity.TemplateConfig;
import com.gitee.gen.gen.CodeFile;
import com.gitee.gen.gen.GeneratorConfig;
import org.apache.commons.io.FileUtils;
import org.noear.snack.core.utils.StringUtil;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author 六如
*/
@Component
public class LocalGenService {
@Inject
private GeneratorService generatorService;
@Inject
private TemplateConfigService templateConfigService;
/**
* 生成本地文件
*
* @param extConfig 配置
*/
public void genLocal(Properties extConfig) throws IOException {
check(extConfig);
GeneratorParam generatorParam = buildGeneratorParam(extConfig);
GeneratorConfig generatorConfig = buildGeneratorConfig(extConfig);
List<CodeFile> files = generatorService.generate(generatorParam, generatorConfig, extConfig);
for (CodeFile file : files) {
FileUtils.writeStringToFile(new File(file.getFileName()), file.getContent(), StandardCharsets.UTF_8);
System.out.println("生成文件:" + file.getFileName());
}
}
private void check(Properties extConfig) {
String moduleName = extConfig.getProperty("moduleName");
if (StringUtil.isEmpty(moduleName)) {
throw new IllegalArgumentException("moduleName 配置必填");
}
}
private GeneratorParam buildGeneratorParam(Properties extConfig) {
GeneratorParam generatorParam = new GeneratorParam();
generatorParam.setDatasourceConfigId(0);
String table = extConfig.getProperty("tables");
if (table == null) {
throw new RuntimeException("未指定表名");
}
String[] split = table.split(",");
generatorParam.setTableNames(Stream.of(split).collect(Collectors.toList()));
List<Integer> templateIds = templateConfigService.listByGroupName(extConfig.getProperty("groupName"))
.stream()
.map(TemplateConfig::getId)
.collect(Collectors.toList());
generatorParam.setTemplateConfigIdList(templateIds);
generatorParam.setPackageName("");
generatorParam.setDelPrefix("");
generatorParam.setAuthor(extConfig.getProperty("author"));
return generatorParam;
}
private GeneratorConfig buildGeneratorConfig(Properties extConfig) {
GeneratorConfig generatorConfig = new GeneratorConfig();
generatorConfig.setDbName(extConfig.getProperty("db.name"));
String driverClass = extConfig.getProperty("db.driverClass");
if (StringUtil.isEmpty(driverClass)) {
throw new RuntimeException("未指定driverClass");
}
generatorConfig.setDbType(buildDbType(driverClass));
generatorConfig.setPort(Integer.parseInt(extConfig.getProperty("db.port")));
generatorConfig.setHost(extConfig.getProperty("db.host"));
generatorConfig.setUsername(extConfig.getProperty("db.username"));
generatorConfig.setPassword(extConfig.getProperty("db.password"));
generatorConfig.setDriverClass(driverClass);
return generatorConfig;
}
private Integer buildDbType(String driverClass) {
if (driverClass.contains("mysql")) {
return 1;
}
if (driverClass.contains("OracleDriver")) {
return 2;
}
if (driverClass.contains("SQLServerDriver")) {
return 3;
}
if (driverClass.contains("postgresql")) {
return 4;
}
if (driverClass.contains("DmDriver")) {
return 5;
}
return 1;
}
}

View File

@@ -0,0 +1,105 @@
package com.gitee.gen.service;
import com.gitee.gen.entity.SystemConfig;
import com.gitee.gen.mapper.SystemConfigMapper;
import java.util.List;
import java.util.Optional;
import org.apache.ibatis.solon.annotation.Db;
import org.noear.solon.annotation.Component;
@Component
public class SystemConfigService {
@Db
private SystemConfigMapper systemConfigMapper;
public Optional<String> getValue(String key) {
SystemConfig config = systemConfigMapper.getByKey(key);
return Optional.ofNullable(config)
.map(SystemConfig::getConfigValue);
}
public void saveOrUpdate(SystemConfig systemConfig) {
SystemConfig config = systemConfigMapper.getByKey(systemConfig.getConfigKey());
if (config == null) {
systemConfigMapper.insert(systemConfig);
} else {
config.setConfigValue(systemConfig.getConfigValue());
config.setRemark(systemConfig.getRemark());
systemConfigMapper.update(config);
}
}
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
public List<SystemConfig> listAll() {
return systemConfigMapper.listAll();
}
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
public SystemConfig getById(Integer id) {
return systemConfigMapper.getById(id);
}
/**
* 新增,插入所有字段
*
* @param systemConfig 新增的记录
* @return 返回影响行数
*/
public int insert(SystemConfig systemConfig) {
return systemConfigMapper.insert(systemConfig);
}
/**
* 新增忽略null字段
*
* @param systemConfig 新增的记录
* @return 返回影响行数
*/
public int insertIgnoreNull(SystemConfig systemConfig) {
return systemConfigMapper.insertIgnoreNull(systemConfig);
}
/**
* 修改,修改所有字段
*
* @param systemConfig 修改的记录
* @return 返回影响行数
*/
public int update(SystemConfig systemConfig) {
return systemConfigMapper.update(systemConfig);
}
/**
* 修改忽略null字段
*
* @param systemConfig 修改的记录
* @return 返回影响行数
*/
public int updateIgnoreNull(SystemConfig systemConfig) {
return systemConfigMapper.updateIgnoreNull(systemConfig);
}
/**
* 删除记录
*
* @param systemConfig 待删除的记录
* @return 返回影响行数
*/
public int delete(SystemConfig systemConfig) {
return systemConfigMapper.delete(systemConfig);
}
}

View File

@@ -0,0 +1,123 @@
package com.gitee.gen.service;
import com.gitee.gen.entity.TemplateConfig;
import com.gitee.gen.mapper.TemplateConfigMapper;
import com.gitee.gen.util.StringUtil;
import com.gitee.gen.util.TemplateMetaUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.solon.annotation.Db;
import org.noear.solon.annotation.Component;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* @author tanghc
*/
@Component
public class TemplateConfigService {
@Db
private TemplateConfigMapper templateConfigMapper;
public List<TemplateConfig> listTemplate(List<Integer> idList) {
if (CollectionUtils.isEmpty(idList)) {
return Collections.emptyList();
}
return templateConfigMapper.listTemplate(idList);
}
public TemplateConfig getById(int id) {
return templateConfigMapper.getById(id);
}
public List<TemplateConfig> listAll() {
return templateConfigMapper.listAll();
}
public void insert(TemplateConfig templateConfig) {
String name = templateConfig.getName();
TemplateConfig existObj = templateConfigMapper.getByName(name, templateConfig.getGroupId());
if (existObj != null) {
throw new RuntimeException("模板名称 "+ name +" 已存在");
}
templateConfig.setIsDeleted(0);
templateConfigMapper.insert(templateConfig);
}
public void update(TemplateConfig templateConfig) {
String name = templateConfig.getName();
TemplateConfig existObj = templateConfigMapper.getByName(name, templateConfig.getGroupId());
if (existObj != null && !Objects.equals(templateConfig.getId(), existObj.getId())) {
throw new RuntimeException("模板名称 "+ name +" 已存在");
}
templateConfigMapper.updateIgnoreNull(templateConfig);
}
public void delete(TemplateConfig templateConfig) {
templateConfigMapper.delete(templateConfig);
}
public List<TemplateConfig> listByGroupId(String groupId) {
return templateConfigMapper.listByGroupId(groupId);
}
public List<TemplateConfig> listByGroupName(String groupName) {
return templateConfigMapper.listByGroupName(groupName);
}
public synchronized void save(TemplateConfig templateConfig) {
handleContent(templateConfig);
String name = templateConfig.getName();
TemplateConfig existObj = templateConfigMapper.getByName(name, templateConfig.getGroupId());
if(existObj == null) {
this.insert(templateConfig);
} else {
templateConfig.setId(existObj.getId());
this.update(templateConfig);
}
}
/**
* 复制模板
* @param templateConfig
*/
public void copy(TemplateConfig templateConfig) {
Integer id = templateConfig.getId();
TemplateConfig templateConfigById = this.getById(id);
if(templateConfigById == null){
throw new RuntimeException("要复制的模板不存在");
}
templateConfigById.setId(null);
templateConfigById.setName(templateConfig.getName());
this.save(templateConfigById);
}
/**
* 解析模板元信息, 即开始第一行是注释时
* <p>
* 格式: ## filename=#{xxx}.java, folder=entity
*/
private void handleContent(TemplateConfig template) {
String content = StringUtil.trimLeadingWhitespace(template.getContent());
// 解析元信息
Map<String, String> data = TemplateMetaUtils.parseMetaContent(content);
if (StringUtils.isEmpty(template.getFileName())) {
template.setFileName(data.get("filename"));
}
if (StringUtils.isEmpty(template.getFolder())) {
template.setFolder(data.get("folder"));
}
// 设置默认值
if (StringUtils.isEmpty(template.getFileName())) {
template.setFileName(template.getName());
}
if (StringUtils.isEmpty(template.getFolder())) {
template.setFolder(template.getName());
}
}
}

View File

@@ -0,0 +1,109 @@
package com.gitee.gen.service;
import com.gitee.gen.entity.TemplateGroup;
import com.gitee.gen.mapper.TemplateConfigMapper;
import com.gitee.gen.mapper.TemplateGroupMapper;
import org.apache.ibatis.solon.annotation.Db;
import org.noear.solon.annotation.Component;
import java.util.List;
/**
* @author : zsljava
* @date Date : 2020-12-15 9:50
* @Description: TODO
*/
@Component
public class TemplateGroupService {
@Db
private TemplateGroupMapper templateGroupMapper;
@Db
private TemplateConfigMapper templateConfigMapper;
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
public List<TemplateGroup> listAll() {
return templateGroupMapper.listAll();
}
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
public TemplateGroup getById(Integer id) {
return templateGroupMapper.getById(id);
}
/**
* 新增,插入所有字段
*
* @param templateGroup 新增的记录
* @return 返回影响行数
*/
public int insert(TemplateGroup templateGroup) {
return templateGroupMapper.insert(templateGroup);
}
/**
* 新增忽略null字段
*
* @param templateGroup 新增的记录
* @return 返回影响行数
*/
public int insertIgnoreNull(TemplateGroup templateGroup) {
templateGroup.setIsDeleted(0);
return templateGroupMapper.insertIgnoreNull(templateGroup);
}
/**
* 修改,修改所有字段
*
* @param templateGroup 修改的记录
* @return 返回影响行数
*/
public int update(TemplateGroup templateGroup) {
return templateGroupMapper.update(templateGroup);
}
/**
* 修改忽略null字段
*
* @param templateGroup 修改的记录
* @return 返回影响行数
*/
public int updateIgnoreNull(TemplateGroup templateGroup) {
return templateGroupMapper.updateIgnoreNull(templateGroup);
}
/**
* 删除记录
*
* @param templateGroup 待删除的记录
* @return 返回影响行数
*/
public int delete(TemplateGroup templateGroup) {
return templateGroupMapper.delete(templateGroup);
}
public int deleteGroup(TemplateGroup templateGroup) {
List<TemplateGroup> templateGroups = this.listAll();
if (templateGroups.size() == 1) {
throw new RuntimeException("无法删除,必须要有一个模板组");
}
int delete = templateGroupMapper.delete(templateGroup);
templateConfigMapper.deleteByGroupId(templateGroup.getId());
return delete;
}
public TemplateGroup getByName(String name) {
return templateGroupMapper.getByName(name);
}
}

View File

@@ -0,0 +1,97 @@
package com.gitee.gen.service;
import com.gitee.gen.entity.TypeConfig;
import com.gitee.gen.gen.converter.ColumnTypeConverter;
import com.gitee.gen.gen.converter.DbColumnTypeConverter;
import com.gitee.gen.mapper.TypeConfigMapper;
import org.apache.ibatis.solon.annotation.Db;
import org.noear.solon.annotation.Component;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
@Component
public class TypeConfigService {
@Db
private TypeConfigMapper typeConfigMapper;
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
public List<TypeConfig> listAll() {
return typeConfigMapper.listAll();
}
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
public TypeConfig getById(Integer id) {
return typeConfigMapper.getById(id);
}
/**
* 新增,插入所有字段
*
* @param typeConfig 新增的记录
* @return 返回影响行数
*/
public int insert(TypeConfig typeConfig) {
return typeConfigMapper.insert(typeConfig);
}
/**
* 新增忽略null字段
*
* @param typeConfig 新增的记录
* @return 返回影响行数
*/
public int insertIgnoreNull(TypeConfig typeConfig) {
return typeConfigMapper.insertIgnoreNull(typeConfig);
}
/**
* 修改,修改所有字段
*
* @param typeConfig 修改的记录
* @return 返回影响行数
*/
public int update(TypeConfig typeConfig) {
return typeConfigMapper.update(typeConfig);
}
/**
* 修改忽略null字段
*
* @param typeConfig 修改的记录
* @return 返回影响行数
*/
public int updateIgnoreNull(TypeConfig typeConfig) {
return typeConfigMapper.updateIgnoreNull(typeConfig);
}
/**
* 删除记录
*
* @param typeConfig 待删除的记录
* @return 返回影响行数
*/
public int delete(TypeConfig typeConfig) {
return typeConfigMapper.delete(typeConfig);
}
public ColumnTypeConverter buildColumnTypeConverter() {
List<TypeConfig> typeConfigs = typeConfigMapper.listAll();
Map<String, TypeConfig> map = typeConfigs.stream()
.collect(Collectors.toMap(TypeConfig::getDbType, Function.identity(), (v1, v2) -> v2));
return new DbColumnTypeConverter(map);
}
}

View File

@@ -0,0 +1,323 @@
package com.gitee.gen.service;
import com.gitee.gen.entity.ColumnInfo;
import com.gitee.gen.entity.SystemConfig;
import com.gitee.gen.mapper.UpgradeMapper;
import com.gitee.gen.util.SystemUtil;
import org.apache.ibatis.solon.annotation.Db;
import org.noear.solon.Solon;
import org.noear.solon.Utils;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.AppClassLoader;
import org.noear.solon.core.util.IoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
/**
* 升级
*
* @author tanghc
*/
@Component
public class UpgradeService {
private static final Logger log = LoggerFactory.getLogger(UpgradeService.class);
public static final String TABLE_DATASOURCE_CONFIG = "datasource_config";
public static final String TABLE_TEMPLATE_CONFIG = "template_config";
public static final String TABLE_TEMPLATE_GROUP = "template_group";
public static final String TABLE_GENERATE_HISTORY = "generate_history";
// 版本号格式xx.yy.zz1.16.0,1.16.11
private static final int CURRENT_VERSION = 200000;
public static final String GEN_VERSION = "GEN_VERSION";
private static final String DB_FILE_NAME = "gen.db";
@Db
private UpgradeMapper upgradeMapper;
@Inject
private SystemConfigService systemConfigService;
@Inject("${dbms.enable:false}")
private boolean useDbms;
@Inject("${gen.db2.driverClassName}")
private String driverClassName;
@Inject("${dbms.database:gen}")
private String dbName;
@Inject("${gen.init-file:gen_init.db}")
private String initFileName;
public void init() {
this.createTable("system_config");
int oldVersion = getOldVersion();
upgrade(oldVersion);
}
public void initDatabase() {
if (useDbms) {
log.info("使用DBMS跳过sqlit3文件初始化");
return;
}
File dbFile = getDbFile();
if (!dbFile.exists()) {
try {
dbFile.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
try (InputStream inputStream = AppClassLoader.getSystemResourceAsStream(initFileName)) {
Path path = dbFile.toPath();
log.info("初始化数据库文件, path={}", path);
OutputStream outputStream = Files.newOutputStream(path);
IoUtil.transferTo(inputStream, outputStream);
outputStream.close();
} catch (IOException e) {
throw new RuntimeException("初始化数据库失败", e);
}
}
}
private File getDbFile() {
String localDbPath = getLocalDbPath();
log.info("SQLite3 Database file:{}", localDbPath);
return new File(localDbPath);
}
public static String getLocalDbPath() {
String dbPath = Solon.cfg().get("LOCAL_DB", "");
if (Utils.isNotBlank(dbPath)) {
return dbPath.replace("${user.home}", SystemUtil.getUserHome());
} else {
return SystemUtil.getUserDir() + "/" + DB_FILE_NAME;
}
}
private int getOldVersion() {
return systemConfigService.getValue(GEN_VERSION)
.map(Integer::parseInt)
.orElse(0);
}
private void writeNewVersion() {
SystemConfig systemConfig = new SystemConfig();
systemConfig.setConfigKey(GEN_VERSION);
systemConfig.setConfigValue(String.valueOf(CURRENT_VERSION));
systemConfig.setRemark("版本号");
systemConfigService.saveOrUpdate(systemConfig);
}
/**
* 升级
*/
public void upgrade(int oldVersion) {
if (oldVersion == 0) {
upgradeV1_4_0();
upgradeV1_4_12();
upgradeV1_4_17();
upgradeV1_5_2();
}
doUpgrade(oldVersion);
writeNewVersion();
}
private void doUpgrade(int oldVersion) {
upgradeV1_6_0(oldVersion);
upgradeV2_0_0(oldVersion);
}
private void upgradeV2_0_0(int oldVersion) {
if (oldVersion < 200000) {
createTable("type_config", () -> {
runSql("insert into type_config(db_type, base_type, box_type) values\n" +
"('bit', 'boolean', 'Boolean')\n" +
",('boolean', 'boolean', 'Boolean')\n" +
",('tinyint', 'int', 'Integer')\n" +
",('smallint', 'int', 'Integer')\n" +
",('int', 'int', 'Integer')\n" +
",('bigint', 'long', 'Long')\n" +
",('float', 'float', 'Float')\n" +
",('double', 'double', 'Double')\n" +
",('decimal', 'BigDecimal', 'BigDecimal')\n" +
",('varchar', 'String', 'String')\n" +
",('datetime', 'Date', 'Date')\n" +
",('date', 'Date', 'Date')\n" +
",('blob', 'String', 'String')\n" +
",('jsonb', 'String', 'String')");
});
}
}
private void upgradeV1_6_0(int oldVersion) {
if (oldVersion < 101600) {
this.addColumn(TABLE_DATASOURCE_CONFIG, "db_desc", "varchar(64)");
this.addColumn(TABLE_DATASOURCE_CONFIG, "db_group_name", "varchar(64)");
}
}
private void upgradeV1_4_17() {
this.addColumn(TABLE_TEMPLATE_CONFIG, "folder", "varchar(64)");
}
private void upgradeV1_4_12() {
this.addColumn(TABLE_DATASOURCE_CONFIG, "schema_name", "varchar(100)");
}
/**
* 升级v1.4.0
*/
private void upgradeV1_4_0() {
this.createTable(TABLE_GENERATE_HISTORY);
boolean isCreate = this.createTable(TABLE_TEMPLATE_GROUP);
if (isCreate) {
runSql("INSERT INTO `template_group` (`id`, `group_name`, `is_deleted`) VALUES (1,'default',0)");
}
this.addColumn(TABLE_DATASOURCE_CONFIG, "package_name", "varchar(100)");
this.addColumn(TABLE_DATASOURCE_CONFIG, "del_prefix", "varchar(200)");
this.addColumn(TABLE_DATASOURCE_CONFIG, "group_id", "int");
this.addColumn(TABLE_TEMPLATE_CONFIG, "group_id", "int");
this.addColumn(TABLE_TEMPLATE_CONFIG, "group_name", "varchar(100)");
runSql("update template_config set group_id=1,group_name='default' where group_id IS NULL");
}
/**
* 升级v1.5.2
* 1、前端修复修改数据源时候不管什么数据库都带出oracle数据库
* 2、前端新增oracle类型数据库 数据库角色可以为空
* 3、前端修复数据库类型为oracle数据库时候测试连接服务器字段展示undefined问题
* 4、前后端新增author作者名配置方便模板中插入作者
* 5、后端修复postgresql数据库表如果没有设置主键无法获取列数组问题
*/
private void upgradeV1_5_2() {
this.addColumn(TABLE_DATASOURCE_CONFIG, "author", "varchar(255)");
}
private void runSql(String sql) {
upgradeMapper.runSql(sql);
}
/**
* 添加表字段
*
* @param tableName 表名
* @param columnName 字段名
* @param type 字段类型varchar(128),text,integer
* @return 返回true插入成功
*/
public boolean addColumn(String tableName, String columnName, String type) {
if (!isColumnExist(tableName, columnName)) {
try {
if (isMysql()) {
upgradeMapper.addColumnMysql(tableName, columnName, type);
} else if (isDm()) {
upgradeMapper.addColumnDm(tableName, columnName, type);
} else {
upgradeMapper.addColumn(tableName, columnName, type);
}
} catch (Exception e) {
log.error("add column error, tableName={}, columnName={}, type={}",
tableName, columnName, type, e);
}
return true;
}
return false;
}
/**
* 创建表
*
* @param tableName 表名
* @return 创建成功返回true
*/
public boolean createTable(String tableName, Runnable afterCreated) {
if (!isTableExist(tableName)) {
String sql = this.loadDDL(tableName);
upgradeMapper.runSql(sql);
if (afterCreated != null) {
afterCreated.run();
}
return true;
}
return false;
}
public boolean createTable(String tableName) {
return createTable(tableName, null);
}
private String loadDDL(String tableName) {
String tmp_dm = "ddl_%s_dm.txt";
String tmp_mysql = "ddl_%s_mysql.txt";
String tmp_sqlite = "ddl_%s_sqlite.txt";
String tmp = isDm() ? tmp_dm : (isMysql() ? tmp_mysql : tmp_sqlite);
String filename = "upgrade/" + String.format(tmp, tableName);
InputStream inputStream = AppClassLoader.getSystemResourceAsStream(filename);
if (inputStream == null) {
throw new RuntimeException("找不到文件:" + filename);
}
try {
return IoUtil.transferToString(inputStream);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("打开文件出错", e);
}
}
/**
* 判断列是否存在
*
* @param tableName 表名
* @param columnName 列名
* @return true存在
*/
public boolean isColumnExist(String tableName, String columnName) {
List<ColumnInfo> columnInfoList = isDm() ? upgradeMapper.listColumnInfoDm(tableName) :
(isMysql() ? upgradeMapper.listColumnInfoMysql(tableName, dbName) : upgradeMapper.listColumnInfo(tableName));
return columnInfoList
.stream()
.anyMatch(columnInfo -> Objects.equals(columnInfo.getName(), columnName));
}
/**
* 表是否存在
*
* @param tableName
* @return
*/
public boolean isTableExist(String tableName) {
List<String> tableNameList;
if (isMysql()) {
tableNameList = upgradeMapper.listTableNameMysql();
} else if (isDm()) {
tableNameList = upgradeMapper.listTableNameDm();
} else {
tableNameList = upgradeMapper.listTableName();
}
return tableNameList != null && tableNameList.contains(tableName);
}
private boolean isMysql() {
return useDbms && this.driverClassName.contains("mysql");
}
private boolean isDm() {
return useDbms && this.driverClassName.contains("dm");
}
}

View File

@@ -0,0 +1,372 @@
package com.gitee.gen.util;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
/**
* @author thc
*/
public class BeanUtil {
private static final Log logger = LogFactory.getLog(BeanUtil.class);
private static final String PREFIX_GET = "get";
private static final String PREFIX_SET = "set";
private static final String PREFIX_IS = "is";
private static final String GET_CLASS_NAME = "getClass";
/**
* 属性拷贝,第一个参数中的属性值拷贝到第二个参数中<br>
* 注意:当第一个参数中的属性有null值时,不会拷贝进去
*
* @param source 源对象
* @param target 目标对象
*/
public static void copyPropertiesIgnoreNull(Object source, Object target) {
copyProperties(source, target, true);
}
/**
* 属性拷贝,第一个参数中的属性值拷贝到第二个参数中<br>
* 注意:当第一个参数中的属性有null值时,不会拷贝进去
*
* @param source 源对象
* @param target 目标对象
* @param ignoreNullValue 是否忽略null值
*/
private static void copyPropertiesForMap(Map<String, Object> source, Object target, boolean ignoreNullValue) {
Objects.requireNonNull(source, "Source must not be null");
Objects.requireNonNull(target, "Target must not be null");
Method[] targetMethods = target.getClass().getMethods();
Map<String, MethodBean> setMethodMap = buildSetMethodMap(targetMethods);
Set<String> keys = source.keySet();
try {
for (String column : keys) {
Object sourceFieldValue = source.get(column);
if (ignoreNullValue && sourceFieldValue == null) {
continue;
}
MethodBean methodBean = setMethodMap.get(column);
// 如果为null转成驼峰再获取一次
if (methodBean == null) {
String fieldName = FieldUtil.underlineFilter(column);
methodBean = setMethodMap.get(fieldName);
}
if (methodBean == null) {
continue;
}
Class<?> paramType = methodBean.getParamType();
Object targetVal = parseValue(sourceFieldValue, paramType);
Method targetMethod = methodBean.getMethod();
setValue(targetMethod, target, targetVal);
}
} catch (Exception e) {
logger.error("copyPropertiesForMap error, source=" + source, e);
throw new RuntimeException(e);
}
}
/**
* 属性拷贝,第一个参数中的属性值拷贝到第二个参数中<br>
* 注意:当第一个参数中的属性有null值时,不会拷贝进去
*
* @param source 源对象
* @param target 目标对象
* @param ignoreNullValue 是否忽略null值
*/
private static void copyProperties(Object source, Object target, boolean ignoreNullValue) {
Objects.requireNonNull(source, "Source must not be null");
Objects.requireNonNull(target, "Target must not be null");
if (source instanceof Map) {
copyPropertiesForMap((Map<String, Object>) source, target, ignoreNullValue);
return;
}
Method[] sourceMethods = source.getClass().getMethods();
Method[] targetMethods = target.getClass().getMethods();
Map<String, MethodBean> setMethodMap = buildSetMethodMap(targetMethods);
try {
for (Method method : sourceMethods) {
if (isGetMethod(method)) {
String methodName = method.getName();
Class<?> returnType = method.getReturnType();
String sourceFieldName = buildFieldName(methodName);
Object sourceFieldValue = method.invoke(source);
if (ignoreNullValue && sourceFieldValue == null) {
continue;
}
MethodBean methodBean = setMethodMap.get(sourceFieldName);
if (methodBean == null) {
continue;
}
Class<?> paramType = methodBean.getParamType();
Method targetMethod = methodBean.getMethod();
if (paramType == returnType) {
setValue(targetMethod, target, sourceFieldValue);
}
}
}
} catch (Exception e) {
throw new RuntimeException("copyProperties error", e);
}
}
/**
* 返回所有的setXX方法key为对应的字段名称
*
* @param methods 方法列表
* @return 返回setXx方法对应关系key为对应的字段名称
*/
private static Map<String, MethodBean> buildSetMethodMap(Method[] methods) {
return Arrays.stream(methods)
.filter(BeanUtil::isSetMethod)
.collect(Collectors.toMap(method -> buildFieldName(method.getName()), method -> {
Class<?> parameterType = method.getParameterTypes()[0];
return new MethodBean(method, parameterType);
}));
}
private static void setValue(Method method, Object obj, Object value) throws InvocationTargetException, IllegalAccessException {
method.invoke(obj, value);
}
/**
* 属性拷贝,第一个参数中的属性值拷贝到第二个参数中<br>
* 注意:当第一个参数中的属性有null值时,不会拷贝进去
*
* @param source 源对象
* @param target 目标对象
*/
public static void copyProperties(Object source, Object target) {
Objects.requireNonNull(source, "Source must not be null");
Objects.requireNonNull(target, "Target must not be null");
copyProperties(source, target, false);
}
/**
* 深层次拷贝
*
* @param from 待转换的集合类
* @param toClass 目标类class
* @param <T> 目标类
* @return 返回目标类
*/
public static <T> List<T> copyBean(List<?> from, Class<T> toClass) {
if (from == null || from.isEmpty()) {
return new ArrayList<>();
}
return from.stream()
.filter(Objects::nonNull)
.map(source -> copyBean(source, toClass))
.collect(Collectors.toList());
}
/**
* 深层次拷贝通过json转换的方式实现
*
* @param from 待转换的类
* @param toClass 目标类class
* @param <T> 目标类
* @return 返回目标类
*/
public static <T> T copyBean(Object from, Class<T> toClass) {
if (from == null) {
return null;
}
T target = newInstance(toClass);
copyProperties(from, target);
return target;
}
private static <T> T newInstance(Class<T> clazz) {
try {
return clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException("create instance error", e);
}
}
/**
* 将实体对象转换成Map, key:实体类中的字段名称
*
* @param pojo 实体类
* @return 返回map, key:实体类中的字段名称, value实体类中的字段值
*/
public static Map<String, Object> pojoToMap(Object pojo) {
if (pojo == null) {
return Collections.emptyMap();
}
Method[] methods = pojo.getClass().getMethods();
Map<String, Object> map = new HashMap<>(methods.length * 2);
try {
for (Method method : methods) {
if (isGetMethod(method)) {
String methodName = method.getName();
String fieldName = buildFieldName(methodName);
Object value = method.invoke(pojo);
map.put(fieldName, value);
}
}
} catch (Exception e) {
throw new RuntimeException("pojoToMap失败", e);
}
return map;
}
// 构建列名
private static String buildFieldName(String methodName) {
if (methodName.startsWith(PREFIX_IS)) {
return methodName.substring(2, 3).toLowerCase() + methodName.substring(3);
}
return methodName.substring(3, 4).toLowerCase() + methodName.substring(4);
}
/**
* 是否是get方法
*/
private static boolean isGetMethod(Method method) {
Class<?> returnType = method.getReturnType();
if (returnType == Void.TYPE) {
return false;
}
String methodName = method.getName();
if (GET_CLASS_NAME.equals(methodName)) {
return false;
}
boolean isBooleanType = returnType == boolean.class || returnType == Boolean.class;
return methodName.startsWith(PREFIX_GET) || (isBooleanType && methodName.startsWith(PREFIX_IS));
}
/**
* 是否是set方法
*
* @param method
* @return
*/
private static boolean isSetMethod(Method method) {
return method.getName().startsWith(PREFIX_SET) && method.getParameterTypes().length == 1;
}
/**
* 单值转换
* @param value 单值
* @param valClass 转换的class类型
* @param <T> 类型
* @return 转换后的值
*/
public static <T> T parseValue(Object value, Class<T> valClass) {
if (value == null) {
return null;
}
if (valClass == Object.class) {
return (T) value;
}
if (valClass == String.class) {
return (T) String.valueOf(value);
}
// 处理时间类型
if (value.getClass() == Timestamp.class) {
Timestamp timestamp = (Timestamp) value;
if (valClass == Date.class) {
return (T) timestamp;
} else if (valClass == java.sql.Date.class) {
return (T) new java.sql.Date(timestamp.getTime());
} else if (valClass == LocalDateTime.class) {
return (T) timestamp.toLocalDateTime();
}
}
if ( valClass == Date.class && value.getClass() == LocalDateTime.class) {
LocalDateTime localDateTime = (LocalDateTime) value;
return (T) Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
T t = null;
// 转换单值byte、short短整数、int整数、long长整数、float单精度、double双精度、char字符和boolean布尔值
String strValue = String.valueOf(value);
if (valClass == Byte.class || valClass == byte.class) {
t = (T) Byte.valueOf(strValue);
}
if (valClass == Short.class || valClass == short.class) {
t = (T) Short.valueOf(strValue);
}
if (valClass == Integer.class || valClass == int.class) {
t = (T) Integer.valueOf(strValue);
}
if (valClass == Long.class || valClass == long.class) {
t = (T) Long.valueOf(strValue);
}
if (valClass == Float.class || valClass == float.class) {
t = (T) Float.valueOf(strValue);
}
if (valClass == Double.class || valClass == double.class) {
t = (T) Double.valueOf(strValue);
}
if (valClass == Character.class || valClass == char.class) {
t = (T) Character.valueOf(strValue.charAt(0));
}
if (valClass == BigDecimal.class) {
t = (T) (value.getClass() == BigDecimal.class ? value : new BigDecimal(strValue));
}
if (valClass == BigInteger.class) {
t = (T) (value.getClass() == BigInteger.class ? value : new BigInteger(strValue));
}
if (valClass == AtomicInteger.class) {
t = (T) (value.getClass() == AtomicInteger.class ? value : new AtomicInteger(Integer.valueOf(strValue)));
}
if (valClass == AtomicLong.class) {
t = (T) (value.getClass() == AtomicLong.class ? value : new AtomicLong(Long.valueOf(strValue)));
}
if (valClass == Boolean.class || valClass == boolean.class) {
String temp = strValue;
if ("0".equals(strValue)) {
temp = "false";
} else if ("1".equals(strValue)) {
temp = "true";
}
t = (T) Boolean.valueOf(temp);
}
if (t != null) {
return t;
}
// 转换其它单值
return (T) value;
}
static class MethodBean {
private final Method method;
private final Class<?> paramType;
public MethodBean(Method method, Class<?> paramType) {
this.method = method;
this.paramType = paramType;
}
public Method getMethod() {
return method;
}
public Class<?> getParamType() {
return paramType;
}
}
}

View File

@@ -0,0 +1,164 @@
package com.gitee.gen.util;
import org.apache.commons.lang.StringUtils;
import java.util.Objects;
public class FieldUtil {
public static final String UNDER_LINE = "_";
/**
* 下划线字段转驼峰 <br/>
*
* <pre>
* user_age -> userAge
* user_address_detail -> userAddressDetail
* user__age -> userAge
* name -> name
* _name -> _name
* _name_ -> _name_
* _user_age -> _userAge
* _user__age -> _userAge
* user_age_ -> userAge_
* _user_age_ -> _userAge_
* name__ -> name__
* __name -> __name
* </pre>
*
*
* @param field 字段
* @return 返回转换后的字段
*/
public static String underlineFilter(String field) {
if (StringUtils.isNotBlank(field)) {
char underLine = '_';
int underLineCountLeading = findCharCount(field, underLine, false);
int underLineCountTailing = findCharCount(field, underLine, true);
// 去除首尾'_'
field = StringUtil.trimLeadingCharacter(field, underLine);
field = StringUtil.trimTrailingCharacter(field, underLine);
if (isSingleAllUpper(field)) {
return field.toLowerCase();
}
if (field.contains(UNDER_LINE)) {
field = field.toLowerCase();
}
String[] arr = field.split("_+");
return join(arr, underLineCountLeading, underLineCountTailing);
}
return "";
}
/**
* 是不是全部大写的单词NAME, ADDRESS
* @param name 单词
* @return true
*/
private static boolean isSingleAllUpper(String name) {
if (name.contains(UNDER_LINE)) {
return false;
}
return Objects.equals(name, name.toUpperCase());
}
private static String join(String[] arr, int underLineCountLeading, int underLineCountTailing) {
if (arr.length > 1) {
for (int i = 1; i < arr.length; i++) {
arr[i] = upperFirstLetter(arr[i]);
}
}
StringBuilder ret = new StringBuilder();
char underLine = '_';
for (int i = 0; i < underLineCountLeading; i++) {
ret.append(underLine);
}
ret.append(String.join("", arr));
for (int i = 0; i < underLineCountTailing; i++) {
ret.append(underLine);
}
return ret.toString();
}
private static int findCharCount(String str, char searchChar, boolean reverse) {
if (StringUtils.isEmpty(str)) {
return 0;
}
int count = 0;
char[] chars = str.toCharArray();
if (reverse) {
for (int i = chars.length - 1; i >= 0; i--) {
if (chars[i] == searchChar) {
count++;
} else {
break;
}
}
} else {
for (char aChar : chars) {
if (aChar == searchChar) {
count++;
} else {
break;
}
}
}
return count;
}
public static String convertString(Object object) {
if (object == null) {
return "";
}
return String.valueOf(object);
}
/**
* 过滤"."
*
* @param field 字段
* @return 返回新字段
*/
public static String dotFilter(String field) {
if (StringUtils.isNotBlank(field)) {
if (field.contains(".")) {
String[] words = field.split("\\.");
StringBuilder ret = new StringBuilder();
for (String str : words) {
ret.append(upperFirstLetter(str));
}
return ret.toString();
}
}
return field;
}
/**
* 将第一个字母转换成大写。 name -> Name
*
* @param str 字符串
* @return 返回新字段
*/
public static String upperFirstLetter(String str) {
if (StringUtils.isNotBlank(str)) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
return str;
}
/**
* 将第一个字母转换成小写。Name -> name
*
* @param str 字符串
* @return 返回新内容
*/
public static String lowerFirstLetter(String str) {
if (StringUtils.isNotBlank(str)) {
return str.substring(0, 1).toLowerCase() + str.substring(1);
}
return str;
}
}

View File

@@ -0,0 +1,10 @@
package com.gitee.gen.util;
/**
* @author 六如
*/
public class FileUtil {
}

View File

@@ -0,0 +1,50 @@
package com.gitee.gen.util;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.StringReader;
import java.io.StringWriter;
/**
* 代码格式化
* @author tanghc
*/
public class FormatUtil {
public static String formatXml(String input) {
try{
SAXReader reader = new SAXReader();
// System.out.println(reader);
// 注释:创建一个串的字符输入流
StringReader in = new StringReader(input);
Document doc = reader.read(in);
// System.out.println(doc.getRootElement());
// 注释:创建输出格式
OutputFormat formater = OutputFormat.createPrettyPrint();
// formater=OutputFormat.createCompactFormat();
// 注释设置xml的输出编码
formater.setEncoding("utf-8");
// TAB缩进
formater.setIndent(" ");
// 注释:创建输出(目标)
StringWriter out = new StringWriter();
// 注释:创建输出流
XMLWriter writer = new XMLWriter(out, formater);
// 注释输出格式化的串到目标中执行后。格式化后的串保存在out中。
writer.write(doc);
writer.close();
// 注释:返回我们格式化后的结果
return out.toString();
}catch (Exception e) {
e.printStackTrace();
return input;
}
}
}

View File

@@ -0,0 +1,161 @@
package com.gitee.gen.util;
import com.gitee.gen.gen.TypeEnum;
import java.util.HashMap;
import java.util.Map;
/**
* 字段类型转换
*/
public class SqlTypeUtil {
private static final Map<String, String> javaTypeMap = new HashMap<>();
private static final Map<String, String> javaBoxTypeMap = new HashMap<>();
private static final Map<String, String> mybatisTypeMap = new HashMap<>();
static {
javaTypeMap.put("bigint", "long");
javaTypeMap.put("binary", "byte[]");
javaTypeMap.put("bit", "boolean");
javaTypeMap.put("boolean", "boolean");
javaTypeMap.put("blob", "byte[]");
javaTypeMap.put("char", "String");
javaTypeMap.put("date", "Date");
javaTypeMap.put("datetime", "Date");
javaTypeMap.put("decimal", "BigDecimal");
javaTypeMap.put("double", "double");
javaTypeMap.put("float", "float");
javaTypeMap.put("int", "int");
javaTypeMap.put("integer", "int");
javaTypeMap.put("image", "byte[]");
javaTypeMap.put("money", "BigDecimal");
javaTypeMap.put("nchar", "String");
javaTypeMap.put("ntext", "byte");
javaTypeMap.put("numeric", "BigDecimal");
javaTypeMap.put("nvarchar", "String");
javaTypeMap.put("real", "float");
javaTypeMap.put("smalldatetime", "Date");
javaTypeMap.put("smallint", "int");
javaTypeMap.put("smallmoney", "BigDecimal");
javaTypeMap.put("sql_variant", "String");
javaTypeMap.put("text", "String");
javaTypeMap.put("tinyint", "int");
javaTypeMap.put("timestamp", "Date");
javaTypeMap.put("uniqueidentifier", "String");
javaTypeMap.put("varbinary", "byte[]");
javaTypeMap.put("varchar", "String");
javaBoxTypeMap.put("bigint", "Long");
javaBoxTypeMap.put("binary", "Byte[]");
javaBoxTypeMap.put("bit", "Boolean");
javaBoxTypeMap.put("bool", "Boolean");
javaBoxTypeMap.put("boolean", "Boolean");
javaBoxTypeMap.put("blob", "Byte[]");
javaBoxTypeMap.put("char", "String");
javaBoxTypeMap.put("date", "Date");
javaBoxTypeMap.put("datetime", "Date");
javaBoxTypeMap.put("decimal", "BigDecimal");
javaBoxTypeMap.put("double", "Double");
javaBoxTypeMap.put("float", "Float");
javaBoxTypeMap.put("int", "Integer");
javaBoxTypeMap.put("integer", "Integer");
javaBoxTypeMap.put("image", "Byte[]");
javaBoxTypeMap.put("money", "BigDecimal");
javaBoxTypeMap.put("nchar", "String");
javaBoxTypeMap.put("ntext", "String");
javaBoxTypeMap.put("numeric", "BigDecimal");
javaBoxTypeMap.put("nvarchar", "String");
javaBoxTypeMap.put("real", "Float");
javaBoxTypeMap.put("smalldatetime", "Date");
javaBoxTypeMap.put("smallint", "Integer");
javaBoxTypeMap.put("smallmoney", "BigDecimal");
javaBoxTypeMap.put("sql_variant", "String");
javaBoxTypeMap.put("text", "String");
javaBoxTypeMap.put("tinyint", "Integer");
javaBoxTypeMap.put("timestamp", "Date");
javaBoxTypeMap.put("uniqueidentifier", "String");
javaBoxTypeMap.put("varbinary", "Byte[]");
javaBoxTypeMap.put("varchar", "String");
mybatisTypeMap.put("bigint", "BIGINT");
mybatisTypeMap.put("binary", "BLOB");
mybatisTypeMap.put("bit", "BOOLEAN");
mybatisTypeMap.put("boolean", "BOOLEAN");
mybatisTypeMap.put("blob", "BLOB");
mybatisTypeMap.put("char", "CHAR");
mybatisTypeMap.put("date", "TIMESTAMP");
mybatisTypeMap.put("datetime", "TIMESTAMP");
mybatisTypeMap.put("decimal", "DECIMAL");
mybatisTypeMap.put("double", "DOUBLE");
mybatisTypeMap.put("float", "FLOAT");
mybatisTypeMap.put("int", "INTEGER");
mybatisTypeMap.put("integer", "INTEGER");
mybatisTypeMap.put("image", "BLOB");
mybatisTypeMap.put("money", "DECIMAL");
mybatisTypeMap.put("nchar", "NCHAR");
mybatisTypeMap.put("ntext", "VARCHAR");
mybatisTypeMap.put("numeric", "DECIMAL");
mybatisTypeMap.put("nvarchar", "NVARCHAR");
mybatisTypeMap.put("real", "FLOAT");
mybatisTypeMap.put("smalldatetime", "TIMESTAMP");
mybatisTypeMap.put("smallint", "INTEGER");
mybatisTypeMap.put("smallmoney", "DECIMAL");
mybatisTypeMap.put("sql_variant", "VARCHAR");
mybatisTypeMap.put("text", "VARCHAR");
mybatisTypeMap.put("tinyint", "TINYINT");
mybatisTypeMap.put("timestamp", "TIMESTAMP");
mybatisTypeMap.put("uniqueidentifier", "VARCHAR");
mybatisTypeMap.put("varbinary", "BLOB");
mybatisTypeMap.put("varchar", "VARCHAR");
}
public static final Map<String, String> TYPE_MYBATIS_MAP = new HashMap<>(64);
static {
TYPE_MYBATIS_MAP.put(TypeEnum.BIT.getType(), "BOOLEAN");
TYPE_MYBATIS_MAP.put(TypeEnum.BOOLEAN.getType(), "BOOLEAN");
TYPE_MYBATIS_MAP.put(TypeEnum.TINYINT.getType(), "TINYINT");
TYPE_MYBATIS_MAP.put(TypeEnum.SMALLINT.getType(), "INTEGER");
TYPE_MYBATIS_MAP.put(TypeEnum.INT.getType(), "INTEGER");
TYPE_MYBATIS_MAP.put(TypeEnum.BIGINT.getType(), "BIGINT");
TYPE_MYBATIS_MAP.put(TypeEnum.FLOAT.getType(), "FLOAT");
TYPE_MYBATIS_MAP.put(TypeEnum.DOUBLE.getType(), "DOUBLE");
TYPE_MYBATIS_MAP.put(TypeEnum.DECIMAL.getType(), "DECIMAL");
TYPE_MYBATIS_MAP.put(TypeEnum.VARCHAR.getType(), "VARCHAR");
TYPE_MYBATIS_MAP.put(TypeEnum.DATETIME.getType(), "TIMESTAMP");
TYPE_MYBATIS_MAP.put(TypeEnum.BLOB.getType(), "BLOB");
}
/**
* 将sql字段类型转换为java字段类型
* @param sqlType 数据库字段类型
* @return 找不到类型默认返回String
*/
public static String convertToJavaType(String sqlType){
String javaType = javaTypeMap.get(sqlType);
return javaType == null ? "String" : javaType;
}
/**
* 将sql字段类型转换为java装箱字段类型
* @param sqlType 数据库字段类型
* @return 找不到类型默认返回String
*/
public static String convertToJavaBoxType(String sqlType){
String javaType = javaBoxTypeMap.get(sqlType);
return javaType == null ? "String" : javaType;
}
/**
* 将sql字段类型转换为mybatis的jdbcType
* @param sqlType 数据库字段类型
* @return 找不到类型默认返回VARCHAR
*/
public static String convertToMyBatisJdbcType(String sqlType){
String javaType = mybatisTypeMap.get(sqlType);
return javaType == null ? "VARCHAR" : javaType;
}
}

View File

@@ -0,0 +1,51 @@
package com.gitee.gen.util;
import org.apache.commons.lang.StringUtils;
/**
* @author thc
*/
public class StringUtil {
/**
* Trim leading whitespace from the given {@code String}.
* @param str the {@code String} to check
* @return the trimmed {@code String}
* @see Character#isWhitespace
*/
public static String trimLeadingWhitespace(String str) {
if (StringUtils.isBlank(str)) {
return str;
}
int beginIdx = 0;
while (beginIdx < str.length() && Character.isWhitespace(str.charAt(beginIdx))) {
beginIdx++;
}
return str.substring(beginIdx);
}
public static String trimLeadingCharacter(String str, char leadingCharacter) {
if (StringUtils.isBlank(str)) {
return str;
}
int beginIdx = 0;
while (beginIdx < str.length() && leadingCharacter == str.charAt(beginIdx)) {
beginIdx++;
}
return str.substring(beginIdx);
}
public static String trimTrailingCharacter(String str, char trailingCharacter) {
if (StringUtils.isBlank(str)) {
return str;
}
int endIdx = str.length() - 1;
while (endIdx >= 0 && trailingCharacter == str.charAt(endIdx)) {
endIdx--;
}
return str.substring(0, endIdx + 1);
}
}

View File

@@ -0,0 +1,45 @@
package com.gitee.gen.util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
/**
* @author tanghc
*/
public class SystemUtil {
private static volatile String binPath;
/**
* 获取程序执行目录即jar包所在的目录。此方法只在部署后有用开发模式下这里返回target路径
*
* @return 返回路径
*/
public static String getBinPath() {
if (binPath == null) {
synchronized (SystemUtil.class) {
if (binPath == null) {
String path = SystemUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath();
try {
path = URLDecoder.decode(path, "UTF-8");
path = StringUtil.trimTrailingCharacter(path, '/');
int index = path.lastIndexOf('/');
path = path.substring(0, index);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
binPath = path;
}
}
}
return binPath;
}
public static String getUserDir() {
return System.getProperty("user.dir");
}
public static String getUserHome() {
return System.getProperty("user.home");
}
}

View File

@@ -0,0 +1,106 @@
package com.gitee.gen.util;
import com.gitee.gen.entity.TemplateConfig;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* 模板元信息工具类
*/
public final class TemplateMetaUtils {
private TemplateMetaUtils() {
}
/**
* 解析模板内容中的元信息
*/
public static Map<String, String> parseMetaContent(String content) {
content = StringUtil.trimLeadingWhitespace(content);
if (content != null && content.startsWith("##")) {
int rowIdx = content.indexOf('\n');
String metaInfo = content.substring(2, rowIdx);
return parseMetaRow(metaInfo);
}
return Collections.emptyMap();
}
/**
* 解析元数据信息
*/
public static Map<String, String> parseMetaRow(String row) {
char[] charArray = row.toCharArray();
Map<String, String> data = new HashMap<>();
StringBuilder kvBuilder = new StringBuilder();
// 剩余未闭合表达式数量
int leftExpr = 0;
for (int i = 0, len = charArray.length, end = len - 1; i < len; i++) {
char c = charArray[i];
boolean kvEnd = false;
if (i == end) {
kvBuilder.append(c);
kvEnd = true;
} else if (',' == c && leftExpr == 0) {
kvEnd = true;
}
if (kvEnd) {
String[] kv = kvBuilder.toString().trim().split("=");
data.put(kv[0].trim(), kv.length == 1 ? null : kv[1].trim());
kvBuilder = new StringBuilder();
continue;
}
kvBuilder.append(c);
switch (c) {
case '{':
case '(':
leftExpr++;
break;
case '}':
case ')':
leftExpr--;
break;
default:
break;
}
}
if (leftExpr > 0) {
throw new RuntimeException("读取元数据失败,有" + leftExpr + "个表达式未闭合");
}
return data;
}
/**
* 生成元数据的模板内容
*/
public static String generateMetaContent(TemplateConfig template) {
String content = StringUtil.trimLeadingWhitespace(template.getContent());
String metaRow = generateMetaRow(template);
if (content.startsWith("##")) {
int rowIdx = content.indexOf('\n');
if(rowIdx == -1) {
content = metaRow;
} else {
content = metaRow + content.substring(rowIdx);
}
} else {
content = metaRow + "\n" + content;
}
return content;
}
/**
* 解析元数据信息
*/
public static String generateMetaRow(TemplateConfig template) {
String format = "## filename=%s, folder=%s";
String filename = template.getFileName() != null ? template.getFileName() : "";
String folder = template.getFolder() != null ? template.getFolder() : "";
return String.format(format, filename, folder);
}
}

View File

@@ -0,0 +1,42 @@
package com.gitee.gen.util;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.log.NullLogChute;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
/**
* Velocity工具类,根据模板内容生成文件
*/
public class VelocityUtil {
private VelocityUtil() {
super();
}
static {
// 禁止输出日志
Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, new NullLogChute());
Velocity.init();
}
private final static String LOG_TAG = "velocity_log";
public static String generate(VelocityContext context, String template) {
StringReader reader = new StringReader(template);
StringWriter writer = new StringWriter();
// 不用vm文件
Velocity.evaluate(context, writer, LOG_TAG, reader);
try {
writer.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return writer.toString();
}
}

View File

@@ -0,0 +1,88 @@
solon.app:
name: gen
server:
port: 6969
# sqlite3
#LOCAL_DB: ${user.home}/gen.db
gen.db1:
url: "jdbc:sqlite:"
driverClassName: org.sqlite.JDBC
userName:
password:
# mysql
dbms:
enable: false
# host: localhost:3306
# database: gen
# username: root
# password: root
gen.db2:
url: jdbc:mysql://${dbms.host:localhost:3306}/${dbms.database:gen}?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
driverClassName: com.mysql.cj.jdbc.Driver
userName: ${dbms.username:gen}
password: ${dbms.password:}
# 配置数据源对应的 mybatis 信息(要与 DataSource bean 的名字对上)
mybatis.db1:
mappers: #支持包名 或 类名(大写开头 或 *)或 xml.xml结尾//支持 ** 或 * 占位符
- "com.gitee.gen.mapper.*" #这个表达式同上效果
- "classpath:mybatis/**/*.xml"
configuration: #扩展配置(要与 Configuration 类的属性一一对应)
cacheEnabled: false
mapperVerifyEnabled: true #如果为 true则要求所有 mapper 有 @Mapper 主解
mapUnderscoreToCamelCase: true
gen:
format-xml: ${GEN_FORMAT_XML:true}
db-name: ${GEN_DBNAME:gen}
# log
solon.logging.appender:
console:
level: INFO
enable: true #是否启用
file:
name: "logs/${solon.app.name}"
level: INFO
enable: false #是否启用
extension: ".log" #v2.2.18 后支持(例:.log, .log.gz, .log.zip
maxFileSize: "10 MB"
maxHistory: "7"
cloud:
level: INFO
enable: false #是否启用
# 2.0.3新增
# 连接方式管理, {HOST},{PORT},{DB_NAME} 表示占位符
connect:
1:
name: MySQL
driver: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://{HOST}:{PORT}/{DB_NAME}?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
serviceName: com.gitee.gen.gen.mysql.MySqlService
2:
name: Oracle
driver: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@{HOST}:{PORT}{DB_NAME}
serviceName: com.gitee.gen.gen.oracle.OracleService
3:
name: "SQL Server"
driver: com.microsoft.sqlserver.jdbc.SQLServerDriver
url: jdbc:sqlserver://{HOST}:{PORT};DatabaseName={DB_NAME};trustServerCertificate=true
serviceName: com.gitee.gen.gen.sqlserver.SqlServerService
4:
name: PostgreSQL
driver: org.postgresql.Driver
url: jdbc:postgresql://{HOST}:{PORT}/{DB_NAME}
serviceName: com.gitee.gen.gen.postgresql.PostgreSqlService
5:
name: "达梦"
driver: dm.jdbc.driver.DmDriver
url: jdbc:dm://{HOST}:{PORT}/{DB_NAME}
serviceName: com.gitee.gen.gen.dm.DmService

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More