初始代码

This commit is contained in:
wangmingwei
2026-04-21 17:41:09 +08:00
parent 186ec6683a
commit b686ecac5f
493 changed files with 52349 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
<?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">
<parent>
<artifactId>yunzhupaas-boot-common</artifactId>
<groupId>com.yunzhupaas</groupId>
<version>5.2.0-RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yunzhupaas-common-database</artifactId>
<dependencies>
<!-- mybatisplus -->
<dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join-boot-starter</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- sqlserver -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<!-- oracle -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.nls</groupId>
<artifactId>orai18n</artifactId>
</dependency>
<!-- dm -->
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
</dependency>
<!--人大金仓-->
<dependency>
<groupId>cn.com.kingbase</groupId>
<artifactId>kingbase8</artifactId>
</dependency>
<!--PostGre-->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!--GaussDB-->
<!--<dependency>
<groupId>org.opengauss</groupId>
<artifactId>opengauss-jdbc</artifactId>
</dependency>-->
<!--HighgoDB-->
<!--<dependency>
<groupId>com.highgo</groupId>
<artifactId>hgdb-pgjdbc</artifactId>
</dependency>-->
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- redis模块 -->
<dependency>
<groupId>com.yunzhupaas</groupId>
<artifactId>yunzhupaas-common-auth</artifactId>
</dependency>
<!-- &lt;!&ndash; SpringBoot Admin 客户端 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>de.codecentric</groupId>-->
<!-- <artifactId>spring-boot-admin-starter-client</artifactId>-->
<!-- <version>${spring-boot-admin.version}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-context</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<exclusions>
<exclusion>
<artifactId>jsqlparser</artifactId>
<groupId>com.github.jsqlparser</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<profiles>
<profile>
<id>boot3</id>
<activation>
<jdk>[17,)</jdk>
</activation>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId><exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</profile>
<profile>
<id>boot2</id>
<activation>
<jdk>(,17)</jdk>
</activation>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId><exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

View File

@@ -0,0 +1,27 @@
package com.yunzhupaas.base.controller;
import com.yunzhupaas.base.service.SuperService;
import org.springframework.beans.factory.annotation.Autowired;
import java.lang.reflect.ParameterizedType;
public abstract class SuperController<S extends SuperService<Entity>, Entity> {
@Autowired
protected S baseService;
Class<Entity> entityClass = null;
public Class<Entity> getEntityClass() {
if (entityClass == null) {
this.entityClass = (Class<Entity>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
}
return this.entityClass;
}
public S getBaseService() {
return baseService;
}
}

View File

@@ -0,0 +1,203 @@
package com.yunzhupaas.base.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.yunzhupaas.database.util.IgnoreLogicDeleteHolder;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.ResultHandler;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public interface SuperMapper<T> extends MPJBaseMapper<T> {
/**
* 调用此方法后 后续SQL操作忽略逻辑删除筛选
* 调用完成后需要调用clearIgnoreLogicDelete 清除标记
* @return
*/
default SuperMapper<T> setIgnoreLogicDelete(){
IgnoreLogicDeleteHolder.setIgnoreLogicDelete();
return this;
}
/**
* 调用此方法后 后续SQL恢复逻辑删除筛选
* @return
*/
default SuperMapper<T> clearIgnoreLogicDelete(){
IgnoreLogicDeleteHolder.clear();
return this;
}
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteByIdIlg(Serializable id);
/**
* 根据实体(ID)删除
*
* @param entity 实体对象
* @since 3.4.4
*/
int deleteByIdIlg(T entity);
/**
* 根据 entity 条件,删除记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int deleteIlg(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 删除根据ID或实体 批量删除)
*
* @param idList 主键ID列表或实体列表(不能为 null 以及 empty)
*/
int deleteBatchIdsIlg(@Param(Constants.COLL) Collection<?> idList);
/**
* 根据 ID 修改
*
* @param entity 实体对象
*/
int updateByIdIlg(@Param(Constants.ENTITY) T entity);
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int updateIlg(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
T selectByIdIlg(Serializable id);
/**
* 查询根据ID 批量查询)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIdsIlg(@Param(Constants.COLL) Collection<? extends Serializable> idList);
/**
* 查询根据ID 批量查询)
*
* @param idList idList 主键ID列表(不能为 null 以及 empty)
* @param resultHandler resultHandler 结果处理器 {@link ResultHandler}
* @since 3.5.4
*/
void selectBatchIdsIlg(@Param(Constants.COLL) Collection<? extends Serializable> idList, ResultHandler<T> resultHandler);
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null
*/
Long selectCountIlg(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null
*/
List<T> selectListIlg(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null
* @param resultHandler 结果处理器 {@link ResultHandler}
* @since 3.5.4
*/
void selectListIlg(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper, ResultHandler<T> resultHandler);
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类(可以为 null
* @since 3.5.3.2
*/
List<T> selectListIlg(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录(并翻页)
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类(可以为 null
* @param resultHandler 结果处理器 {@link ResultHandler}
* @since 3.5.4
*/
void selectListIlg(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper, ResultHandler<T> resultHandler);
/**
* 根据 Wrapper 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类
*/
List<Map<String, Object>> selectMapsIlg(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类
* @param resultHandler 结果处理器 {@link ResultHandler}
* @since 3.5.4
*/
void selectMapsIlg(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper, ResultHandler<Map<String, Object>> resultHandler);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
* @since 3.5.3.2
*/
List<Map<String, Object>> selectMapsIlg(IPage<? extends Map<String, Object>> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
* @param resultHandler 结果处理器 {@link ResultHandler}
* @since 3.5.4
*/
void selectMapsIlg(IPage<? extends Map<String, Object>> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper, ResultHandler<Map<String, Object>> resultHandler);
/**
* 根据 Wrapper 条件,查询全部记录
* <p>注意: 只返回第一个字段的值</p>
*
* @param queryWrapper 实体对象封装操作类(可以为 null
*/
<E> List<E> selectObjsIlg(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* <p>注意: 只返回第一个字段的值</p>
*
* @param queryWrapper 实体对象封装操作类(可以为 null
* @param resultHandler 结果处理器 {@link ResultHandler}
* @since 3.5.4
*/
<E> void selectObjsIlg(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper, ResultHandler<E> resultHandler);
}

View File

@@ -0,0 +1,28 @@
package com.yunzhupaas.base.service;
import com.github.yulichang.base.MPJBaseService;
import com.yunzhupaas.database.util.IgnoreLogicDeleteHolder;
public interface SuperService<T> extends MPJBaseService<T> {
/**
* 调用此方法后 后续SQL操作忽略逻辑删除筛选
* 调用完成后需要调用clearIgnoreLogicDelete 清除标记
* @return
*/
default SuperService<T> setIgnoreLogicDelete(){
IgnoreLogicDeleteHolder.setIgnoreLogicDelete();
return this;
}
/**
* 调用此方法后 后续SQL恢复逻辑删除筛选
* @return
*/
default SuperService<T> clearIgnoreLogicDelete(){
IgnoreLogicDeleteHolder.clear();
return this;
}
}

View File

@@ -0,0 +1,83 @@
package com.yunzhupaas.base.service;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.yunzhupaas.base.mapper.SuperMapper;
import com.yunzhupaas.util.DateUtil;
import com.yunzhupaas.util.UserProvider;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import java.util.Collection;
import java.util.Date;
public abstract class SuperServiceImpl<M extends SuperMapper<T>, T> extends MPJBaseServiceImpl<M, T> implements SuperService<T> {
private final ConversionService conversionService = DefaultConversionService.getSharedInstance();
/**
* 填充删除用户与删除时间
* @param entity 实体
* @return
*/
@Override
public boolean removeById(T entity) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(getEntityClass());
if (tableInfo.isWithLogicDelete() && tableInfo.isWithUpdateFill()) {
try{
if(tableInfo.getPropertyValue(entity, "deleteUserId") == null){
String userId = UserProvider.getLoginUserId();
if (userId != null) {
Date deleteTime = DateUtil.getNowDate();
tableInfo.setPropertyValue(entity, "deleteUserId" , userId);
tableInfo.setPropertyValue(entity, "deleteTime" , deleteTime);
}
}
}catch (Exception e){ }
}
return super.removeById(entity);
}
/**
* 填充删除用户与删除时间
* @param list 主键ID或实体列表
* @param batchSize 批次大小
* @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)
* @return
*/
@Override
public boolean removeBatchByIds(Collection<?> list, int batchSize, boolean useFill) {
String sqlStatement = getSqlStatement(SqlMethod.DELETE_BY_ID);
TableInfo tableInfo = TableInfoHelper.getTableInfo(getEntityClass());
return executeBatch(list, batchSize, (sqlSession, e) -> {
if (useFill && tableInfo.isWithLogicDelete()) {
if (getEntityClass().isAssignableFrom(e.getClass())) {
sqlSession.update(sqlStatement, e);
} else {
T instance = tableInfo.newInstance();
Object value = tableInfo.getKeyType() != e.getClass() ? conversionService.convert(e, tableInfo.getKeyType()) : e;
tableInfo.setPropertyValue(instance, tableInfo.getKeyProperty(), value);
try{
if(tableInfo.getPropertyValue(instance, "deleteUserId") == null){
String userId = UserProvider.getLoginUserId();
if (userId != null) {
Date deleteTime = DateUtil.getNowDate();
tableInfo.setPropertyValue(instance, "deleteUserId" , userId);
tableInfo.setPropertyValue(instance, "deleteTime" , deleteTime);
}
}
}catch (Exception ex){ }
sqlSession.update(sqlStatement, instance);
}
} else {
sqlSession.update(sqlStatement, e);
}
});
}
}

View File

@@ -0,0 +1,81 @@
package com.yunzhupaas.database.config;
import com.alibaba.druid.support.jakarta.StatViewServlet;
import com.alibaba.druid.support.jakarta.WebStatFilter;
import com.yunzhupaas.database.util.ConnUtil;
import com.yunzhupaas.database.util.DataSourceUtil;
import com.yunzhupaas.exception.DataException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 数据源配置
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/16 8:49
*/
@Configuration
public class DruidConfig {
@Autowired
DataSourceUtil dataSourceUtil;
// @Bean
public DataSource druid() throws DataException {
return ConnUtil.getDruidDataSource(dataSourceUtil);
}
/**
* 配置Druid的监控
* 配置一个管理后台的Servlet
* @return
*/
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String, String> initParams = new HashMap<>(4);
//配置druid页面监控的账户密码
initParams.put("loginUsername", "com.yunzhupaas");
initParams.put("loginPassword","123456");
//默认就是允许所有访问
initParams.put("allow","");
//黑名单 注意 黑名单优先于 allow白名单加载 两个名单中不可重复
initParams.put("deny","192.168.10.21");
bean.setInitParameters(initParams);
return bean;
}
/**
* 配置一个web监控的filter
* @return
*/
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String, String> initParams = new HashMap<>(16);
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}

View File

@@ -0,0 +1,90 @@
package com.yunzhupaas.database.config;
import com.github.yitter.contract.IdGeneratorOptions;
import com.github.yitter.idgen.YitIdHelper;
import jakarta.annotation.PreDestroy;
import com.yunzhupaas.util.CacheKeyUtil;
import com.yunzhupaas.util.ThreadPoolExecutorUtil;
import com.yunzhupaas.util.context.SpringContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;
import java.util.Random;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class IdGeneratorConfig {
private static final String ID_IDX = CacheKeyUtil.IDGENERATOR + "Index:";
private RedisTemplate<String, Long> redisTemplate;
//ID缓存有效时间 定时刷新有效期
private static final long CacheTimeout = 60L * 60 * 24;
//30分钟续期一次 如果Redis被清空可以早点续期
private static final long ScheduleTimeout = 60L * 30;
private static final byte WorkerIdBitLength = 16;
//65535 参数为shot 最大值为Short.MAX_VALUE
private static final int MaxWorkerIdNumberByMode = (1 << WorkerIdBitLength) -1 >Short.MAX_VALUE?Short.MAX_VALUE : (1 << WorkerIdBitLength) -1 ;
private static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
private short workerId = -1;
private String cacheKey;
/**
* 初始化雪花生成器WorkerID 通过Redis实现集群获取不同的编号 如果相同会出现ID重复
*/
@Bean
private void initIdWorker(){
redisTemplate = SpringContext.getBean("redisTemplate");
if(redisTemplate != null) {
RedisAtomicLong redisAtomicLong = new RedisAtomicLong(ID_IDX, redisTemplate.getConnectionFactory());
for (int i = 0; i <= MaxWorkerIdNumberByMode; i++) {
long andInc = redisAtomicLong.getAndIncrement();
long result = andInc % (MaxWorkerIdNumberByMode + 1);
//计数超出上限之后重新计数
if (andInc >= MaxWorkerIdNumberByMode) {
redisAtomicLong.set(andInc % (MaxWorkerIdNumberByMode));
}
cacheKey = ID_IDX + result;
boolean useSuccess = redisTemplate.opsForValue().setIfAbsent(cacheKey, System.currentTimeMillis(), CacheTimeout, TimeUnit.SECONDS);
if (useSuccess) {
workerId = (short) result;
break;
}
}
if (workerId == -1) {
throw new RuntimeException(String.format("已尝试生成%d个ID生成器编号, 无法获取到可用编号", MaxWorkerIdNumberByMode + 1));
}
}else{
workerId = (short) new Random().nextInt(MaxWorkerIdNumberByMode);
}
log.info("当前ID生成器编号: " + workerId);
IdGeneratorOptions options = new IdGeneratorOptions(workerId);
options.WorkerIdBitLength = WorkerIdBitLength;
YitIdHelper.setIdGenerator(options);
scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1, ThreadPoolExecutorUtil.getExecutor().getThreadPoolExecutor().getThreadFactory());
//提前一分钟续期
scheduledThreadPoolExecutor.scheduleWithFixedDelay(resetExpire, ScheduleTimeout, ScheduleTimeout, TimeUnit.SECONDS);
}
private Runnable resetExpire = ()->{
//重新设值, 如果Redis被意外清空或者掉线可以把当前编号重新锁定
redisTemplate.opsForValue().set(cacheKey, System.currentTimeMillis(), CacheTimeout, TimeUnit.SECONDS);
};
@PreDestroy
private void onDestroy(){
//正常关闭时删除当前生成器编号
if(redisTemplate != null) {
redisTemplate.delete(cacheKey);
}
}
}

View File

@@ -0,0 +1,423 @@
package com.yunzhupaas.database.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationAdvisor;
import com.baomidou.dynamic.datasource.enums.DdConstants;
import com.baomidou.dynamic.datasource.processor.DsProcessor;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.github.pagehelper.PageInterceptor;
import com.yunzhupaas.base.entity.SuperBaseEntity;
import com.yunzhupaas.config.ApplicationStartErrorCheck;
import com.yunzhupaas.config.ConfigValueUtil;
import com.yunzhupaas.database.model.entity.DbLinkEntity;
import com.yunzhupaas.database.plugins.*;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.source.impl.DbOracle;
import com.yunzhupaas.database.util.ConnUtil;
import com.yunzhupaas.database.util.DataSourceUtil;
import com.yunzhupaas.database.util.DbTypeUtil;
import com.yunzhupaas.database.util.DynamicDataSourceUtil;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.ClassUtil;
import com.yunzhupaas.util.TenantHolder;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.StringValue;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.*;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import javax.sql.DataSource;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.*;
/**
* MybatisPlus配置类
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/16 8:53
*/
@Slf4j
@Configuration
@ComponentScan("com.yunzhupaas")
@DependsOn({ "tenantDataSourceUtil", "threadPoolExecutorUtil" })
@MapperScan(basePackages = { "com.yunzhupaas.*.mapper", "com.yunzhupaas.mapper", "com.xxl.job.admin.dao" })
public class MybatisPlusConfig {
/**
* 对接数据库的实体层
*/
static final String ALIASES_PACKAGE = "com.yunzhupaas.*.entity;com.xxl.job.admin.core.model";
@Autowired
private DataSourceUtil dataSourceUtil;
@Autowired
private ConfigValueUtil configValueUtil;
@Primary
@Bean(name = "dataSourceSystem")
public DataSource dataSourceOne(DynamicDataSourceProperties properties, List<DynamicDataSourceProvider> providers)
throws SQLException, IOException, URISyntaxException {
DataSource dataSource = dynamicDataSource(properties, providers);
initDynamicDataSource(dataSource, properties);
return dataSource;
}
@Bean(name = "sqlSessionFactorySystem")
public SqlSessionFactory sqlSessionFactoryOne(@Qualifier("dataSourceSystem") DataSource dataSource,
@Autowired(required = false) ISqlInjector sqlInjector) throws Exception {
return createSqlSessionFactory(dataSource, sqlInjector);
}
/**
* 服务中查询其他服务的表数据, 未引用Mapper无法初始化MybatisPlus的TableInfo对象, 无法判断逻辑删除情况,
* 初始化MybatisPlus所有Entity对象
* 微服务的情况才进行扫描
*
* @param sqlSessionFactory
* @return
*/
@Bean
@ConditionalOnClass(name = "org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient")
public Object scanAllEntity(SqlSessionFactory sqlSessionFactory) {
ApplicationStartErrorCheck.getApplicationInitThreadPool().execute(() -> {
Set<Class<?>> classes = ClassUtil.scanCandidateComponents("com.yunzhupaas",
c -> !Modifier.isAbstract(c.getModifiers())
&& SuperBaseEntity.SuperTBaseEntity.class.isAssignableFrom(c));
for (Class<?> aClass : classes) {
MapperBuilderAssistant builderAssistant = new MapperBuilderAssistant(
sqlSessionFactory.getConfiguration(), "resource");
builderAssistant.setCurrentNamespace(aClass.getName());
TableInfoHelper.initTableInfo(builderAssistant, aClass);
}
});
return null;
}
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
try {
// 判断是否多租户
if (configValueUtil.isMultiTenancy()) {
interceptor.addInnerInterceptor(myTenantLineInnerInterceptor());
interceptor.addInnerInterceptor(mySchemaInnerInterceptor());
}
// 开启逻辑删除插件功能
if (configValueUtil.isEnableLogicDelete()) {
interceptor.addInnerInterceptor(myLogicDeleteInnerInterceptor());
}
// 新版本分页必须指定数据库,否则分页不生效
// 不指定会动态生效 多数据源不能指定数据库类型
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
// 乐观锁
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
} catch (Exception e) {
e.printStackTrace();
}
return interceptor;
}
@Bean("myLogicDeleteInnerInterceptor")
@ConditionalOnProperty(prefix = "config", name = "EnableLogicDelete", havingValue = "true")
public MyLogicDeleteInnerInterceptor myLogicDeleteInnerInterceptor() {
MyLogicDeleteInnerInterceptor myLogicDeleteInnerInterceptor = new MyLogicDeleteInnerInterceptor();
myLogicDeleteInnerInterceptor.setLogicDeleteHandler(new LogicDeleteHandler() {
@Override
public Expression getNotDeletedValue() {
return new NullValue();
}
@Override
public String getLogicDeleteColumn() {
return configValueUtil.getLogicDeleteColumn();
}
});
return myLogicDeleteInnerInterceptor;
}
@Bean("myTenantLineInnerInterceptor")
@ConditionalOnProperty(prefix = "config", name = "MultiTenancy", havingValue = "true")
public TenantLineInnerInterceptor myTenantLineInnerInterceptor() {
TenantLineInnerInterceptor tenantLineInnerInterceptor = new MyTenantLineInnerInterceptor();
tenantLineInnerInterceptor.setTenantLineHandler(new TenantLineHandler() {
@Override
public Expression getTenantId() {
return new StringValue(TenantHolder.getDatasourceName());
}
@Override
public String getTenantIdColumn() {
return configValueUtil.getMultiTenantColumn();
}
@Override
public boolean ignoreTable(String tableName) {
return configValueUtil.getMultiTenantIgnoreTable().contains(tableName.toLowerCase());
}
});
return tenantLineInnerInterceptor;
}
@Bean("mySchemaInnerInterceptor")
@ConditionalOnProperty(prefix = "config", name = "MultiTenancy", havingValue = "true")
public DynamicTableNameInnerInterceptor mySchemaInnerInterceptor() throws Exception {
DbLinkEntity dbLinkEntity = dataSourceUtil.init();
DbBase dbBase = DbTypeUtil.getDb(dbLinkEntity);
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new MySchemaInnerInterceptor();
HashMap<String, TableNameHandler> map = new HashMap<>(150);
// null空库保护
List<String> tableNames = new ArrayList<>();
// JdbcUtil.queryCustomMods(SqlComEnum.TABLES.getPrepSqlDto(dbLinkEntity, null),
// DbTableFieldModel.class)
// .forEach(dbTableModel->
// tableNames.add(dbTableModel.getTable().toLowerCase()));
// 将当前连接库的所有表保存, 在列表中的表才进行切库, 所有表名转小写, 后续比对转小写
DbBase.dynamicAllTableName = tableNames;
dynamicTableNameInnerInterceptor.setTableNameHandler(dbBase.getDynamicTableNameHandler());
return dynamicTableNameInnerInterceptor;
}
@Bean("myTenantMasterSlaveInterceptor")
@ConditionalOnProperty(prefix = "config", name = "MultiTenancy", havingValue = "true")
public MyTenantMasterSlaveAutoRoutingPlugin myTenantMasterSlaveAutoRoutingPlugin(DataSource dataSource) {
return new MyTenantMasterSlaveAutoRoutingPlugin(dataSource);
}
public MyDefaultMasterSlaveAutoRoutingPlugin myDefaultMasterSlaveAutoRoutingPlugin(DataSource dataSource) {
return new MyDefaultMasterSlaveAutoRoutingPlugin(dataSource);
}
protected DataSource dynamicDataSource(DynamicDataSourceProperties properties,
List<DynamicDataSourceProvider> providers) {
// 动态路由数据源(关键)
DynamicRoutingDataSource dataSource = new MyDynamicRoutingDataSource(providers);
dataSource.setPrimary(properties.getPrimary());
dataSource.setStrict(properties.getStrict());
dataSource.setStrategy(properties.getStrategy());
dataSource.setP6spy(properties.getP6spy());
dataSource.setSeata(properties.getSeata());
// 创建失败不等待
// properties.getDruid().setBreakAfterAcquireFailure(false);
// properties.getDruid().setMaxWait(1000);
return dataSource;
}
private void initDynamicDataSource(@Qualifier("dataSourceSystem") DataSource dataSource1,
DynamicDataSourceProperties properties)
throws DataException, SQLException, IOException, URISyntaxException {
DynamicRoutingDataSource dataSource = (DynamicRoutingDataSource) dataSource1;
// 若未配置多数据源, 从主配置复制数据库配置填充多数据源
boolean isPresentPrimary = properties.getDatasource().entrySet().stream()
.anyMatch(ds -> ds.getKey().equals(properties.getPrimary())
|| ds.getKey().startsWith(properties.getPrimary() + "_")
|| properties.getPrimary().equals(ds.getValue().getPoolName()));
if (!isPresentPrimary) {
// null多租户空库保护
DynamicDataSourceUtil.dynamicDataSourceProperties = properties;
String url = ConnUtil.getUrl(dataSourceUtil,
configValueUtil.isMultiTenancy() ? null : dataSourceUtil.getDbName());
DataSourceProperty dataSourceProperty = DynamicDataSourceUtil.createDataSourceProperty(dataSourceUtil, url);
dataSourceProperty.getDruid().setBreakAfterAcquireFailure(false);
dataSourceProperty.setLazy(false);
properties.getDatasource().put(properties.getPrimary(), dataSourceProperty);
}
}
@Bean
public Advisor myDynamicDatasourceGeneratorAdvisor(DsProcessor dsProcessor) {
DynamicGeneratorInterceptor interceptor = new DynamicGeneratorInterceptor(true, dsProcessor);
return new DynamicDataSourceAnnotationAdvisor(interceptor, DS.class) {
private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
{
pointcut.setExpression(
"within(com.yunzhupaas.database.plugins.DynamicSourceGeneratorInterface+) && @target(com.baomidou.dynamic.datasource.annotation.DS)");
}
@Override
public Pointcut getPointcut() {
return pointcut;
}
};
}
protected DataSource druidDataSource() throws Exception {
DbBase dbBase = DbTypeUtil.getDb(dataSourceUtil);
String userName = dataSourceUtil.getUserName();
String password = dataSourceUtil.getPassword();
String driver = dbBase.getDriver();
String url = "";
if (configValueUtil.isMultiTenancy()) {
url = ConnUtil.getUrl(dataSourceUtil, null);
} else {
url = ConnUtil.getUrl(dataSourceUtil);
}
DruidDataSource dataSource = new DruidDataSource();
if (dbBase.getClass() == DbOracle.class) {
// Oracle特殊创建数据源方式
// String logonUer = "Default";
String logonUer = "SYSDBA";
// String logonUer = "SYSOPER";
Properties properties = DbOracle.setConnProp(logonUer, userName, password);
dataSource.setConnectProperties(properties);
} else {
dataSource.setUsername(userName);
dataSource.setPassword(password);
}
dataSource.setUrl(url);
dataSource.setDriverClassName(driver);
return dataSource;
}
public Resource[] resolveMapperLocations() {
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<String> mapperLocations = new ArrayList<>();
mapperLocations.add("classpath*:mapper/*.xml");
mapperLocations.add("classpath*:mapper/*/*.xml");
mapperLocations.add("classpath*:mapper/*/*/*.xml");
mapperLocations.add("classpath*:mybatis-mapper/*.xml");
List<Resource> resources = new ArrayList<Resource>();
for (String mapperLocation : mapperLocations) {
try {
Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
} catch (IOException e) {
// ignore
}
}
return resources.toArray(new Resource[0]);
}
public SqlSessionFactory createSqlSessionFactory(DataSource dataSource, ISqlInjector sqlInjector) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(dataSource);
// 全局配置
GlobalConfig globalConfig = new GlobalConfig();
// 配置填充器
globalConfig.setMetaObjectHandler(new MybatisPlusMetaObjectHandler());
bean.setGlobalConfig(globalConfig);
if (configValueUtil.isEnableLogicDelete()) {
globalConfig.setDbConfig(new GlobalConfig.DbConfig());
globalConfig.getDbConfig().setLogicDeleteField("deleteMark");
globalConfig.getDbConfig().setLogicDeleteValue("1");
globalConfig.getDbConfig().setLogicNotDeleteValue(StringPool.NULL);
}
sqlInjector = new MyDefaultSqlInjector(sqlInjector, configValueUtil);
globalConfig.setSqlInjector(sqlInjector);
List<Interceptor> mybatisPlugins = new ArrayList<>();
mybatisPlugins.add(new ResultSetInterceptor());
mybatisPlugins.add(new MyDynamicDataSourceAutoRollbackInterceptor());
mybatisPlugins.add(pageHelper());
if (configValueUtil.isMultiTenancy()) {
mybatisPlugins.add(myTenantMasterSlaveAutoRoutingPlugin(dataSource));
}
// 配置从库添加读写分离插件
if (DynamicDataSourceUtil.dynamicDataSourceProperties.getDatasource().keySet().stream()
.anyMatch(k -> k.startsWith(DdConstants.SLAVE))) {
mybatisPlugins.add(myDefaultMasterSlaveAutoRoutingPlugin(dataSource));
}
bean.setVfs(SpringBootVFS.class);
bean.setTypeAliasesPackage(ALIASES_PACKAGE);
bean.setMapperLocations(resolveMapperLocations());
bean.setConfiguration(configuration(dataSource));
bean.setPlugins(mybatisPlugins.toArray(new Interceptor[mybatisPlugins.size()]));
return bean.getObject();
}
public PageInterceptor pageHelper() {
PageInterceptor pageHelper = new PageInterceptor();
// 配置PageHelper参数
Properties properties = new Properties();
properties.setProperty("dialectAlias", "kingbase8=com.github.pagehelper.dialect.helper.MySqlDialect");
properties.setProperty("autoRuntimeDialect", "true");
properties.setProperty("offsetAsPageNum", "false");
properties.setProperty("rowBoundsWithCount", "false");
properties.setProperty("pageSizeYunzhupaas", "true");
properties.setProperty("reasonable", "false");
properties.setProperty("supportMethodsArguments", "false");
properties.setProperty("returnPageInfo", "none");
pageHelper.setProperties(properties);
return pageHelper;
}
public MybatisConfiguration configuration(DataSource dataSource) {
MybatisConfiguration mybatisConfiguration = new MybatisConfiguration() {
@Override
public void addMappedStatement(MappedStatement ms) {
// 避免Mybatis多线程初始化问题
synchronized (ALIASES_PACKAGE) {
super.addMappedStatement(ms);
}
}
};
mybatisConfiguration.setMapUnderscoreToCamelCase(false);
mybatisConfiguration.setCacheEnabled(false);
mybatisConfiguration.setCallSettersOnNulls(true);
mybatisConfiguration.addInterceptor(mybatisPlusInterceptor());
mybatisConfiguration.setLogImpl(Slf4jImpl.class);
mybatisConfiguration.setJdbcTypeForNull(JdbcType.NULL);
return mybatisConfiguration;
}
@Bean
public IKeyGenerator keyGenerator() {
return new H2KeyGenerator();
}
/**
* 数据权限插件
*
* @return DataScopeInterceptor
*/
// @Bean
// @ConditionalOnMissingBean
// public DataScopeInterceptor dataScopeInterceptor(DataSource dataSource) {
// return new DataScopeInterceptor(dataSource);
// }
}

View File

@@ -0,0 +1,67 @@
package com.yunzhupaas.database.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.yunzhupaas.constant.GlobalConst;
import com.yunzhupaas.database.util.TenantDataSourceUtil;
import com.yunzhupaas.util.DateUtil;
import com.yunzhupaas.util.UserProvider;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2024年12月22日 下午20:14
*/
@Component
public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
String userId = UserProvider.getLoginUserId();
Object enabledMark = this.getFieldValByName("enabledMark", metaObject);
Object creatorUserId = this.getFieldValByName("creatorUserId", metaObject);
Object creatorTime = this.getFieldValByName("creatorTime", metaObject);
Object creatorUser = this.getFieldValByName("creatorUser", metaObject);
if (enabledMark == null) {
this.strictInsertFill(metaObject, "enabledMark", () -> 1, Integer.class);
}
if (creatorUserId == null) {
this.strictInsertFill(metaObject, "creatorUserId", () -> userId, String.class);
}
if (creatorTime == null) {
this.strictInsertFill(metaObject, "creatorTime", DateUtil::getNowDate, Date.class);
}
if (creatorUser == null) {
this.strictInsertFill(metaObject, "creatorUser", () -> userId, String.class);
}
String tenantColumn = TenantDataSourceUtil.getTenantColumn();
if (GlobalConst.DEFAULT_TENANT_VALUE.equals(tenantColumn)) {
this.strictInsertFill(metaObject, "tenantId", () -> tenantColumn, String.class);
} else {
this.setFieldValByName("tenantId", TenantDataSourceUtil.getTenantColumn(), metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
String userId = UserProvider.getLoginUserId();
this.strictUpdateFill(metaObject, "lastModifyTime", DateUtil::getNowDate, Date.class);
this.strictUpdateFill(metaObject, "lastModifyUserId", () -> userId, String.class);
this.strictUpdateFill(metaObject, "lastModifyUser", () -> userId, String.class);
String tenantColumn = TenantDataSourceUtil.getTenantColumn();
if (GlobalConst.DEFAULT_TENANT_VALUE.equals(tenantColumn)) {
this.strictUpdateFill(metaObject, "tenantId", () -> tenantColumn, String.class);
} else {
this.setFieldValByName("tenantId", TenantDataSourceUtil.getTenantColumn(), metaObject);
}
}
}

View File

@@ -0,0 +1,91 @@
package com.yunzhupaas.database.constant;
import com.google.common.collect.ImmutableMap;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.exception.DataException;
import lombok.AllArgsConstructor;
import java.util.Map;
import java.util.Optional;
/**
* 字段别名特殊标识
*
* @author 云筑产品开发平台组
* @version v3.4.6
* @copyrignt 深圳市乐程软件有限公司
* @date 2023-02-11
*/
public class DbAliasConst {
/**
* 允空
*/
public static final String NULL = "NULL";
/**
* 非空
*/
public static final String NOT_NULL = "NOT NULL";
/**
* 允空
* 0:空值 NULL、1:非空值 NOT NULL
*/
public static final NumFieldAttr<String> ALLOW_NULL = new NumFieldAttr<>(ImmutableMap.of(
1, NULL,
0, NOT_NULL,
-1, NOT_NULL
));
/**
* 主键
* 0:非主键、1主键
*/
public static final NumFieldAttr<Boolean> PRIMARY_KEY = new NumFieldAttr<>(ImmutableMap.of(
1, true,
0, false,
-1, false
));
public static final NumFieldAttr<Boolean> AUTO_INCREMENT = new NumFieldAttr<>(ImmutableMap.of(
1, true,
0, false,
-1, false
));
/**
* 数值对应字段属性
* @param <T>
*/
@AllArgsConstructor
public static class NumFieldAttr<T>{
private Map<Integer, T> config;
/**
* 获取标识
*/
public T getSign(Integer i) {
return config.get(i == null ? -1 : i);
}
/**
* 获取数值
*/
public Integer getNum(T sign) throws DataException {
if(sign == null){
return 0;
}
Optional<Map.Entry<Integer, T>> first = config.entrySet().stream().filter(map -> map.getValue().equals(sign)).findFirst();
if(first.isPresent()){
return first.get().getKey();
}else {
throw new DataException(MsgCode.DB012.get());
}
}
}
}

View File

@@ -0,0 +1,79 @@
package com.yunzhupaas.database.constant;
/**
* 数据库相关静态常量
*
* @author 云筑产品开发平台组 YY
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/06
*/
public class DbConst {
/**
* jdbc工具类返回数据类型
*/
public static final String TABLE_FIELD_MOD = "tableFieldMod";
public static final String MAP_MOD = "mapMods";
public static final String INCLUDE_FIELD_MOD = "includeFieldMods";
public static final String CUSTOM_MOD = "customMods";
public static final String PAGE_MOD = "pageMod";
/**
* url连接
*/
public static final String HOST = "{host}";
public static final String PORT = "{port}";
public static final String DB_NAME = "{dbname}";
public static final String DB_SCHEMA = "{schema}";
/**
* 默认表(不可删)
*
*/
public static final String BYO_TABLE =
"base_advanced_query_scheme,base_app_data,base_authorize,base_bill_rule,base_columns_purview,base_common_fields," +
"base_common_words,base_data_interface,base_data_interface_log,base_data_interface_oauth,base_data_interface_variate," +
"base_db_link,base_dictionary_data,base_dictionary_type,base_file,base_group,base_im_content,base_im_reply," +
"base_integrate,base_integrate_node,base_integrate_queue,base_integrate_task,base_message,base_module," +
"base_module_authorize,base_module_button,base_module_column,base_module_form,base_module_link," +
"base_module_scheme,base_msg_account,base_msg_monitor,base_msg_send,base_msg_send_template," +
"base_msg_short_link,base_msg_sms_field,base_msg_template,base_msg_template_param,base_msg_wechat_user," +
"base_notice,base_organize,base_organize_administrator,base_organize_relation,base_permission_group," +
"base_portal,base_portal_data,base_portal_manage,base_position,base_print_log,base_print_template," +
"base_province,base_province_atlas,base_role,base_schedule,base_schedule_log,base_schedule_user,base_sign_img," +
"base_socials_users,base_syn_third_info,base_sys_config,base_sys_log,base_system,base_time_task," +
"base_time_task_log,base_user,base_user_device,base_user_old_password,base_user_relation,base_visual_dev," +
"base_visual_dev_copy1,base_visual_filter,base_visual_link,base_visual_release,base_visual_release_copy1," +
"blade_visual,blade_visual_category,blade_visual_component,blade_visual_config,blade_visual_db,blade_visual_map," +
"blade_visual_record,ct293714178055641925,ct294012196562705414,ct294022926200511493,ct294031961024928774," +
"ct294031961024928775,ct294037561750363142,ct294037561750363143,ct294099893327272966,ct294376098702073542," +
"ct294382866144468678,ct395899726056134917,ct459734202267475653,ct469496947162544645,ct469499339585157637," +
"data_report,ext_big_data,ext_customer,ext_document,ext_document_share,ext_email_config,ext_email_receive," +
"ext_email_send,ext_employee,ext_order,ext_order_2,ext_order_entry,ext_order_entry_2,ext_order_receivable," +
"ext_order_receivable_2,ext_product,ext_product_classify,ext_product_entry,ext_product_goods,ext_project_gantt," +
"ext_table_example,ext_worklog,ext_worklog_share,flow_candidates,flow_comment,flow_delegate,flow_form,flow_form_copy1," +
"flow_form_relation,flow_launch_user,flow_reject_data,flow_task,flow_task_circulate,flow_task_node,flow_task_operator," +
"flow_task_operator_record,flow_task_operator_user,flow_template,flow_template_json,flow_visible,mt293714178051447621," +
"mt293732572561709893,mt293737725377420101,mt293740367726025541,mt293756710756064069,mt294012196562705413," +
"mt294022926196317189,mt294027801932110853,mt294031961024928773,mt294037561750363141,mt294090217118276613," +
"mt294099237023526085,mt294099893327272965,mt294104577349819397,mt294376098702073541,mt294382866144468677," +
"mt382811547782648325,mt385453315686752389,mt395179351563312389,mt395899725691230469,mt395964134161651973," +
"mt400655094485373381,mt420589912199274117,mt456990191458975685,mt469496947087047173,mt469499339534825989," +
"mt469502670336489989,mt470888132380721605,mt470913062111543749,mt470929966582727173,report_charts,report_department," +
"report_user,test_carapplication,test_cost,test_customer,test_details,test_position,test_projects,test_purchase," +
"test_purchase_form,test_purchase_form_order,test_purchaseorder,test_receivable,test_reimbursement,test_subpackage," +
"test_vehicleinfo,test_warehousing,test_warehousingorder,undo_log,wform_applybanquet,wform_applydelivergoods," +
"wform_applydelivergoodsentry,wform_applymeeting,wform_archivalborrow,wform_articleswarehous,wform_batchpack," +
"wform_batchtable,wform_conbilling,wform_contractapproval,wform_contractapprovalsheet,wform_debitbill," +
"wform_documentapproval,wform_documentsigning,wform_expenseexpenditure,wform_finishedproduct,wform_finishedproductentry," +
"wform_incomerecognition,wform_leaveapply,wform_letterservice,wform_materialrequisition,wform_materialrequisitionentry," +
"wform_monthlyreport,wform_officesupplies,wform_outboundorder,wform_outboundorderentry,wform_outgoingapply," +
"wform_paydistribution,wform_paymentapply,wform_postbatchtab,wform_procurementmaterial,wform_procurementmaterialentry," +
"wform_purchaselist,wform_purchaselistentry,wform_quotationapproval,wform_receiptprocessing,wform_receiptsign," +
"wform_rewardpunishment,wform_salesorder,wform_salesorderentry,wform_salessupport,wform_staffovertime," +
"wform_supplementcard,wform_travelapply,wform_travelreimbursement,wform_vehicleapply,wform_violationhandling," +
"wform_warehousereceipt,wform_warehousereceiptentry,wform_workcontactsheet,wform_zjf_wikxqi";
}

View File

@@ -0,0 +1,35 @@
package com.yunzhupaas.database.constant;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-17
*/
public class DbFieldConst {
/**
* 允空
*/
public static final String NULL = "NULL";
/**
* 非空
*/
public static final String NOT_NULL = "NOT NULL";
/**
* 主键
*/
public static final Boolean IS_PRIMARY_KEY = true;
/**
* 非主键
*/
public static final Boolean NOT_PRIMARY_KEY = false;
}

View File

@@ -0,0 +1,104 @@
package com.yunzhupaas.database.constant;
/**
* 打印模板-结果集字段Key
*
* @author 云筑产品开发平台组 YY
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024-09-30
*/
public interface RsColumnKeyConst {
/**
* 表类别
*/
String TABLE_CAT = "TABLE_CAT";
/**
* 表模式
*/
String TABLE_SCHEM = "TABLE_SCHEM";
/**
* 表名称
*/
String TABLE_NAME = "TABLE_NAME";
/**
* 列名称
*/
String COLUMN_NAME = "COLUMN_NAME";
/**
* 来自 java.sql.Types 的 SQL 类型
*/
String DATA_TYPE = "DATA_TYPE";
/**
* 数据源依赖的类型名称,对于 UDT该类型名称是完全限定的
*/
String TYPE_NAME = "TYPE_NAME";
/**
* 列的大小
* charLength(字符串长度)
*/
String COLUMN_SIZE = "COLUMN_SIZE";
/**
* 基数(通常为 10 或 2
* Precision精度
*/
String NUM_PREC_RADIX = "NUM_PREC_RADIX";
/**
* 小数部分的位数。对于 DECIMAL_DIGITS 不适用的数据类型,则返回 Null
* Scale标度
*/
String DECIMAL_DIGITS = "DECIMAL_DIGITS";
/**
* 是否允许使用 NULL。 columnNoNulls - 可能不允许使用NULL值 columnNullable - 明确允许使用NULL值 columnNullableUnknown - 不知道是否可使用 null
*/
String NULLABLE = "NULLABLE";
/**
* 描述列的注释可为null
*/
String REMARKS = "REMARKS";
/**
* 该列的默认值当值在单引号内时应被解释为一个字符串可为null
*/
String COLUMN_DEF = "COLUMN_DEF";
/**
* 未使用
*/
String SQL_DATA_TYPE = "SQL_DATA_TYPE";
/**
* 未使用
*/
String SQL_DATETIME_SUB = "SQL_DATETIME_SUB";
/**
* 对于 char 类型,该长度是列中的最大字节数
*/
String CHAR_OCTET_LENGTH = "CHAR_OCTET_LENGTH";
/**
* 表中的列的索引(从 1 开始)
*/
String ORDINAL_POSITION = "ORDINAL_POSITION";
/**
* 是否允许使用 NULL columnNoNulls - 可能不允许使用NULL值 columnNullable - 明确允许使用NULL值 columnNullableUnknown - 不知道是否可使用 null
*/
String IS_NULLABLE = "IS_NULLABLE";
/**
* 表的类别,它是引用属性的作用域(如果 DATA_TYPE 不是 REF则为null
*/
String SCOPE_CATLOG = "SCOPE_CATLOG";
/**
* 表的模式,它是引用属性的作用域(如果 DATA_TYPE 不是 REF则为null
*/
String SCOPE_SCHEMA = "SCOPE_SCHEMA";
/**
* 表名称,它是引用属性的作用域(如果 DATA_TYPE 不是 REF则为null
*/
String SCOPE_TABLE = "SCOPE_TABLE";
/**
* 不同类型或用户生成 Ref 类型、来自 java.sql.Types 的 SQL 类型的源类型(如果 DATA_TYPE 不是 DISTINCT 或用户生成的 REF则为null
*/
String SOURCE_DATA_TYPE = "SOURCE_DATA_TYPE";
/**
* 指示此列是否自动增加YES --- 如果该列自动增加 NO --- 如果该列不自动增加, 空字符串 --- 如果不能确定该列是否是自动增加参数
*/
String IS_AUTOINCREMENT = "IS_AUTOINCREMENT";
}

View File

@@ -0,0 +1,15 @@
package com.yunzhupaas.database.constant;
public interface RsTableKeyConst {
/**
* 表名
*/
String TABLE_NAME = "TABLE_NAME";
String TABLE_TYPE = "TABLE_TYPE";
String REMARKS = "REMARKS";
}

View File

@@ -0,0 +1,94 @@
package com.yunzhupaas.database.datatype.db;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 达梦数据类型
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/25
*/
@Getter
@AllArgsConstructor
public enum DtDMEnum implements DtInterface {
/*============================ 整型 ===========================*/
TINY_INT ("TINYINT", new IntegerLimit()),
SMALL_INT ("SMALLINT", new IntegerLimit()),
/**
* 默认长度10
*/
INT ("INT", new IntegerLimit()),
/**
* 默认长度19
*/
BIGINT ("BIGINT", new IntegerLimit()),
/*============================ 文本字符串类型 ===========================*/
CHAR ("CHAR", new StringLimit(true).charLength(32767L, 150L)),
/**
* 字节长度32767汉字:3字节特殊字符:3字节
* 达梦自带迁移使用的是 (MySQL varchar) -> VARCHAR
*/
VARCHAR ("VARCHAR", new StringLimit(true).bitLength(32767L, 150L)),
VARCHAR2 ("VARCHAR2", new StringLimit(true).bitLength(32767L, 150L)),
/**
* 默认长度2147483647
*/
TEXT ("TEXT", new StringLimit().fixedCharLength(2147483647L)),
/**
* 默认长度2147483647
*/
CLOB ("CLOB", new StringLimit().fixedCharLength(2147483647L)),
BLOB ("BLOB", new StringLimit()),
/*============================ 时间格式 ===========================*/
DATE ("DATE", new DateTimeLimit()),
/**
* 默认长度36默认精度6
* Mysql datetime转达梦 TIMESTAMP,手动改成DATETIME数据会报错
* 利用 PostGreSQL进行迁移
*/
DATE_TIME ("DATETIME", new DateTimeLimit()),
/**
* 默认长度36默认精度6
* 默认工具mysqlTimestamp--> DmDateTime
*/
TIME_STAMP ("TIMESTAMP", new DateTimeLimit()),
/**
* 默认长度22默认精度6
*/
TIME ("TIME", new DateTimeLimit()),
/**
* 默认长度13
*/
/*============================ 定点型 ===========================*/
DECIMAL ("DECIMAL", new DecimalLimit(true)
.precision(38, 18).scale(38, 6, 3)),
DEC ("DEC", new DecimalLimit(true)
.precision(38, 18).scale(38, 6, 3)),
/*============================浮点===========================*/
/**
* 显示real
*/
FLOAT ("FLOAT", new FloatLimit(true).precision(24, 18).scale(30, 3)),
DOUBLE ("DOUBLE", new FloatLimit(true).precision(53, 18).scale(30, 3)),
;
/**
* 数据库字段类型
*/
private final String dataType;
/**
* 长度、精度、标度规则模型
*/
private final DtLimitBase dtLimit;
}

View File

@@ -0,0 +1,95 @@
package com.yunzhupaas.database.datatype.db;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version v3.4.5
* @copyrignt 深圳市乐程软件有限公司
* @date 2024-12-23
*/
@Getter
@AllArgsConstructor
public enum DtDorisEnum implements DtInterface {
/* =============================== 整数类型: TINYINT、SMALLINT、MEDIUMINT、INT(INTEGER)、BIGINT =============================== */
/* ============== 支持TINYINT、INT、BIGINT ============= */
/**
* 短整型
* 带符号:-128 ~ 127
* 无符号255
*/
TINY_INT ("tinyint", new IntegerLimit().fixedPrecision(3)),
/**
* 与TINYINT一样0代表false1代表true
*/
BOOLEAN ("boolean", new IntegerLimit().fixedPrecision(null)),
/**
* 字节有符号整数,范围:[-32768, 32767]
*/
SMALL_INT ("smallint", new IntegerLimit().fixedPrecision(5)),
/**
* 整型
* -2147483648 ~ 2147483647
*/
INT ("int", new IntegerLimit().fixedPrecision(10)),
/**
* 长整型
* -9223372036854775808 ~ 9223372036854775807
*/
BIGINT ("bigint", new IntegerLimit().fixedPrecision(19)),
LARGE_INT ("largeint", new IntegerLimit().fixedPrecision(null)),
/* =============================== 文本字符串类型: =============================== */
/**
* 定长字符串M代表的是定长字符串的长度。M的范围是1-255
*/
CHAR ("char", new StringLimit(true).charLength(255L,50L)),
/**
* 变长字符串M代表的是变长字符串的字节长度。M的范围是1-65533
* 变长字符串是以UTF-8编码存储的因此英文字符占1个字节中文字符占3个字节
*/
VARCHAR ("varchar", new StringLimit(true).charLength(16170L, 50L)),
/**
* 变长字符串最大支持2147483643字节(2GB-4)。String类型的长度还受BE配置参数 string_type_soft_limit的影响, 实际能存储的最大长度取两者最小值
* String类型只能用在value列不能用在key列和分区分桶列
* 变长字符串是以UTF-8编码存储的因此英文字符占1个字节中文字符占3个字节
*/
STRING ("string", new StringLimit()),
/* =============================== 浮点类型: =============================== */
FLOAT ("float", new FloatLimit(true).precision(35, 18).scale(30, 3)),
DOUBLE ("double", new FloatLimit(true).fixedPrecision(35).fixedScale(30)),
/* =============================== 定点数类型: =============================== */
DECIMAL ("decimal", new DecimalLimit(true).precision(27, 18).scale(30, 3)),
/* =============================== 日期时间类型: =============================== */
DATE ("date", new DateTimeLimit()),
DATE_TIME ("datetime", new DateTimeLimit()),
/* ======= 集合: ======= */
BITMAP ("BITMAP", new StringLimit()),
/* ======= 聚合类型: ======= */
/**
* HyperLogLog
* 1~16385 个字节。HLL不能作为key列使用建表时配合聚合类型为HLL_UNION。用户不需要指定长度和默认值。长度根据数据的聚合程度系统内控制
* 并且HLL列只能通过配套的hll_union_agg、hll_raw_agg、hll_cardinality、hll_hash进行查询或使用
* HLL是模糊去重在数据量大的情况性能优于Count Distinct。HLL的误差通常在1%左右有时会达到2%
*/
HLL ("HLL", new StringLimit())
;
/**
* 数据库字段类型
*/
private final String dataType;
/**
* 长度、精度、标度规则模型
*/
private final DtLimitBase dtLimit;
}

View File

@@ -0,0 +1,86 @@
package com.yunzhupaas.database.datatype.db;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 金仓数据类型
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/25
*/
@Getter
@AllArgsConstructor
public enum DtKingbaseESEnum implements DtInterface {
/*================================== 整数型 ========================================*/
TINY_INT ("tinyint", new IntegerLimit()),
SMALL_INT ("smallint", new IntegerLimit()),
/**
* 默认长度:无
*/
INTEGER ("integer", new IntegerLimit()),
/**
* 默认长度:无
*/
BIGINT ("bigint", new IntegerLimit()),
/*================================== 文本字符串类型 ========================================*/
CHAR ("character", new StringLimit(true).charLength(10485760L, 50L)),
/**
* 显示character varying
*/
VARCHAR ("varchar", new StringLimit(true).charLength(10485760L, 50L)),
/**
* 默认长度:无
*/
TEXT ("text", new StringLimit()),
/*================================== 浮点型 ========================================*/
/**
* 显示real不允许修改,与sqlserver一样
*/
FLOAT4 ("float4", new FloatLimit()),
/**
* 显示: double precision
*/
FLOAT8 ("float8", new FloatLimit()),
/*================================== 定点型 ========================================*/
/**
* 默认长度:无
*/
NUMERIC ("numeric", new DecimalLimit(true)
.precision(1000, 38).scale(1000, 38)),
/* =============================== 日期时间类型: =============================== */
/**
* 显示time without time zone
*/
TIME ("time", new DateTimeLimit()),
DATE ("date", new DateTimeLimit()),
/**
* 有些版本不支持datetime
*/
DATE_TIME ("datetime", new DateTimeLimit()),
/**
* 默认长度:无
* 显示timestamp without time zone
*/
TIMESTAMP ("timestamp(0)", new DateTimeLimit()),
BYTEA ("bytea", new StringLimit()),
;
/**
* 数据库字段类型
*/
private final String dataType;
/**
* 长度、精度、标度规则模型
*/
private final DtLimitBase dtLimit;
}

View File

@@ -0,0 +1,119 @@
package com.yunzhupaas.database.datatype.db;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* MySQL字段数据类型枚举
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/26
*/
@Getter
@AllArgsConstructor
public enum DtMySQLEnum implements DtInterface {
/* =============================== 整数类型: TINYINT、SMALLINT、MEDIUMINT、INT(INTEGER)、BIGINT =============================== */
/* ============== 支持TINYINT、INT、BIGINT ============= */
/**
* 短整型
* 带符号:-128 ~ 127
* 无符号255
*/
TINY_INT ("tinyint", new IntegerLimit().fixedPrecision(3)),
SMALL_INT ("smallint", new IntegerLimit().fixedPrecision(5)),
MEDIUM_INT ("mediumint", new IntegerLimit().fixedPrecision(7)),
/**
* 整型
* -2147483648 ~ 2147483647
*/
INT ("int", new IntegerLimit().fixedPrecision(10)),
/**
* 长整型
* -9223372036854775808 ~ 9223372036854775807
*/
BIGINT ("bigint", new IntegerLimit().fixedPrecision(19)),
/* =============================== 文本字符串类型: =============================== */
BIT ("bit", new StringLimit(true).charLength(15L, 64L)),
BLOB ("blob", new StringLimit()),
CHAR ("char", new StringLimit(true).charLength(50L,255L)),
/**
* 字符串
* 默认最大长度1617065535 bytes
* 标注:当varchar当主键的时候最长是7683072 bytes当长度过长时推荐用text
*/
VARCHAR ("varchar", new StringLimit(true).charLength(16170L, 50L)),
/**
* 文本
* 默认长度0
*/
TINY_TEXT ("tinytext", new StringLimit().fixedCharLength(225L)),
TEXT ("text", new StringLimit().fixedCharLength(65535L)),
MEDIUM_TEXT ("mediumtext", new StringLimit().fixedCharLength(16777215L)),
/**
* 长文本
* 默认长度0
* longtext支持65535字节长度utf8编码下最多支持21843个字符
*/
LONG_TEXT ("longtext", new StringLimit().fixedBitLength(4294967295L)),
/**
* 二进制大对象 longblob (lang binary large object)
*/
LONG_BLOB ("longblob", new StringLimit().fixedCharLength(0L)),
/* =============================== 浮点类型: =============================== */
/**
* float单精度4个字节,8位精度
* double双精度8个字节16位精度
* 总结double精度更高占用更大float精度更低运算更快
*/
FLOAT ("float", new FloatLimit(true).precision(255, 18).scale(30, 3)),
DOUBLE ("double", new FloatLimit(true).precision(255, 18).scale(30, 3)),
/* =============================== 定点数类型: =============================== */
DECIMAL ("decimal", new DecimalLimit(true).precision(65, 18).scale(30, 3)),
/* =============================== 日期时间类型: =============================== */
/**
* 示例14:50:42.000000 (长度6)、14:50:42.0长度1
*/
TIME ("time", new DateTimeLimit(true).scale(6, 6)),
/**
* 示例2022-06-06 14:53:12.000000长度6、2022-06-06 14:53:12.0长度1
*/
DATE_TIME ("datetime", new DateTimeLimit(true).scale(6, 6)),
/**
* 示例2022-06-06 14:56:04.000000长度6、2022-06-06 14:56:04.0长度1
*/
TIMESTAMP ("timestamp", new DateTimeLimit(true).scale(6, 6)),
/**
* 示例1992、2020、2060
*/
YEAR ("year", new DateTimeLimit(true).precision(4, 4)),
DATE ("date", new DateTimeLimit()),
/* ======= 枚举类型: ======= */
/* ======= 集合类型: ======= */
/* ======= 二进制字符串类型: ======= */
/* ======= JSON类型: ======= */
/* ======= 空间数据类型: ======= */
;
/**
* 数据库字段类型
*/
private final String dataType;
/**
* 长度、精度、标度规则模型
*/
private final DtLimitBase dtLimit;
}

View File

@@ -0,0 +1,80 @@
package com.yunzhupaas.database.datatype.db;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.DateTimeLimit;
import com.yunzhupaas.database.datatype.limit.FloatLimit;
import com.yunzhupaas.database.datatype.limit.NumberLimit;
import com.yunzhupaas.database.datatype.limit.StringLimit;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* Oracle数据类型
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/25
*/
@Getter
@AllArgsConstructor
public enum DtOracleEnum implements DtInterface {
/*================================== 整数型 ========================================*/
/**
* 长度:1---38
* 精度:-84---127
*/
NUMBER ("NUMBER", new NumberLimit(true).precision(38, 11).scale(127, -84)),
/* =============================== 文本字符串类型 =============================== */
CHAR ("CHAR", new StringLimit(true).charLength(2000L, 50L)),
NCHAR ("VARCHAR2", new StringLimit(true).charLength(2000L, 50L)),
/**
* VARCHAR2支持4000个字节4000个字母1333个汉字汉字:3个字节
* NVARCHAR2支持2000个字符2000个字母2000个汉字不管是汉字还是字母每个字符的长度都是2个字节不受数据库字符集
*/
VARCHAR2 ("VARCHAR2", new StringLimit(true).bitLength(4000L, 50L)),
NVARCHAR2 ("NVARCHAR2", new StringLimit(true).charLength(2000L, 50L)),
/**
* 默认长度4000
* TEXT与BLOB的主要差别就是BLOB保存二进制数据TEXT保存字符数据
*/
/**
* 1.BLOB
* BLOB全称为二进制大型对象Binary Large Object)。它用于存储数据库中的大型二进制对象。可存储的最大大小为4G字节
* 2.CLOB
* CLOB全称为字符大型对象Character Large Object)。它与LONG数据类型类似只不过CLOB用于存储数据库中的大型单字节字符数据块不支持宽度不等的字符集。可存储的最大大小为4G字节
* 3.NCLOB
* 基于国家语言字符集的NCLOB数据类型用于存储数据库中的固定宽度单字节或多字节字符的大型数据块不支持宽度不等的字符集。可存储的最大大小为4G字节
*/
CLOB ("CLOB", new StringLimit()),
BLOB ("BLOB", new StringLimit()),
NCLOB ("NCLOB", new StringLimit()),
/* =============================== 浮点类型 =============================== */
/**
* 除了oracle其他库浮点型都无法修改参数
*/
FLOAT ("FLOAT", new FloatLimit(true).precision(126, 18).scale(126, 3)),
/* =============================== 日期时间类型: =============================== */
/**
* 默认长度7
*/
DATE ("DATE", new DateTimeLimit()),
TIMESTAMP ("TIMESTAMP", new DateTimeLimit()),
;
/**
* 数据库字段类型
*/
private final String dataType;
/**
* 长度、精度、标度规则模型
*/
private final DtLimitBase dtLimit;
}

View File

@@ -0,0 +1,75 @@
package com.yunzhupaas.database.datatype.db;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* PostgreSQL数据类型
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/25
*/
@Getter
@AllArgsConstructor
public enum DtPostgreSQLEnum implements DtInterface {
/*================================== 整数型 ========================================*/
/**
* 类型名称: smallint
*/
INT2 ("int2", new IntegerLimit()),
/**
* 类型名称: integer
* 默认长度32
*/
INT4 ("int4", new IntegerLimit()),
/**
* 类型名称: bigint
* 默认长度64
*/
INT8 ("int8", new IntegerLimit()),
/*================================== 文本字符串类型 ========================================*/
CHAR ("char", new StringLimit(true).charLength(10485760L, 50L)),
VARCHAR ("varchar", new StringLimit(true).charLength(10485760L, 50L)),
/**
* 默认长度:无
*/
TEXT ("text", new StringLimit()),
/*================================== 浮点型 ========================================*/
FLOAT4 ("float4", new FloatLimit(true).precision(24, 18).scale(18, 3)),
/**
* 类型名称: double
*/
FLOAT8 ("float8", new FloatLimit(true).precision(53, 18).scale(18, 3)),
/*================================== 定点型 ========================================*/
NUMERIC ("numeric", new DecimalLimit(true).precision(1000, 18).scale(100, 3)),
/*================================== 时间日期 ========================================*/
TIME ("time", new DateTimeLimit()),
DATE ("date", new DateTimeLimit()),
/**
* 默认长度6
*/
TIMESTAMP ("timestamp", new DateTimeLimit()),
BYTEA ("bytea", new StringLimit()),
;
/**
* 数据库字段类型
*/
private final String dataType;
/**
* 长度、精度、标度规则模型
*/
private final DtLimitBase dtLimit;
}

View File

@@ -0,0 +1,99 @@
package com.yunzhupaas.database.datatype.db;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* SQLServer数据类型
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/25
*/
@Getter
@AllArgsConstructor
public enum DtSQLServerEnum implements DtInterface {
/* =============================== 整数类型 =============================== */
TINY_INT ("tinyint", new IntegerLimit()),
SMALL_INT ("smallint", new IntegerLimit()),
/**
* 默认长度:无
*/
INT ("int", new IntegerLimit()),
/**
* 默认长度:无
*/
BIGINT ("bigint", new IntegerLimit()),
/* =============================== 文本字符串类型 =============================== */
CHAR ("char", new StringLimit(true).charLength(8000L, 50L)),
/**
* N 代表Unicode可变长度类型
* NVARCHAR 字符存储VARCHAR 字节存储
* 推荐使用nvarchar 虽然varchar比nvarchar省空间但空间相对来说已经不是奢侈的了而且带来的问题也很严重
* 因为varchar是非Unicode所以系统读取数据都会进行一次Unicode转码nvarchar不会转码这是其一其二如果操作系统是英文操作系统
* 那么用varchar存储的汉字会出现乱码的情况varchar是单字节存储nvarchar是双字节存储
*/
NVARCHAR ("nvarchar", new StringLimit(true).charLength(8000L, 50L)),
VARCHAR ("varchar", new StringLimit(true).charLength(4000L, 50L)),
/* Text 和 Image 是可能被 SQServer 以后的版本淘汰的数据类型
varchar(max)-------text;
nvarchar(max)-----ntext;
varbinary(max)----p_w_picpath.
nvarchar长度会显示-1
查询出来只能显示nvarchar长度-1的时候代表nvarchar(max)项目中转换成text */
/**
* 默认长度4005
*/
VARCHAR_MAX ("nvarchar(max)",new StringLimit().fixedCharLength(4005L)),
VARBINARY ("varbinary(max)", new StringLimit()),
/**
* 默认长度:无
* 长度可变的非 Unicode 数据
*/
TEXT ("text", new StringLimit()),
/**
* 长度可变的 Unicode 数据
*
*/
N_TEXT ("ntext", new StringLimit()),
/**
* 长度可变的二进制数据
*/
IMAGE ("image", new StringLimit()),
/* =============================== 浮点类型: =============================== */
/**
* 显示 real
*/
FLOAT ("float", new FloatLimit().precision(53, 18).scale(18, 3)),
/* =============================== 日期时间类型: =============================== */
DATE ("date", new DateTimeLimit()),
/**
* 默认长度4005
*/
TIME ("time", new DateTimeLimit()),
DATE_TIME ("datetime", new DateTimeLimit()),
DATE_TIME2 ("datetime2", new DateTimeLimit()),
TIMESTAMP ("timestamp", new DateTimeLimit()),
/* =============================== 定点数类型: =============================== */
DECIMAL ("decimal", new DecimalLimit(true).precision(38, 18).scale(18, 3)),
;
/**
* 数据库字段类型
*/
private final String dataType;
/**
* 长度、精度、标度规则模型
*/
private final DtLimitBase dtLimit;
}

View File

@@ -0,0 +1,192 @@
package com.yunzhupaas.database.datatype.db.interfaces;
import com.yunzhupaas.database.datatype.limit.base.DtLimitModel;
import com.yunzhupaas.database.datatype.viewshow.ViewDataTypeEnum;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.util.StringUtil;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* 数据库数据类型接口
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/11/26
*/
public interface DtInterface {
/**
* 以字符为单位的最大长度,适于二进制数据、字符数据,或者文本和图像数据。否则,返回 NULL
* 例如text、varcharint时为null其中varchar为可变长度text为固定长度
*/
String CHARACTER_LENGTH = "CHARACTER_MAXIMUM_LENGTH";
/**
* precision:数值精度(整个数值的长度)
* 例如decimal
* 注意int(i)类型时无论i是多少NUMERIC_PRECISION都是10在填充0的时候i才会起作用
*/
String NUMERIC_PRECISION = "NUMERIC_PRECISION";
/**
* scale:数值标度(小数部分的长度)
*/
String NUMERIC_SCALE = "NUMERIC_SCALE";
/**
* 获取数据库自身数据类型
*
* @return ignore
*/
String getDataType();
/**
* 获取枚举名
*
* @return ignore
*/
String name();
/**
* 获取长度规则模型
*
* @return ignore
*/
DtLimitBase getDtLimit();
/**
* 字符长度
*/
default DtLimitModel getCharLengthLm() {
return getDtLimit().getCharLengthLm();
}
/**
* 字节长度
*/
default DtLimitModel getBitLengthLm() {
return getDtLimit().getBitLengthLm();
}
/**
* 精度
*/
default DtLimitModel getNumPrecisionLm() {
return getDtLimit().getNumPrecisionLm();
}
/**
* 标度
*/
default DtLimitModel getNumScaleLm() {
return getDtLimit().getNumScaleLm();
}
/**
* 数据类型
*/
default String getDtCategory() {
return getDtLimit().getDtCategory();
}
/**
* 是否可修改
*/
default Boolean getIsModifyFlag() {
return getDtLimit().getIsModifyFlag();
}
/**
* java类型
*/
default String getJavaType() {
return getDtLimit().getJavaType();
}
/**
* 数据库类型
*
* @return dbType
*/
default String getDbType() {
return this.getClass().getSimpleName().replace("Dt", "").replace("Enum", "");
}
/**
* 根据数据库类型编码获取枚举类
*/
static <T extends DtInterface> Class<T> getClz(String dbType) throws Exception {
// 数据类型枚举类命名规则Dt + yunzhupaasDbEncode
return (Class<T>) Class.forName("com.yunzhupaas.database.datatype.db.Dt" + dbType + "Enum");
}
/**
* 根据前端数据类型,返回对应枚举
*
* @param viewDataType 前端数据类型名称
* @param dbEncode 数据类型枚数据库编码
* @return 数据类型枚举
*/
static DtInterface newInstanceByView(String viewDataType, String dbEncode) throws Exception {
if (StringUtil.isNotNull(viewDataType)) {
for (ViewDataTypeEnum value : ViewDataTypeEnum.values()) {
if (value.getViewFieldType().equalsIgnoreCase(viewDataType)) {
switch (dbEncode) {
case DbBase.MYSQL:
return value.getDtMySQLEnum();
case DbBase.ORACLE:
return value.getDtOracleEnum();
case DbBase.SQL_SERVER:
return value.getDtSQLServerEnum();
case DbBase.DM:
return value.getDtDMEnum();
case DbBase.KINGBASE_ES:
return value.getDtKingbaseESEnum();
case DbBase.POSTGRE_SQL:
return value.getDtPostgreSQLEnum();
default:
}
}
}
}
return null;
}
/**
* 根据数据类型,返回对应枚举
*
* @param dtDataType 数据库数据类型名称
* @param dbEncode 数据类型枚数据库编码
* @return 数据类型枚举
*/
static DtInterface newInstanceByDt(String dtDataType, String dbEncode) throws Exception {
BiFunction<String, String, String> checkDataType = (dataType, dbType) -> {
switch (dbType) {
case DbBase.MYSQL:
if (dataType.equalsIgnoreCase("INT UNSIGNED"))
return "int";
if (dataType.equalsIgnoreCase("BIGINT UNSIGNED"))
return "bigint";
case DbBase.ORACLE:
case DbBase.SQL_SERVER:
case DbBase.DM:
case DbBase.KINGBASE_ES:
case DbBase.POSTGRE_SQL:
default:
return dataType;
}
};
// 当类型无法在预设中找到时,在枚举中寻找
for (DtInterface enumConstant : getClz(dbEncode).getEnumConstants()) {
if (enumConstant.getDataType().equalsIgnoreCase(checkDataType.apply(dtDataType, dbEncode))) {
return enumConstant;
}
}
return null;
}
}

View File

@@ -0,0 +1,154 @@
package com.yunzhupaas.database.datatype.db.interfaces;
import com.yunzhupaas.database.datatype.limit.base.DtLimitModel;
import com.yunzhupaas.database.datatype.model.DtModel;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
import lombok.AccessLevel;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.Getter;
/**
* 数据类型:长度精度限制
* default:为可变长度时的默认值
* fixed:不可变长度的固有值
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-05-19
*/
@Data
public abstract class DtLimitBase {
{
this.dtCategory = initDtCategory();
}
/**
* 数据类型 - 归属
*/
protected String dtCategory;
/**
* 数据类型 - 可修改表示
* true:可修改 false:不可修改
*/
protected Boolean isModifyFlag = false;
private String javaType;
/**
* 默认最短长度
*/
private final static Integer YUNZHUPAAS_MIN_LENGTH = 0;
private final static Integer ONE_MIN_LENGTH = 1;
/* 数据类型 - 长度限制模型 =========== */
/**
* 字符长度
* 会显示类似5E+1长度的字符串,例如4294967295固Long类型
*/
@Getter(AccessLevel.PACKAGE)
private DtLimitModel charLengthLm;
/**
* 字节长度
*/
@Getter(AccessLevel.PACKAGE)
private DtLimitModel bitLengthLm;
/**
* 精度(数值整体长度)
* >= 1
*/
@Getter(AccessLevel.PACKAGE)
private DtLimitModel numPrecisionLm;
/**
* 标度(数值小数点长度)
* >= 0 && 标度 < 精度
* 默认为: 0
*/
@Getter(AccessLevel.PACKAGE)
private DtLimitModel numScaleLm;
/**
* 设置数据归档类型
*/
public abstract String initDtCategory();
/**
* 转换
* 特殊MySQL的varchar作为主键的长度是一个特殊值
*
* @param dtModelDTO 前端数据类型模型
* @return 数据类型模型
*/
public abstract DtModel convert(DtModelDTO dtModelDTO);
/* ======================================== */
/**
* 精度
*/
public DtLimitBase precision(Integer precisionMax, Integer precisionDefault) {
this.numPrecisionLm = new DtLimitModel(precisionMax, ONE_MIN_LENGTH, precisionDefault);
return this;
}
/**
* 标度
*/
public DtLimitBase scale(Integer scaleMax, Integer scaleDefault) {
return scale(scaleMax, YUNZHUPAAS_MIN_LENGTH, scaleDefault);
}
public DtLimitBase scale(Integer scaleMax, Integer scaleMin, Integer scaleDefault) {
this.numScaleLm = new DtLimitModel(scaleMax, scaleMin, scaleDefault);
return this;
}
/**
* 字符长度
*/
public DtLimitBase charLength(Long charLengthMax, Long defaultLength) {
this.charLengthLm = new DtLimitModel(charLengthMax, ONE_MIN_LENGTH, defaultLength);
return this;
}
/**
* 字节长度
*/
public DtLimitBase bitLength(Long bitLengthMax, Long defaultLength) {
this.bitLengthLm = new DtLimitModel(bitLengthMax, ONE_MIN_LENGTH, defaultLength);
return this;
}
/* ==================== 固定长度(当没有输入默认长度时,为固定长度) ====================== */
/**
* 固定精度标度
*/
public DtLimitBase fixedScale(Integer scaleFixed) {
this.numScaleLm = new DtLimitModel(scaleFixed);
return this;
}
public DtLimitBase fixedPrecision(Integer precisionFixed) {
this.numPrecisionLm = new DtLimitModel(precisionFixed);
return this;
}
public DtLimitBase fixedBitLength(Long bitLengthFixed) {
this.bitLengthLm = new DtLimitModel(bitLengthFixed);
return this;
}
public DtLimitBase fixedCharLength(Long charLengthFixed) {
this.charLengthLm = new DtLimitModel(charLengthFixed);
return this;
}
}

View File

@@ -0,0 +1,41 @@
package com.yunzhupaas.database.datatype.limit;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.model.DtModel;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
import lombok.NoArgsConstructor;
/**
* 时间数据类型
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-06
*/
@NoArgsConstructor
public class DateTimeLimit extends DtLimitBase {
public final static String CATEGORY = "type-DateTime";
public final static String JAVA_TYPE = "date";
public DateTimeLimit(Boolean modify){
this.isModifyFlag = modify;
}
@Override
public String initDtCategory() {
return CATEGORY;
}
@Override
public DtModel convert(DtModelDTO dtModelDTO){
DtModel dataTypeModel = new DtModel(dtModelDTO.getConvertTargetDtEnum());
if(this.isModifyFlag){
dataTypeModel.setFormatLengthStr("");
}
return dataTypeModel;
}
}

View File

@@ -0,0 +1,41 @@
package com.yunzhupaas.database.datatype.limit;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.util.DtLimitUtil;
import com.yunzhupaas.database.datatype.model.DtModel;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
/**
* 小数数据类型
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-06
*/
public class DecimalLimit extends DtLimitBase {
public final static String CATEGORY = "type-Decimal";
public final static String JAVA_TYPE = "decimal";
{this.dtCategory = CATEGORY;}
public DecimalLimit(Boolean modify) {
this.isModifyFlag = modify;
}
@Override
public String initDtCategory() {
return CATEGORY;
}
@Override
public DtModel convert(DtModelDTO viewDtModel){
DtModel dataTypeModel = DtLimitUtil.convertNumeric(viewDtModel);
if(this.isModifyFlag){
DtLimitUtil.getNumericLength(dataTypeModel);
}
return dataTypeModel;
}
}

View File

@@ -0,0 +1,42 @@
package com.yunzhupaas.database.datatype.limit;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.util.DtLimitUtil;
import com.yunzhupaas.database.datatype.model.DtModel;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
import lombok.NoArgsConstructor;
/**
* 浮点数据类型
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-06
*/
@NoArgsConstructor
public class FloatLimit extends DtLimitBase {
public final static String CATEGORY = "type-Float";
public final static String JAVA_TYPE = "float";
public FloatLimit(Boolean modify){
this.isModifyFlag = modify;
}
@Override
public String initDtCategory() {
return CATEGORY;
}
@Override
public DtModel convert(DtModelDTO viewDtModel){
DtModel dataTypeModel = DtLimitUtil.convertNumeric(viewDtModel);
if(this.isModifyFlag){
DtLimitUtil.getNumericLength(dataTypeModel);
}
return dataTypeModel;
}
}

View File

@@ -0,0 +1,73 @@
package com.yunzhupaas.database.datatype.limit;
import com.yunzhupaas.database.datatype.db.DtMySQLEnum;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.model.DtModel;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
import com.yunzhupaas.database.datatype.sync.util.DtSyncUtil;
import com.yunzhupaas.database.source.DbBase;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 整型数据类型
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-06
*/
@Data
@NoArgsConstructor
public class IntegerLimit extends DtLimitBase {
public final static String CATEGORY = "type-Integer";
public final static String JAVA_TYPE = "int";
@Override
public String initDtCategory() {
return CATEGORY;
}
@Override
public DtModel convert(DtModelDTO viewDtModel){
DtInterface targetDtEnum = viewDtModel.getConvertTargetDtEnum();
DtModel toModel = new DtModel(targetDtEnum);
// 当转换成Oracle的数字类型
if(targetDtEnum.getDtCategory().equals(NumberLimit.CATEGORY)){
try{
// 先当前数据库转成DtMySQL枚举
DtMySQLEnum dtEnum = (DtMySQLEnum) DtSyncUtil.getToFixCovert(targetDtEnum, DbBase.MYSQL);
// 在进行转换对比
switch (dtEnum){
case TINY_INT:
toModel.setNumPrecision(3);
break;
case SMALL_INT:
toModel.setNumPrecision(5);
break;
case MEDIUM_INT:
toModel.setNumPrecision(7);
break;
case INT:
toModel.setNumPrecision(10);
break;
case BIGINT:
toModel.setNumPrecision(19);
break;
default:
}
}catch (Exception e){
e.printStackTrace();
}
}
if(this.isModifyFlag){
toModel.setFormatLengthStr("");
}
return toModel;
}
}

View File

@@ -0,0 +1,57 @@
package com.yunzhupaas.database.datatype.limit;
import com.yunzhupaas.database.datatype.db.DtOracleEnum;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.util.DtLimitUtil;
import com.yunzhupaas.database.datatype.model.DtModel;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
import com.yunzhupaas.database.source.DbBase;
/**
* 数字数据类型
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-06
*/
public class NumberLimit extends DtLimitBase {
public final static String CATEGORY = "type-Number";
public final static String JAVA_TYPE = "number";
public NumberLimit(Boolean modify){
this.isModifyFlag = modify;
}
@Override
public String initDtCategory() {
return CATEGORY;
}
@Override
public DtModel convert(DtModelDTO viewDtModel){
DtModel dataTypeModel;
switch (viewDtModel.getDtEnum().getDtCategory()){
case DecimalLimit.CATEGORY:
case IntegerLimit.CATEGORY:
case NumberLimit.CATEGORY:
dataTypeModel = DtLimitUtil.convertNumeric(viewDtModel);
break;
default:
dataTypeModel = new DtModel(viewDtModel.getDtEnum());
}
if(viewDtModel.getConvertTargetDtEnum().getIsModifyFlag()){
if(viewDtModel.getConvertTargetDtEnum().getDbType().equals(DbBase.ORACLE)){
if(dataTypeModel.getNumPrecision().equals(0) && dataTypeModel.getNumScale().equals(0)){
dataTypeModel.setNumPrecision(Integer.valueOf(DtOracleEnum.NUMBER.getNumPrecisionLm().getDefaults().toString()));
dataTypeModel.setNumScale(Integer.valueOf(DtOracleEnum.NUMBER.getNumScaleLm().getDefaults().toString()));
}
}
DtLimitUtil.getNumericLength(dataTypeModel);
}
return dataTypeModel;
}
}

View File

@@ -0,0 +1,91 @@
package com.yunzhupaas.database.datatype.limit;
import com.yunzhupaas.database.datatype.db.DtMySQLEnum;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.db.interfaces.DtLimitBase;
import com.yunzhupaas.database.datatype.limit.base.DtLimitModel;
import com.yunzhupaas.database.datatype.limit.util.DtLimitUtil;
import com.yunzhupaas.database.datatype.model.DtModel;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
import com.yunzhupaas.database.source.DbBase;
import lombok.NoArgsConstructor;
import java.util.function.BiFunction;
/**
* 字符串数据类型
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-06
*/
@NoArgsConstructor
public class StringLimit extends DtLimitBase {
public final static String CATEGORY = "type-String";
public final static String JAVA_TYPE = "String";
@Override
public String initDtCategory() {
return CATEGORY;
}
public StringLimit(Boolean modify){
this.isModifyFlag = modify;
}
@Override
public DtModel convert(DtModelDTO dto){
DtInterface originEnum = dto.getDtEnum();
DtInterface targetEnum = dto.getConvertTargetDtEnum();
DtModel dataTypeModel = new DtModel(targetEnum);
special(dto);
if(this.isModifyFlag){
// 设置模型
BiFunction<Long, DtLimitModel, Long> setMod = (inputVarLength, varLengthLm)->{
// 长度设置;
Long targetLength = DtLimitUtil.convertCharacter(inputVarLength, dto.getConvertType(), varLengthLm);
// 获取字符类型显示
dataTypeModel.setFormatLengthStr(targetLength.toString());
return targetLength;
};
// 字节字符转换规则
boolean originBigFlag = originEnum.getBitLengthLm() != null;
boolean originCharFlag = originEnum.getCharLengthLm() != null;
boolean targetBigFlag = targetEnum.getBitLengthLm() != null;
boolean targetCharFlag = targetEnum.getCharLengthLm() != null;
/* GBK 1字符=2字节UTF8 1字符=3字节 */
if(originBigFlag && targetCharFlag){
// 字节 -> 字符 /3
dataTypeModel.setCharLength(setMod.apply(dto.getBitLength() / 3, targetEnum.getCharLengthLm()));
}else if(originCharFlag && targetBigFlag){
// 字符 -> 字节 *3
dataTypeModel.setBitLength(setMod.apply(dto.getCharLength() * 3, targetEnum.getBitLengthLm()));
}else if(originBigFlag && targetBigFlag){
// 字节 -> 字节 ==
dataTypeModel.setBitLength(setMod.apply(dto.getBitLength(), targetEnum.getBitLengthLm()));
}else if(originCharFlag){
// 字符 -> 字符 ==
dataTypeModel.setCharLength(setMod.apply(dto.getCharLength(), targetEnum.getCharLengthLm()));
}
}
return dataTypeModel;
}
/**
* 特殊情况
*/
public void special(DtModelDTO dto){
DtInterface originEnum = dto.getDtEnum();
if(originEnum.getDbType().equals(DbBase.MYSQL) &&
originEnum.getDataType().equals(DtMySQLEnum.BIT.getDataType()) &&
dto.getCharLength() == 1){
/* MySQL设置tinyint类型且长度为1时JDBC读取时会变成BIT类型java类型为Boolean类型。
1:true , 0:false , 当前先转换成字符串格式长度为5*/
dto.setCharLength(15L);
}
}
}

View File

@@ -0,0 +1,58 @@
package com.yunzhupaas.database.datatype.limit.base;
import lombok.AllArgsConstructor;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-06
*/
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class DtLimitModel {
/**
* 最大长度
*/
private Object max;
/**
* 最小长度
*/
private Object min;
/**
* 默认长度
*/
private Object defaults;
/**
* 固定长度
*/
private Object fixed;
public DtLimitModel(Object fixed){
this.fixed = fixed;
}
/**
* 生成类型限制对象
*/
public DtLimitModel(Object maxLength, Object minLength, Object defaultLength){
this.max = maxLength;
this.min = minLength;
this.defaults = defaultLength;
this.fixed = defaultLength;
}
}

View File

@@ -0,0 +1,45 @@
package com.yunzhupaas.database.datatype.limit.base;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version v3.4.5
* @copyrignt 深圳市乐程软件有限公司
* @date 2024-12-15
*/
@Data
public class DtModelBase {
/**
* 数据类型枚举
*/
protected DtInterface dtEnum;
/**
* 字符长度1个字母1个字节1个汉字1个字节
*/
protected Long charLength;
/**
* 字节长度1个字母1个字节1个汉字GBK:2个字节,UTF8:3个字节
*/
protected Long bitLength;
/**
* 精度(数值整体长度)
*/
protected Integer numPrecision;
/**
* 标度(数值小数点长度)
*/
protected Integer numScale;
}

View File

@@ -0,0 +1,152 @@
package com.yunzhupaas.database.datatype.limit.util;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.limit.base.DtLimitModel;
import com.yunzhupaas.database.datatype.model.DtModel;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-06
*/
public class DtLimitUtil {
/* ============== 转换方式 =============== */
/*
* 说明:
* 1、不可修改转可修改按默认值
* 2、可修改转可修改
* 3、创建可修改
*
* (以下都不进行长度设置)
* 4、可修改转不可修改
* 5、不可修改转不可修改
* 6、创建不可修改
* */
/**
* 数值转换
* @param dto 前端数据类型模型
* @return 转换数据类型模板
*/
public static DtModel convertNumeric(DtModelDTO dto){
DtInterface toDtEnum = dto.getConvertTargetDtEnum();
DtModel toModel = new DtModel(toDtEnum);
DtLimitModel numPrecisionLm = toDtEnum.getNumPrecisionLm();
DtLimitModel numScaleLm = toDtEnum.getNumScaleLm();
// 精度、标度:标准化 =========
Integer numPrecision = dto.getNumPrecision();
Integer numScale = dto.getNumScale();
if(toDtEnum.getIsModifyFlag()){
switch (dto.getConvertType()){
// 1数据库取到的值
case DtModelDTO.DB_VAL:
break;
// 2使用固定值
case DtModelDTO.FIX_VAL:
numPrecision = (Integer) numPrecisionLm.getFixed();
numScale = (Integer) numScaleLm.getFixed();
break;
// 3前端传来的参数
case DtModelDTO.VIEW_VAL:
// 验证比较
numPrecision = convertNum(numPrecision, (Integer) numPrecisionLm.getMin(), (Integer) numPrecisionLm.getMax(), (Integer)numPrecisionLm.getDefaults());
numScale = convertNum(numScale, (Integer) numScaleLm.getMin(), (Integer) numScaleLm.getMax(), (Integer)numScaleLm.getDefaults());
break;
default:
}
// 数据型设置 =========
toModel.setNumPrecision(numPrecision);
toModel.setNumScale(numScale);
toModel.formatNumLength(numPrecision, numScale);
}
return toModel;
}
/**
* 字符转换
* @return 转换数据类型模板
*/
public static Long convertCharacter(Long inputVarLength, String convertType, DtLimitModel varLengthLm){
// 精度、标度:标准化 =========
Long outVarLength = null;
switch (convertType){
// 1数据库取到的值且同库(不用转换直接使用)
case DtModelDTO.DB_VAL:
outVarLength = inputVarLength;
break;
// 2使用固定值
case DtModelDTO.FIX_VAL:
outVarLength = (Long)varLengthLm.getFixed();
break;
// 3主要转换前端传来的参数
case DtModelDTO.VIEW_VAL:
// 验证比较
outVarLength = convertLongNum(inputVarLength, (Long) varLengthLm.getMax(), (Long) varLengthLm.getDefaults());
break;
default:
}
return outVarLength;
}
/* ================ */
/**
* 获取数值类型显示
*/
public static void getNumericLength(DtModel model){
model.setFormatLengthStr(model.getNumPrecision() + "," + model.getNumScale());
}
/* =========== 内部使用算法 =========== */
/**
* originNum < [Min, Max] < originNum
*/
private static Integer convertNum(Integer originNum, Integer toMin, Integer toMax, Integer defaultNum){
originNum = originNum == null || originNum < toMin ? defaultNum : originNum;
// 区间内
if(originNum >= toMin && toMax >= originNum){
return originNum;
}else if(originNum > toMax){
// 大于区间,为保证尽可能数据不丢失,返回最大长度
return toMax;
}else {
return toMin;
}
}
/**
* charLength 的 Long类型
* >= 0
*/
private static Long convertLongNum(Long originNum, Long toMax, Long defaultNum){
originNum = originNum == null || originNum < 1 ? defaultNum : originNum;
if(originNum <= toMax){
return originNum;
}else{
return toMax;
}
}
/*
说明:
UTF-8一个汉字 = 3个字节英文一个字母占用一个字节
GBK 一个汉字 = 2个字节英文一个字母占用一个字节
MySQL的char_length计算的是字符长度而Oracle的bit_length计算的是字节长度
1、GBK是在国家标准GB2312基础上扩容后兼容GB2312的标准。GBK编码专门用来解决中文编码的是双字节的。不论中英文都是双字节的。
2、UTF8编码是用以解决国际上字符的一种多字节编码它对英文使用8位即一个字节中文使用24位三个字节来编码。
对于英文字符较多的论坛则用UTF8节省空间。另外如果是外国人访问你的GBK网页需要下载中文语言包支持。
访问UTF-8编码的网页则不出现这问题。可以直接访问。
3、GBK包含全部中文字符UTF8则包含全世界所有国家需要用到的字符。
*/
}

View File

@@ -0,0 +1,61 @@
package com.yunzhupaas.database.datatype.model;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.limit.base.DtModelBase;
import com.yunzhupaas.util.StringUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 数据类型模型
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/25
*/
@Data
public class DtModel extends DtModelBase {
/**
* 显示长度
*/
private String formatLengthStr;
public DtModel(DtInterface dtEnum){
this.dtEnum = dtEnum;
}
/**
* 表字段数据类型名
*/
public String getDataType(){
return this.dtEnum.getDataType();
}
/**
* java数据类型
*/
public String getJavaType(){
return this.dtEnum.getJavaType();
}
/**
* 当精度(>=1小于标度
* 重置标度,让其小于精度(精度-1)
*/
public void formatNumLength(Integer numPrecision, Integer numScale){
if(numScale != null && numPrecision < numScale){
this.numScale = numPrecision - 1;
}
}
public String formatDataType(){
String lengthInfo = getFormatLengthStr();
return getDataType() + (StringUtil.isNotEmpty(lengthInfo) ? "(" + lengthInfo + ")" : "");
}
}

View File

@@ -0,0 +1,125 @@
package com.yunzhupaas.database.datatype.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.limit.base.DtModelBase;
import com.yunzhupaas.database.datatype.utils.DataTypeUtil;
import com.yunzhupaas.database.datatype.viewshow.ViewDataTypeEnum;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.StringUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* 前端数据类型模型
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/25
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
public class DtModelDTO extends DtModelBase {
/**
* 转换目标类型
*/
@JsonIgnore
private DtInterface convertTargetDtEnum;
/**
* 数据库取到的值(不用转换直接使用)
*/
public final static String DB_VAL = "DB_VAL";
/**
* 使用固定值
*/
public final static String FIX_VAL = "FIX_VAL";
/**
* 主要转换:前端传来的参数
*/
public final static String VIEW_VAL = "VIEW_VAL";
/**
* 转换类型
*/
private String convertType = VIEW_VAL;
/**
* 初始化创建表使用
*
* 析长度信息,例如 decimal(18,3) 中的 18,3
* @param dataType 数据类型
* @param dtLength 数据精度、标度信息
* @param dbEncode 数据库类型
*/
public DtModelDTO(String dataType, String dtLength, String dbEncode, boolean viewFlag) throws Exception {
// 设置长度
if (StringUtil.isEmpty(dtLength)) dtLength = "-1";
if (dtLength.contains(",")) {
String[] split = dtLength.split(",");
if (DataTypeUtil.numFlag(split[0], split[1])) {
charLength = Long.parseLong(split[0]);
bitLength = Long.parseLong(split[0]);
numPrecision = Integer.parseInt(split[0]);
numScale = Integer.parseInt(split[1]);
}
} else {
if (DataTypeUtil.numFlag(dtLength)) {
charLength = Long.parseLong(dtLength);
bitLength = Long.parseLong(dtLength);
numPrecision = Integer.parseInt(dtLength);
}
}
// 1、根据前端信息判断内置数据标准类型枚举
if(viewFlag) dtEnum = DtInterface.newInstanceByView(dataType, dbEncode);
// 2、直接使用前端数据类型作为数据库类型查询
if (dtEnum == null) dtEnum = DtInterface.newInstanceByDt(dataType, dbEncode);
if (dtEnum == null) new DataException(MsgCode.DB013.get(dbEncode, dataType)).printStackTrace();
convertTargetDtEnum = dtEnum;
}
/**
* 初始化显示表使用
*
* @param charLength 字符串长度
* @param numPrecision 精度
* @param numScale 标度
*/
public DtModelDTO(DtInterface dtEnum, Long charLength, Integer numPrecision, Integer numScale) {
this.dtEnum = dtEnum;
this.numPrecision = numPrecision;
this.numScale = numScale;
if (dtEnum.getCharLengthLm() != null) {
this.charLength = charLength;
} else if(dtEnum.getBitLengthLm() != null){
this.bitLength = charLength;
}
}
/**
* 默认建表字符串数据类型(当数据类型失败时候,使用这个减低错误率)
*
* @param dbEncode 数据类型编码
* @return 字符串数据类型Sql片段
*/
public static String getStringFixedDt(String dbEncode) throws Exception {
DtInterface dtEnum = DtInterface.newInstanceByView(ViewDataTypeEnum.VARCHAR.getViewFieldType(), dbEncode);
if (dtEnum != null) {
DtModelDTO dto = new DtModelDTO(dtEnum, -1L, -1, -1);
dto.setConvertType(FIX_VAL);
return dto.convert().formatDataType();
}
return "varchar(50)";
}
public DtModel convert() {
return dtEnum.getDtLimit().convert(this);
}
}

View File

@@ -0,0 +1,771 @@
package com.yunzhupaas.database.datatype.sync.enums;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.database.datatype.db.*;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.sync.model.DtConvertModel;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.exception.DataException;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 数据库相对应一些方法
* 固定转换关系
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-05-31
*/
@Getter
@AllArgsConstructor
public enum DtConvertEnum {
/**
* 根据数据选择的方法枚举
*/
MYSQL(DbBase.MYSQL){
/**
* DtMutualConvertEnum(默认原始搭配),在这个地方重复的枚举会重写覆盖原来的搭配
*/
@Override
public <T extends DtInterface> DtConvertModel<T> getModel(T dtEnum){
DtConvertModel<T> model = new DtConvertModel<>();
switch ((DtMySQLEnum)dtEnum){
/* =============================== 整数类型 =============================== */
case TINY_INT: convert(model,
DtOracleEnum.NUMBER,
DtSQLServerEnum.TINY_INT,
DtDMEnum.TINY_INT,
DtKingbaseESEnum.TINY_INT,
DtPostgreSQLEnum.INT2,
DtDorisEnum.TINY_INT
); break;
case SMALL_INT: convert(model,
DtOracleEnum.NUMBER,
DtSQLServerEnum.SMALL_INT,
DtDMEnum.SMALL_INT,
DtKingbaseESEnum.SMALL_INT,
DtPostgreSQLEnum.INT2,
DtDorisEnum.SMALL_INT
); break;
case MEDIUM_INT:
case INT: convert(model,
DtOracleEnum.NUMBER,
DtSQLServerEnum.INT,
DtDMEnum.INT,
DtKingbaseESEnum.INTEGER,
DtPostgreSQLEnum.INT4,
DtDorisEnum.INT
); break;
case BIGINT: convert(model,
DtOracleEnum.NUMBER,
DtSQLServerEnum.BIGINT,
DtDMEnum.BIGINT,
DtKingbaseESEnum.BIGINT,
DtPostgreSQLEnum.INT8,
DtDorisEnum.BIGINT
); break;
// ====================== 文本字符串类型: ==========================;==== */
// mysql(varchar) 转成 oracle(NVARCHAR2)、sqlserver(nvarchar;
case CHAR: convert(model,
DtOracleEnum.CHAR,
DtSQLServerEnum.CHAR,
DtDMEnum.CHAR,
DtKingbaseESEnum.CHAR,
DtPostgreSQLEnum.CHAR,
DtDorisEnum.CHAR
); break;
// mysql(test) 转成 oracle(NCLOB)、sqlserver(nvarchar(max); break;
case BLOB: convert(model,
DtOracleEnum.BLOB,
DtSQLServerEnum.VARBINARY,
DtDMEnum.BLOB,
DtKingbaseESEnum.TEXT,
DtPostgreSQLEnum.BYTEA,
DtDorisEnum.STRING
); break;
case BIT:
case VARCHAR: convert(model,
DtOracleEnum.NVARCHAR2,
DtSQLServerEnum.NVARCHAR,
DtDMEnum.VARCHAR,
DtKingbaseESEnum.VARCHAR,
DtPostgreSQLEnum.VARCHAR,
DtDorisEnum.VARCHAR
); break;
case TINY_TEXT:
case TEXT:
case MEDIUM_TEXT:
case LONG_TEXT: convert(model,
DtOracleEnum.CLOB,
DtSQLServerEnum.VARCHAR_MAX,
DtDMEnum.CLOB,
DtKingbaseESEnum.TEXT,
DtPostgreSQLEnum.TEXT);
break;
case LONG_BLOB: convert(model,
DtOracleEnum.BLOB,
DtSQLServerEnum.VARBINARY,
DtDMEnum.BLOB,
DtKingbaseESEnum.BYTEA,
DtPostgreSQLEnum.BYTEA
); break;
// ====================== 浮点类型: =============================;= */
case FLOAT: convert(model,
DtDMEnum.FLOAT,
DtOracleEnum.FLOAT,
DtSQLServerEnum.FLOAT,
DtKingbaseESEnum.FLOAT4,
DtPostgreSQLEnum.FLOAT4,
DtDorisEnum.FLOAT
); break;
case DOUBLE: convert(model,
DtOracleEnum.FLOAT,
DtSQLServerEnum.FLOAT,
DtDMEnum.DOUBLE,
DtKingbaseESEnum.FLOAT8,
DtPostgreSQLEnum.FLOAT8,
DtDorisEnum.DOUBLE
); break;
// ====================== 定点数类型: ============================;== */
case DECIMAL: convert(model,
DtOracleEnum.NUMBER,
DtSQLServerEnum.DECIMAL,
DtDMEnum.DECIMAL,
DtKingbaseESEnum.NUMERIC,
DtPostgreSQLEnum.NUMERIC,
DtDorisEnum.DECIMAL
); break;
// ====================== 日期时间类型: ===========================;=== */
case YEAR:
case DATE: convert(model,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.DATE_TIME,
DtDMEnum.DATE_TIME,
DtKingbaseESEnum.DATE,
DtPostgreSQLEnum.TIMESTAMP,
DtDorisEnum.DATE
); break;
case TIME: convert(model,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.TIME,
DtDMEnum.TIME,
DtKingbaseESEnum.TIME,
DtPostgreSQLEnum.TIME,
DtDorisEnum.DATE_TIME
); break;
case DATE_TIME:convert(model,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.DATE_TIME,
DtDMEnum.TIME_STAMP,
DtKingbaseESEnum.TIMESTAMP,
DtPostgreSQLEnum.TIMESTAMP,
DtDorisEnum.DATE_TIME
); break;
case TIMESTAMP: convert(model,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.TIMESTAMP,
DtDMEnum.TIME_STAMP,
DtKingbaseESEnum.TIMESTAMP,
DtPostgreSQLEnum.TIMESTAMP,
DtDorisEnum.DATE_TIME
); break;
default:
}
model.setDtMySQLEnum((DtMySQLEnum) dtEnum);
return model;
}
},
ORACLE(DbBase.ORACLE){
@Override
public <T extends DtInterface> DtConvertModel<T> getModel(T dtEnum){
DtConvertModel<T> model = new DtConvertModel<>();
switch ((DtOracleEnum)dtEnum){
/* =============================== 整数类型 =============================== */
case NUMBER: convert(model,
DtMySQLEnum.BIGINT,
DtSQLServerEnum.BIGINT,
DtDMEnum.BIGINT,
DtKingbaseESEnum.BIGINT,
DtPostgreSQLEnum.INT8
); break;
// ===================== 文本字符串类型 ===========================;= */
case CHAR:
case NCHAR: convert(model,
DtMySQLEnum.CHAR,
DtSQLServerEnum.CHAR,
DtDMEnum.CHAR,
DtKingbaseESEnum.CHAR,
DtPostgreSQLEnum.CHAR
); break;
case VARCHAR2: convert(model,
DtMySQLEnum.VARCHAR,
DtSQLServerEnum.NVARCHAR,
DtDMEnum.VARCHAR,
DtKingbaseESEnum.VARCHAR,
DtPostgreSQLEnum.VARCHAR
); break;
case NVARCHAR2: convert(model,
DtMySQLEnum.VARCHAR,
DtSQLServerEnum.NVARCHAR,
DtDMEnum.VARCHAR2,
DtKingbaseESEnum.VARCHAR,
DtPostgreSQLEnum.VARCHAR
); break;
case CLOB: convert(model,
DtMySQLEnum.TEXT,
DtSQLServerEnum.TEXT,
DtDMEnum.TEXT,
DtKingbaseESEnum.TEXT,
DtPostgreSQLEnum.TEXT
); break;
case NCLOB: convert(model,
DtMySQLEnum.LONG_TEXT,
DtSQLServerEnum.N_TEXT,
DtDMEnum.CLOB,
DtKingbaseESEnum.TEXT,
DtPostgreSQLEnum.TEXT
); break;
// ===================== 浮点类型 =============================;*/
case FLOAT: convert(model,
DtMySQLEnum.FLOAT,
DtDMEnum.FLOAT,
DtSQLServerEnum.FLOAT,
DtKingbaseESEnum.FLOAT4,
DtPostgreSQLEnum.FLOAT4
); break;
// ===================== 日期时间类型: ==========================;== */
case DATE: convert(model,
DtMySQLEnum.DATE,
DtSQLServerEnum.DATE,
DtDMEnum.DATE,
DtKingbaseESEnum.DATE,
DtPostgreSQLEnum.DATE
); break;
case TIMESTAMP: convert(model,
DtMySQLEnum.TIMESTAMP,
DtSQLServerEnum.TIMESTAMP,
DtDMEnum.TIME_STAMP,
DtKingbaseESEnum.TIMESTAMP,
DtPostgreSQLEnum.TIMESTAMP
); break;
default:
}
model.setDtOracleEnum((DtOracleEnum) dtEnum);
return model;
}
},
SQL_SERVER(DbBase.SQL_SERVER){
@Override
public <T extends DtInterface> DtConvertModel<T> getModel(T dtEnum){
DtConvertModel<T> model = new DtConvertModel<>();
switch ((DtSQLServerEnum)dtEnum){
/* =============================== 整数类型 =============================== */
case TINY_INT: convert(model,
DtMySQLEnum.TINY_INT,
DtOracleEnum.NUMBER,
DtDMEnum.TINY_INT,
DtKingbaseESEnum.TINY_INT,
DtPostgreSQLEnum.INT2
); break;
case SMALL_INT: convert(model,
DtMySQLEnum.SMALL_INT,
DtOracleEnum.NUMBER,
DtDMEnum.SMALL_INT,
DtKingbaseESEnum.SMALL_INT,
DtPostgreSQLEnum.INT2
); break;
case INT: convert(model,
DtMySQLEnum.INT,
DtOracleEnum.NUMBER,
DtDMEnum.INT,
DtKingbaseESEnum.INTEGER,
DtPostgreSQLEnum.INT4
); break;
case BIGINT: convert(model,
DtMySQLEnum.BIGINT,
DtOracleEnum.NUMBER,
DtDMEnum.BIGINT,
DtKingbaseESEnum.BIGINT,
DtPostgreSQLEnum.INT8
); break;
// ================== 文本字符串类型 =============================== *;
case CHAR: convert(model,
DtMySQLEnum.CHAR,
DtOracleEnum.CHAR,
DtDMEnum.CHAR,
DtKingbaseESEnum.CHAR,
DtPostgreSQLEnum.CHAR
); break;
case NVARCHAR: convert(model,
DtMySQLEnum.VARCHAR,
DtOracleEnum.NVARCHAR2,
DtDMEnum.VARCHAR2,
DtKingbaseESEnum.VARCHAR,
DtPostgreSQLEnum.VARCHAR
); break;
case VARCHAR: convert(model,
DtMySQLEnum.VARCHAR,
DtOracleEnum.NVARCHAR2,
DtDMEnum.VARCHAR,
DtKingbaseESEnum.VARCHAR,
DtPostgreSQLEnum.VARCHAR
); break;
case VARCHAR_MAX:
case IMAGE:
case TEXT: convert(model,
DtMySQLEnum.TEXT,
DtOracleEnum.CLOB,
DtDMEnum.CLOB,
DtKingbaseESEnum.TEXT,
DtPostgreSQLEnum.TEXT
); break;
case N_TEXT: convert(model,
DtMySQLEnum.LONG_TEXT,
DtOracleEnum.NCLOB,
DtDMEnum.CLOB,
DtKingbaseESEnum.TEXT,
DtPostgreSQLEnum.TEXT
); break;
// ================== 日期时间类型: =============================== *;
case DATE: convert(model,
DtMySQLEnum.DATE,
DtOracleEnum.DATE,
DtDMEnum.DATE,
DtKingbaseESEnum.DATE,
DtPostgreSQLEnum.DATE
); break;
case TIME: convert(model,
DtMySQLEnum.TIME,
DtOracleEnum.TIMESTAMP,
DtDMEnum.TIME,
DtKingbaseESEnum.TIME,
DtPostgreSQLEnum.TIME
); break;
case DATE_TIME: convert(model,
DtMySQLEnum.DATE_TIME,
DtOracleEnum.TIMESTAMP,
DtDMEnum.DATE_TIME,
DtKingbaseESEnum.DATE_TIME,
DtPostgreSQLEnum.TIMESTAMP
); break;
case TIMESTAMP: convert(model,
DtMySQLEnum.TIMESTAMP,
DtOracleEnum.TIMESTAMP,
DtDMEnum.TIME_STAMP,
DtKingbaseESEnum.TIMESTAMP,
DtPostgreSQLEnum.TIMESTAMP
); break;
// ===================== 浮点类型 =============================;*/
case FLOAT: convert(model,
DtMySQLEnum.FLOAT,
DtDMEnum.FLOAT,
DtOracleEnum.FLOAT,
DtKingbaseESEnum.FLOAT4,
DtPostgreSQLEnum.FLOAT4
); break;
// ================== 定点数类型: =============================== *;
case DECIMAL: convert(model,
DtMySQLEnum.DECIMAL,
DtOracleEnum.NUMBER,
DtDMEnum.DECIMAL,
DtKingbaseESEnum.NUMERIC,
DtPostgreSQLEnum.NUMERIC
); break;
default:
}
model.setDtSQLServerEnum((DtSQLServerEnum) dtEnum);
return model;
}
},
DM(DbBase.DM){
@Override
public <T extends DtInterface> DtConvertModel<T> getModel(T dtEnum){
DtConvertModel<T> model = new DtConvertModel<>();
switch ((DtDMEnum)dtEnum){
/* =============================== 整数类型 =============================== */
case TINY_INT: convert(model,
DtMySQLEnum.TINY_INT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.TINY_INT,
DtKingbaseESEnum.TINY_INT,
DtPostgreSQLEnum.INT2
); break;
case SMALL_INT: convert(model,
DtMySQLEnum.SMALL_INT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.SMALL_INT,
DtKingbaseESEnum.SMALL_INT,
DtPostgreSQLEnum.INT2
); break;
case INT: convert(model,
DtMySQLEnum.INT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.INT,
DtKingbaseESEnum.INTEGER,
DtPostgreSQLEnum.INT4
); break;
case BIGINT: convert(model,
DtMySQLEnum.BIGINT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.BIGINT,
DtKingbaseESEnum.BIGINT,
DtPostgreSQLEnum.INT8
); break;
// ===================== 文本字符串类型 ===========================*;
case CHAR: convert(model,
DtMySQLEnum.CHAR,
DtOracleEnum.CHAR,
DtSQLServerEnum.CHAR,
DtKingbaseESEnum.CHAR,
DtPostgreSQLEnum.CHAR
); break;
case VARCHAR:
case VARCHAR2: convert(model,
DtMySQLEnum.VARCHAR,
DtOracleEnum.NVARCHAR2,
DtSQLServerEnum.NVARCHAR,
DtKingbaseESEnum.VARCHAR,
DtPostgreSQLEnum.VARCHAR
); break;
case TEXT:
case CLOB: convert(model,
DtMySQLEnum.TEXT,
DtOracleEnum.CLOB,
DtSQLServerEnum.TEXT,
DtKingbaseESEnum.TEXT,
DtPostgreSQLEnum.TEXT
); break;
// ===================== 时间格式 ===========================*;
case DATE: convert(model,
DtMySQLEnum.DATE,
DtSQLServerEnum.DATE,
DtOracleEnum.DATE,
DtKingbaseESEnum.DATE,
DtPostgreSQLEnum.DATE
); break;
case DATE_TIME: convert(model,
DtMySQLEnum.DATE_TIME,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.DATE_TIME,
DtKingbaseESEnum.DATE_TIME,
DtPostgreSQLEnum.TIMESTAMP
); break;
case TIME_STAMP: convert(model,
DtMySQLEnum.TIMESTAMP,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.TIMESTAMP,
DtKingbaseESEnum.TIMESTAMP,
DtPostgreSQLEnum.TIMESTAMP
); break;
case TIME: convert(model,
DtMySQLEnum.TIME,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.TIME,
DtKingbaseESEnum.TIME,
DtPostgreSQLEnum.TIME
); break;
// =====================浮点===========================*;
case FLOAT: convert(model,
DtMySQLEnum.FLOAT,
DtOracleEnum.FLOAT,
DtSQLServerEnum.FLOAT,
DtKingbaseESEnum.FLOAT4,
DtPostgreSQLEnum.FLOAT4
); break;
case DOUBLE: convert(model,
DtMySQLEnum.DOUBLE,
DtOracleEnum.FLOAT,
DtSQLServerEnum.FLOAT,
DtKingbaseESEnum.FLOAT8,
DtPostgreSQLEnum.FLOAT8
); break;
// ===================== 定点型 ===========================*
case DECIMAL:
case DEC: convert(model,
DtMySQLEnum.DECIMAL,
DtOracleEnum.NUMBER,
DtSQLServerEnum.DECIMAL,
DtKingbaseESEnum.NUMERIC,
DtPostgreSQLEnum.NUMERIC
); break;
default:
}
model.setDtDMEnum((DtDMEnum) dtEnum);
return model;
}
},
KINGBASE(DbBase.KINGBASE_ES){
@Override
public <T extends DtInterface> DtConvertModel<T> getModel(T dtEnum){
DtConvertModel<T> model = new DtConvertModel<>();
switch ((DtKingbaseESEnum)dtEnum){
/* =============================== 整数类型 =============================== */
case TINY_INT: convert(model,
DtMySQLEnum.TINY_INT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.TINY_INT,
DtDMEnum.TINY_INT,
DtPostgreSQLEnum.INT2
); break;
case SMALL_INT: convert(model,
DtMySQLEnum.SMALL_INT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.SMALL_INT,
DtDMEnum.SMALL_INT,
DtPostgreSQLEnum.INT2
); break;
case INTEGER: convert(model,
DtMySQLEnum.INT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.INT,
DtDMEnum.INT,
DtPostgreSQLEnum.INT4
); break;
case BIGINT: convert(model,
DtMySQLEnum.BIGINT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.BIGINT,
DtDMEnum.BIGINT,
DtPostgreSQLEnum.INT8
); break;
// ============= 文本字符串类型 ===========================*;
case CHAR: convert(model,
DtMySQLEnum.CHAR,
DtOracleEnum.CHAR,
DtSQLServerEnum.CHAR,
DtDMEnum.CHAR,
DtPostgreSQLEnum.CHAR
); break;
case VARCHAR: convert(model,
DtMySQLEnum.VARCHAR,
DtOracleEnum.NVARCHAR2,
DtSQLServerEnum.NVARCHAR,
DtDMEnum.VARCHAR,
DtPostgreSQLEnum.VARCHAR
); break;
case TEXT: convert(model,
DtMySQLEnum.TEXT,
DtOracleEnum.CLOB,
DtSQLServerEnum.TEXT,
DtDMEnum.TEXT,
DtPostgreSQLEnum.TEXT
); break;
// =============浮点===========================*;
case FLOAT4: convert(model,
DtMySQLEnum.FLOAT,
DtDMEnum.FLOAT,
DtOracleEnum.FLOAT,
DtSQLServerEnum.FLOAT,
DtPostgreSQLEnum.FLOAT4
); break;
case FLOAT8: convert(model,
DtMySQLEnum.DOUBLE,
DtOracleEnum.FLOAT,
DtSQLServerEnum.FLOAT,
DtDMEnum.DOUBLE,
DtPostgreSQLEnum.FLOAT8
); break;
// =================== 定点型 ========================================*;
case NUMERIC: convert(model,
DtMySQLEnum.DECIMAL,
DtOracleEnum.NUMBER,
DtSQLServerEnum.DECIMAL,
DtDMEnum.DECIMAL,
DtPostgreSQLEnum.NUMERIC
); break;
// ============= 时间格式 ===========================*;
case TIME: convert(model,
DtMySQLEnum.TIME,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.TIME,
DtDMEnum.TIME,
DtPostgreSQLEnum.TIME
); break;
case DATE: convert(model,
DtMySQLEnum.DATE,
DtSQLServerEnum.DATE,
DtOracleEnum.DATE,
DtDMEnum.DATE,
DtPostgreSQLEnum.DATE
); break;
case DATE_TIME: convert(model,
DtMySQLEnum.DATE_TIME,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.DATE_TIME,
DtDMEnum.DATE_TIME,
DtPostgreSQLEnum.TIMESTAMP
); break;
case TIMESTAMP: convert(model,
DtMySQLEnum.TIMESTAMP,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.TIMESTAMP,
DtDMEnum.TIME_STAMP,
DtPostgreSQLEnum.TIMESTAMP
); break;
default:
}
model.setDtKingbaseESEnum((DtKingbaseESEnum) dtEnum);
return model;
}
},
POSTGRE(DbBase.POSTGRE_SQL){
@Override
public <T extends DtInterface> DtConvertModel<T> getModel(T dtEnum){
DtConvertModel<T> model = new DtConvertModel<>();
switch ((DtPostgreSQLEnum)dtEnum){
/* =============================== 整数类型 =============================== */
case INT2: convert(model,
DtMySQLEnum.SMALL_INT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.SMALL_INT,
DtDMEnum.SMALL_INT,
DtKingbaseESEnum.SMALL_INT
); break;
case INT4: convert(model,
DtMySQLEnum.INT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.INT,
DtDMEnum.INT,
DtKingbaseESEnum.INTEGER
); break;
case INT8: convert(model,
DtMySQLEnum.BIGINT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.BIGINT,
DtDMEnum.BIGINT,
DtKingbaseESEnum.BIGINT
); break;
// =================== 文本字符串类型 =======================================*/
case CHAR: convert(model,
DtMySQLEnum.CHAR,
DtOracleEnum.CHAR,
DtSQLServerEnum.CHAR,
DtDMEnum.CHAR,
DtKingbaseESEnum.CHAR
); break;
case VARCHAR: convert(model,
DtMySQLEnum.VARCHAR,
DtOracleEnum.NVARCHAR2,
DtSQLServerEnum.NVARCHAR,
DtDMEnum.VARCHAR,
DtKingbaseESEnum.VARCHAR
); break;
case TEXT: convert(model,
DtMySQLEnum.TEXT,
DtOracleEnum.CLOB,
DtSQLServerEnum.TEXT,
DtDMEnum.TEXT,
DtKingbaseESEnum.TEXT
); break;
// ====================浮点===========================*/
case FLOAT4: convert(model,
DtMySQLEnum.FLOAT,
DtDMEnum.FLOAT,
DtOracleEnum.FLOAT,
DtSQLServerEnum.FLOAT,
DtKingbaseESEnum.FLOAT4
); break;
case FLOAT8: convert(model,
DtMySQLEnum.DOUBLE,
DtOracleEnum.FLOAT,
DtSQLServerEnum.FLOAT,
DtDMEnum.DOUBLE,
DtKingbaseESEnum.FLOAT8
); break;
// =================== 定点型 =======================================*/
case NUMERIC: convert(model,
DtMySQLEnum.DECIMAL,
DtOracleEnum.NUMBER,
DtSQLServerEnum.DECIMAL,
DtDMEnum.DECIMAL,
DtKingbaseESEnum.NUMERIC
); break;
// =================== 时间日期 =======================================*/
case TIME: convert(model,
DtMySQLEnum.TIME,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.TIME,
DtDMEnum.TIME,
DtKingbaseESEnum.TIME
); break;
case DATE: convert(model,
DtMySQLEnum.DATE,
DtSQLServerEnum.DATE,
DtOracleEnum.DATE,
DtDMEnum.DATE,
DtKingbaseESEnum.DATE
); break;
case TIMESTAMP: convert(model,
DtMySQLEnum.TIMESTAMP,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.TIMESTAMP,
DtDMEnum.TIME_STAMP,
DtKingbaseESEnum.TIMESTAMP
); break;
default:
}
model.setDtPostgreSQLEnum((DtPostgreSQLEnum)dtEnum);
return model;
}
},
;
private final String dbType;
/**
* 获取转换模型
* @param fromDtEnum 数据类型枚举
* @return 转换模型
* @throws DataException ignore
*/
public static <T extends DtInterface> DtConvertModel<T> getConvertModel(T fromDtEnum) throws DataException {
return choose(fromDtEnum.getDbType()).getModel(fromDtEnum);
}
/* ================================ 内部方法 ================================== */
/**
* 根据数据类型枚举获取对应转换模型
* @param dtEnum 数据类型枚举
* @return ignore
*/
protected <T extends DtInterface> DtConvertModel<T> getModel(T dtEnum){return null;}
/**
* 根据数据获取其转换规则枚举
* @param dbType 数据库类型
* @return 转换规则枚举
* @throws DataException ignore
*/
private static DtConvertEnum choose(String dbType) throws DataException {
for (DtConvertEnum dbMethod : DtConvertEnum.values()) {
if(dbMethod.getDbType().equals(dbType)){
return dbMethod;
}
}
throw new DataException(MsgCode.DB005.get());
}
/**
* 内部特殊转换
* @param model 转换模型
* @param convertDtEnums 特殊转换集合
*/
protected <T extends DtInterface> void convert(DtConvertModel<T> model, DtInterface... convertDtEnums){
try{
// 特殊的转换关系
for (DtInterface convertDtEnum : convertDtEnums) {
model.setDtEnum(convertDtEnum);
}
}catch (Exception e){
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,112 @@
package com.yunzhupaas.database.datatype.sync.enums;
import com.yunzhupaas.database.datatype.db.*;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 多个转换对应关系
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-05-31
*/
@Getter
@AllArgsConstructor
public enum DtConvertMultiEnum {
/**
* 整数型
*/
INTEGER(
new DtMySQLEnum[] { DtMySQLEnum.TINY_INT, DtMySQLEnum.SMALL_INT, DtMySQLEnum.INT, DtMySQLEnum.BIGINT, DtMySQLEnum.MEDIUM_INT },
new DtOracleEnum[] { DtOracleEnum.NUMBER },
new DtSQLServerEnum[] { DtSQLServerEnum.TINY_INT, DtSQLServerEnum.SMALL_INT, DtSQLServerEnum.INT, DtSQLServerEnum.BIGINT },
new DtDMEnum[] { DtDMEnum.TINY_INT, DtDMEnum.SMALL_INT, DtDMEnum.INT, DtDMEnum.BIGINT },
new DtKingbaseESEnum[] { DtKingbaseESEnum.TINY_INT, DtKingbaseESEnum.SMALL_INT, DtKingbaseESEnum.INTEGER, DtKingbaseESEnum.BIGINT },
new DtPostgreSQLEnum[] { DtPostgreSQLEnum.INT2, DtPostgreSQLEnum.INT4, DtPostgreSQLEnum.INT8 },
new DtDorisEnum[] { DtDorisEnum.TINY_INT, DtDorisEnum.SMALL_INT, DtDorisEnum.INT, DtDorisEnum.BIGINT }
),
/**
* 字符串、文本
*/
STRING(
new DtMySQLEnum[] { DtMySQLEnum.CHAR, DtMySQLEnum.VARCHAR, DtMySQLEnum.TINY_TEXT, DtMySQLEnum.TEXT, DtMySQLEnum.MEDIUM_TEXT, DtMySQLEnum.LONG_TEXT },
new DtOracleEnum[] { DtOracleEnum.CHAR, DtOracleEnum.NCHAR, DtOracleEnum.VARCHAR2, DtOracleEnum.NVARCHAR2 , DtOracleEnum.CLOB, DtOracleEnum.NCLOB },
new DtSQLServerEnum[] { DtSQLServerEnum.CHAR, DtSQLServerEnum.VARCHAR, DtSQLServerEnum.NVARCHAR, DtSQLServerEnum.VARCHAR_MAX, DtSQLServerEnum.TEXT, DtSQLServerEnum.N_TEXT, DtSQLServerEnum.IMAGE },
new DtDMEnum[] { DtDMEnum.CHAR, DtDMEnum.VARCHAR, DtDMEnum.VARCHAR2, DtDMEnum.TEXT , DtDMEnum.CLOB },
new DtKingbaseESEnum[] { DtKingbaseESEnum.CHAR, DtKingbaseESEnum.VARCHAR, DtKingbaseESEnum.TEXT },
new DtPostgreSQLEnum[] { DtPostgreSQLEnum.CHAR, DtPostgreSQLEnum.VARCHAR, DtPostgreSQLEnum.TEXT },
new DtDorisEnum[] { DtDorisEnum.CHAR, DtDorisEnum.VARCHAR, }
),
/**
* 浮点型
*/
FLOAT(
new DtMySQLEnum[] { DtMySQLEnum.FLOAT, DtMySQLEnum.DOUBLE },
new DtOracleEnum[] { DtOracleEnum.FLOAT },
new DtSQLServerEnum[] { DtSQLServerEnum.FLOAT },
new DtDMEnum[] { DtDMEnum.FLOAT, DtDMEnum.DOUBLE },
new DtKingbaseESEnum[] { DtKingbaseESEnum.FLOAT4, DtKingbaseESEnum.FLOAT8 },
new DtPostgreSQLEnum[] { DtPostgreSQLEnum.FLOAT4, DtPostgreSQLEnum.FLOAT8 },
new DtDorisEnum[] { DtDorisEnum.FLOAT, DtDorisEnum.DOUBLE }
),
/**
* 定点型
*/
DECIMAL(
new DtMySQLEnum[] { DtMySQLEnum.DECIMAL },
new DtOracleEnum[] { DtOracleEnum.NUMBER },
new DtSQLServerEnum[] { DtSQLServerEnum.DECIMAL },
new DtDMEnum[] { DtDMEnum.DECIMAL, DtDMEnum.DEC },
new DtKingbaseESEnum[] { DtKingbaseESEnum.NUMERIC },
new DtPostgreSQLEnum[] { DtPostgreSQLEnum.NUMERIC },
new DtDorisEnum[] { DtDorisEnum.DECIMAL }
),
/**
* 时间日期型
*/
DATE_TIME(
new DtMySQLEnum[] { DtMySQLEnum.YEAR, DtMySQLEnum.TIME, DtMySQLEnum.DATE, DtMySQLEnum.DATE_TIME, DtMySQLEnum.TIMESTAMP },
new DtOracleEnum[] { DtOracleEnum.DATE, DtOracleEnum.TIMESTAMP },
new DtSQLServerEnum[] { DtSQLServerEnum.DATE, DtSQLServerEnum.TIME, DtSQLServerEnum.DATE_TIME, DtSQLServerEnum.TIMESTAMP },
new DtDMEnum[] { DtDMEnum.DATE, DtDMEnum.DATE_TIME, DtDMEnum.TIME_STAMP, DtDMEnum.TIME },
new DtKingbaseESEnum[] { DtKingbaseESEnum.TIME, DtKingbaseESEnum.DATE, DtKingbaseESEnum.DATE_TIME, DtKingbaseESEnum.TIMESTAMP },
new DtPostgreSQLEnum[] { DtPostgreSQLEnum.TIME, DtPostgreSQLEnum.DATE, DtPostgreSQLEnum.TIMESTAMP },
new DtDorisEnum[] { DtDorisEnum.DATE, DtDorisEnum.DATE_TIME }
),
;
private final DtMySQLEnum[] dtMySQLEnums;
private final DtOracleEnum[] dtOracleEnums;
private final DtSQLServerEnum[] dtSQLServerEnums;
private final DtDMEnum[] dtDMEnums;
private final DtKingbaseESEnum[] dtKingbaseESEnums;
private final DtPostgreSQLEnum[] dtPostgreSQLEnums;
private final DtDorisEnum[] dtDorisEnums;
public static DtInterface[] getConverts(String dbType, DtConvertMultiEnum cEnum) throws Exception {
Method method = DtConvertMultiEnum.class.getMethod("getDt" + dbType + "Enums");
return (DtInterface[])method.invoke(cEnum);
}
public List<DtInterface> getAllConverts(){
List<DtInterface> list = new ArrayList<>();
list.addAll(Arrays.asList(this.getDtMySQLEnums()));
list.addAll(Arrays.asList(this.getDtOracleEnums()));
list.addAll(Arrays.asList(this.getDtSQLServerEnums()));
list.addAll(Arrays.asList(this.getDtDMEnums()));
list.addAll(Arrays.asList(this.getDtKingbaseESEnums()));
list.addAll(Arrays.asList(this.getDtPostgreSQLEnums()));
return list;
}
}

View File

@@ -0,0 +1,53 @@
package com.yunzhupaas.database.datatype.sync.model;
import com.yunzhupaas.database.datatype.db.*;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.lang.reflect.Method;
/**
* 数据类型互相转换模型
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-05-25
*/
@Data
@NoArgsConstructor
public class DtConvertModel<T> {
private T majorEnumClz;
/**
* 各数据库数据类型枚举
*/
private DtMySQLEnum dtMySQLEnum;
private DtOracleEnum dtOracleEnum;
private DtSQLServerEnum dtSQLServerEnum;
private DtDMEnum dtDMEnum;
private DtKingbaseESEnum dtKingbaseESEnum;
private DtPostgreSQLEnum dtPostgreSQLEnum;
private DtDorisEnum dtDorisEnum;
/**
* 获取数据类型枚举
* @param convertDbEncode 转换数据库类型
* @return ignore
* @throws Exception ignore
*/
public DtInterface getDtEnum(String convertDbEncode) throws Exception {
Method method = DtConvertModel.class.getMethod("getDt" + convertDbEncode + "Enum");
return (DtInterface) method.invoke(this);
}
public void setDtEnum(DtInterface dtEnum) throws Exception {
Method method = DtConvertModel.class.getMethod("setDt" + dtEnum.getDbType() + "Enum", DtInterface.getClz(dtEnum.getDbType()));
method.invoke(this, dtEnum);
}
}

View File

@@ -0,0 +1,160 @@
package com.yunzhupaas.database.datatype.sync.util;
import com.yunzhupaas.base.ActionResult;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.database.datatype.db.*;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.sync.enums.DtConvertMultiEnum;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.exception.DataException;
import java.util.*;
/**
* 测试数据类型完整性
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-01
*/
public class DtSyncTest {
public static void main(String[] args) throws Exception {
checkDataType(true, true, true);
}
public static ActionResult<Map<String, List<String>>> getConvertRules(String fromDbType, String toDbType) throws Exception{
Map<String, List<String>> map = new LinkedHashMap<>();
for (DtInterface dtInterface : DtInterface.getClz(fromDbType).getEnumConstants()) {
List<String> list = new LinkedList<>();
DtInterface[] allConverts = DtSyncUtil.getAllConverts(dtInterface, toDbType);
for (DtInterface allConvert : allConverts) {
list.add(allConvert.getDataType());
}
map.put(dtInterface.getDataType(), list);
}
return ActionResult.success(map);
}
public static ActionResult<Map<String, String>> getDefaultRules(String fromDbType, String toDbType) throws Exception{
Map<String, String> map = new LinkedHashMap<>();
for (DtInterface dtInterface : DtInterface.getClz(fromDbType).getEnumConstants()) {
DtInterface toFixCovert = DtSyncUtil.getToFixCovert(dtInterface, toDbType);
if(toFixCovert != null){
map.put(dtInterface.getDataType(), toFixCovert.getDataType());
}else {
throw new DataException(MsgCode.DB006.get());
}
}
return ActionResult.success(map);
}
/**
* 检测各数据库
* 数据类型对应关系是否缺失
*/
public static void checkDataType(Boolean oneFlag, Boolean multiFlag, Boolean mutualFlag) throws Exception {
// 1、检测一对一固定转换
if(oneFlag){
for (String fromDbEncode : DbBase.DB_ENCODES) {
for (String toDbEncode : DbBase.DB_ENCODES) {
if(fromDbEncode.equals(toDbEncode)){
continue;
}
System.out.println("================ " + fromDbEncode + "" + toDbEncode + " ==============");
Map<String, String> resultMap = getDefaultRules(fromDbEncode, toDbEncode).getData();
for (String key : resultMap.keySet()) {
System.out.println(key + getTab(key, fromDbEncode) + ": \t" + resultMap.get(key));
}
}
}
}
// 2、检测一对多选择转换
if(multiFlag){
System.out.println("\n\n");
for (String fromDbEncode : DbBase.DB_ENCODES) {
for (String toDbEncode : DbBase.DB_ENCODES) {
if(fromDbEncode.equals(toDbEncode)){
continue;
}
System.out.println("================ " + fromDbEncode + "" + toDbEncode + " ==============");
Map<String, List<String>> resultMap = getConvertRules(fromDbEncode, toDbEncode).getData();
for (String key : resultMap.keySet()) {
System.out.println(key + getTab(key, fromDbEncode) + ": \t" + resultMap.get(key).toString());
}
}
}
}
// 3、多对多
if(mutualFlag){
System.out.println("\n\n");
for (DtConvertMultiEnum value : DtConvertMultiEnum.values()) {
System.out.println("================ " + value + " ==============");
System.out.println(DbBase.MYSQL + "\t\t:" + Arrays.asList(value.getDtMySQLEnums()).toString());
System.out.println(DbBase.ORACLE + "\t\t:" + Arrays.asList(value.getDtOracleEnums()).toString());
System.out.println(DbBase.SQL_SERVER + "\t:" + Arrays.asList(value.getDtDMEnums()).toString());
System.out.println(DbBase.DM + "\t\t\t:" + Arrays.asList(value.getDtSQLServerEnums()).toString());
System.out.println(DbBase.KINGBASE_ES + "\t:" + Arrays.asList(value.getDtKingbaseESEnums()).toString());
System.out.println(DbBase.POSTGRE_SQL + "\t:" + Arrays.asList(value.getDtPostgreSQLEnums()).toString());
}
}
// 4、数据库类型
System.out.println("\n\n");
System.out.println("================ " + DbBase.MYSQL + " ==============");
for (DtMySQLEnum value : DtMySQLEnum.values()) {
System.out.println(value.getDataType());
}
System.out.println("================ " + DbBase.ORACLE + " ==============");
for (DtOracleEnum value : DtOracleEnum.values()) {
System.out.println(value.getDataType());
}
System.out.println("================ " + DbBase.SQL_SERVER + " ==============");
for (DtSQLServerEnum value : DtSQLServerEnum.values()) {
System.out.println(value.getDataType());
}
System.out.println("================ " + DbBase.DM + " ==============");
for (DtDMEnum value : DtDMEnum.values()) {
System.out.println(value.getDataType());
}
System.out.println("================ " + DbBase.KINGBASE_ES + " ==============");
for (DtKingbaseESEnum value : DtKingbaseESEnum.values()) {
System.out.println(value.getDataType());
}
System.out.println("================ " + DbBase.POSTGRE_SQL + " ==============");
for (DtPostgreSQLEnum value : DtPostgreSQLEnum.values()) {
System.out.println(value.getDataType());
}
// 5、数据库类型固定转换
// System.out.println("\n\n");
// for (DtConvertFixEnum value : DtConvertFixEnum.values()) {
// System.out.println("================ " + value.name() + " ==============");
// for (DtInterface dtMutualConvert : value.getDtMutualConverts()) {
// System.out.println(dtMutualConvert.getDbType() + "\t:" + dtMutualConvert.getDataType());
// }
// }
}
// 制表符
public static String getTab(String str, String dbType){
int num = str.length();
String tab = "\t\t";
if(DbBase.ORACLE.equals(dbType) || DbBase.DM.equals(dbType)){
if(num >= 8){
tab = "\t";
}
}else {
if(num > 8){
tab = "\t";
}
}
return tab;
}
}

View File

@@ -0,0 +1,75 @@
package com.yunzhupaas.database.datatype.sync.util;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.sync.enums.DtConvertEnum;
import com.yunzhupaas.database.datatype.sync.enums.DtConvertMultiEnum;
import com.yunzhupaas.exception.DataException;
import java.util.Map;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-05-31
*/
public class DtSyncUtil {
/**
* 返回数据类型转换结果
* @param fromDbType 被转化数据库类型
* @param toDbType 转换数据数库类型
* @param dataTypeName 转换数据类型
* @param convertRuleMap 转换规则
*/
public static DtInterface getToCovert(String fromDbType, String toDbType, String dataTypeName, Map<String, String> convertRuleMap) throws Exception {
// 存在规则类型配对
if(convertRuleMap != null) {
for (String key : convertRuleMap.keySet()) {
if (key.equalsIgnoreCase(dataTypeName)) {
String toDataType = convertRuleMap.get(key);
// 直接通过转换类型、数据库类型获取数据类型枚举
return DtInterface.newInstanceByDt(toDataType, toDbType);
}
}
}
// 获取被同步数据类型枚举
DtInterface formDtEnum = DtInterface.newInstanceByDt(dataTypeName, fromDbType);
if(formDtEnum != null){
return getToFixCovert(formDtEnum, toDbType);
}
throw new DataException(MsgCode.DB005.get(fromDbType, dataTypeName));
}
/**
* 获取固定转换后数据类型枚举
* @param fromDtEnum 被转换类型
* @param toDbType 转换数据库类型
* @return 数据类型枚举
* @throws DataException ignore
*/
public static DtInterface getToFixCovert(DtInterface fromDtEnum, String toDbType) throws Exception {
return DtConvertEnum.getConvertModel(fromDtEnum).getDtEnum(toDbType);
}
/**
* 获取所有可转换数据类型枚举集合
* @param fromDtEnum 被转换类型
* @param toDbType 转换数据库类型
* @return 数据类型枚举集合
* @throws Exception ignore
*/
public static DtInterface[] getAllConverts(DtInterface fromDtEnum, String toDbType) throws Exception {
for (DtConvertMultiEnum convertEnum : DtConvertMultiEnum.values()) {
if(convertEnum.getAllConverts().contains(fromDtEnum)){
return DtConvertMultiEnum.getConverts(toDbType, convertEnum);
}
}
return null;
}
}

View File

@@ -0,0 +1,28 @@
package com.yunzhupaas.database.datatype.utils;
import java.util.regex.Pattern;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-07
*/
public class DataTypeUtil {
/**
* 数据类型判断
*/
public static Boolean numFlag(String... nums){
for (String num : nums) {
if(!(Pattern.compile("^[-\\+]?[\\d]*$").matcher(num).matches())){
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,63 @@
package com.yunzhupaas.database.datatype.viewshow;
import com.yunzhupaas.database.datatype.db.DtMySQLEnum;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
/**
* 数据库数据类型向前端显示
* 转换规则
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-05-26
*/
public enum DtViewEnum {
/**
* 整型
*/
INT("int", new DtInterface[]{
DtMySQLEnum.INT,
}),
/**
* 长整型
*/
BIGINT("bigint", new DtInterface[]{
DtMySQLEnum.BIGINT,
}),
/**
* 字符串
*/
VARCHAR("varchar", new DtInterface[]{
DtMySQLEnum.CHAR,
DtMySQLEnum.VARCHAR,
}),
/**
* 文本
*/
TEXT("text", new DtInterface[]{
DtMySQLEnum.TINY_TEXT,
DtMySQLEnum.TEXT,
DtMySQLEnum.MEDIUM_TEXT,
DtMySQLEnum.LONG_TEXT,
}),
/**
* 浮点型
*/
DECIMAL("decimal", new DtInterface[]{
DtMySQLEnum.DECIMAL,
}),
/**
* 日期时间
*/
DATE_TIME("datetime", new DtInterface[]{
DtMySQLEnum.DATE,
DtMySQLEnum.DATE_TIME,
}),
;
DtViewEnum(String view, DtInterface[] dtEnums){}
}

View File

@@ -0,0 +1,118 @@
package com.yunzhupaas.database.datatype.viewshow;
import com.yunzhupaas.database.datatype.db.*;
import com.yunzhupaas.database.datatype.viewshow.constant.DtViewConst;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 字段类型枚举
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/6/29
*/
@Getter
@AllArgsConstructor
public enum ViewDataTypeEnum {
/* 如{主类型},{次类型}:({默认字符长度},{限制长度}(*:不允许设置))*/
/**
* 字符
*/
VARCHAR(
DtViewConst.VARCHAR,
DtMySQLEnum.VARCHAR,
DtOracleEnum.VARCHAR2,
DtSQLServerEnum.VARCHAR,
DtDMEnum.VARCHAR,
DtKingbaseESEnum.VARCHAR,
DtPostgreSQLEnum.VARCHAR
),
/**
* 日期时间
* 日期统一不指定长度
*/
DATE_TIME(
DtViewConst.DATE_TIME,
DtMySQLEnum.DATE_TIME,
DtOracleEnum.TIMESTAMP,
DtSQLServerEnum.DATE_TIME,
DtDMEnum.DATE_TIME,
DtKingbaseESEnum.TIMESTAMP,
DtPostgreSQLEnum.TIMESTAMP
),
/**
* 浮点
*/
DECIMAL(
DtViewConst.DECIMAL,
DtMySQLEnum.DECIMAL,
DtOracleEnum.NUMBER,
DtSQLServerEnum.DECIMAL,
DtDMEnum.DECIMAL,
DtKingbaseESEnum.NUMERIC,
DtPostgreSQLEnum.NUMERIC
),
/**
* 文本
*/
TEXT(
DtViewConst.TEXT,
DtMySQLEnum.TEXT,
DtOracleEnum.CLOB,
DtSQLServerEnum.TEXT,
DtDMEnum.TEXT,
DtKingbaseESEnum.TEXT,
DtPostgreSQLEnum.TEXT
),
/**
* 整型
* SqlServer、PostGre:int不能指定长度
*/
INT(
DtViewConst.INT,
DtMySQLEnum.INT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.INT,
DtDMEnum.INT,
DtKingbaseESEnum.INTEGER,
DtPostgreSQLEnum.INT4
),
/**
* 长整型
*/
BIGINT(
DtViewConst.BIGINT,
DtMySQLEnum.BIGINT,
DtOracleEnum.NUMBER,
DtSQLServerEnum.BIGINT,
DtDMEnum.BIGINT,
DtKingbaseESEnum.BIGINT,
DtPostgreSQLEnum.INT8
),
/**
* oracle数字类型
*/
ORACLE_NUMBER(
DtViewConst.ORACLE_NUMBER,
null,
DtOracleEnum.NUMBER,
null,
null,
null,
null
);
private final String viewFieldType;
private final DtMySQLEnum dtMySQLEnum;
private final DtOracleEnum dtOracleEnum;
private final DtSQLServerEnum dtSQLServerEnum;
private final DtDMEnum dtDMEnum;
private final DtKingbaseESEnum dtKingbaseESEnum;
private final DtPostgreSQLEnum dtPostgreSQLEnum;
}

View File

@@ -0,0 +1,54 @@
package com.yunzhupaas.database.datatype.viewshow.constant;
/**
* 前端数据类型标准
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/25
*/
public class DtViewConst {
/**
* 字符串
*/
public static final String VARCHAR = "varchar";
/**
* 日期时间
*/
public static final String DATE_TIME = "datetime";
/**
* 整型
*/
public static final String INT = "int";
/**
* 浮点
*/
public static final String DECIMAL = "decimal";
/**
* 长整型
*/
public static final String BIGINT = "bigint";
/**
* 文本
*/
public static final String TEXT = "text";
/**
* 显示默认
*/
public static final String DEFAULT = "默认";
/**
* Oracle 整型,长征
*/
public static final String ORACLE_NUMBER = "数字类型";
}

View File

@@ -0,0 +1,149 @@
package com.yunzhupaas.database.enums;
import com.yunzhupaas.database.source.DbBase;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version v3.4.6
* @copyrignt 深圳市乐程软件有限公司
* @date 2023-02-10
*/
@AllArgsConstructor
@Getter
public enum DbAliasEnum {
/* =========================== 表 ============================ */
/**
* 表大小
*/
TABLE_SIZE("F_TABLE_SIZE"),
/**
* 表名
*/
TABLE_NAME("F_TABLE_NAME"),
/**
* 表注释
*/
TABLE_COMMENT("F_TABLE_COMMENT"),
/**
* 类型
*/
TABLE_TYPE("F_TABLE_TYPE"),
/**
* 表总数
*/
TABLE_SUM("F_TABLE_SUM"),
/* =========================== 字段 ============================ */
/**
* 字段名
*/
FIELD("F_FIELD"),
/**
* 字段注释
*/
FIELD_COMMENT("F_FIELD_COMMENT"),
/**
* 字段默认值
*/
DEFAULT_VALUE("F_DEFAULT_VALUE"),
/**
* 自增
*/
AUTO_INCREMENT("F_AUTO_INCREMENT"),
/**
* 默认值(用于判断自增长)
*/
COLUMN_DEFAULT("F_COLUMN_DEFAULT"),
/**
* 自增
*/
IS_IDENTITY("F_IS_IDENTITY"),
/**
* 允空
*/
ALLOW_NULL("F_ALLOW_NULL"),
/**
* 主键
*/
PRIMARY_KEY("F_PRIMARY_KEY"),
/* ------------- 字段数据类型 ------------- */
/**
* 类型
*/
DATA_TYPE("F_DATA_TYPE"),
/**
* 以字符为单位的最大长度,适于二进制数据、字符数据,或者文本和图像数据。否则,返回 NULL
* 例如text、varcharint时为null其中varchar为可变长度text为固定长度
*/
CHAR_LENGTH("F_CHAR_LENGTH"),
/**
* precision:数值精度(整个数值的长度)
* 例如decimal
* 注意int(i)类型时无论i是多少NUMERIC_PRECISION都是10在填充0的时候i才会起作用
*/
NUM_PRECISION("F_NUM_PRECISION"),
/**
* scale:数值标度(小数部分的长度)
*/
NUM_SCALE("F_NUM_SCALE"),
/* =========================== 其他 ============================ */
/**
* 总数返回
*/
TOTAL_RECORD("totalRecord"),
/**
* 总数
*/
TOTAL("total"),
/**
* 自增主键触发器判断
*/
AUTO_TRIGGER("F_AUTO_TRIGGER"),
;
private final String alias;
public String getAlias(String dbEncode) {
return getAlias(dbEncode, alias);
}
public static String getAlias(String dbEncode, String keyWord){
if (DbBase.POSTGRE_SQL.equals(dbEncode)) {
//postgre别名只能输出小写Oracle只能大写
//Mysql默认SqlServer默认
return keyWord.toLowerCase();
} else if (DbBase.ORACLE.equals(dbEncode)) {
return keyWord.toUpperCase();
} else {
return keyWord;
}
}
}

View File

@@ -0,0 +1,75 @@
package com.yunzhupaas.database.enums;
/**
* 数据库 结构、参数 替换枚举 structure
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/6/29
*/
public enum ParamEnum {
/**
* 数据库
*/
DB_URL("{dbUrl}"),
/**
* 数据库名
*/
DB_NAME("{dbName}"),
/**
* 用户名
*/
USER_NAME("{userName}"),
/**
* 模式
* schema关键字,加前缀
*/
DB_SCHEMA("{dbSchema}"),
/**
* 表空间
*/
TABLE_SPACE("{tableSpace}"),
/**
* 表
*/
TABLE("{table}"),
/**
* 替换符
*/
SPLIT("split"),
/**
* 字段名
*/
FILED("{filed}"),
/**
* 字段长度
*/
DATA_LENGTH("{dataLength}"),
/**
* 字段注释
*/
COMMENT("{comment}")
;
/**
* 替换目标
*/
private final String target;
public String getTarget(){
return this.target;
}
public String getParamSign(){
return "?";
}
ParamEnum(String target){
this.target = target;
}
}

View File

@@ -0,0 +1,19 @@
package com.yunzhupaas.database.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version v3.4.3
* @copyrignt 深圳市乐程软件有限公司
* @date 2024-10-18
*/
@Mapper
public interface JdbcMapper extends BaseMapper<Object> {
}

View File

@@ -0,0 +1,117 @@
package com.yunzhupaas.database.model.dbfield;
import com.yunzhupaas.database.constant.DbAliasConst;
import com.yunzhupaas.database.datatype.model.DtModel;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.model.dbfield.base.DbFieldModelBase;
import com.yunzhupaas.database.model.dto.ModelDTO;
import com.yunzhupaas.database.model.interfaces.JdbcGetMod;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.util.DbTypeUtil;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.StringUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 表字段模型
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/12 15:31
*/
@Data
public class DbFieldModel extends DbFieldModelBase implements JdbcGetMod {
/**
* 数据类型传递对象
*/
private DtModelDTO dtModelDTO;
/**
* 早期注释叫法
*/
public String getFieldName(){
return super.getComment();
}
/**
* 数据类型格式化
* -- 创表
*/
public String formatDataTypeByView(String dbEncode) throws Exception {
DtModel dataTypeModel;
try{
// 1、前端指定数据类型转换
if(dtModelDTO == null) dtModelDTO = new DtModelDTO(getDataType(), getLength(), dbEncode, true);
// 2、标准数据类型对象转换
dataTypeModel = dtModelDTO.convert();
}catch (DataException e){
e.printStackTrace();
return getDataType();
}catch (Exception e){
e.printStackTrace();
// 准备异常时,使用默认可执行数据类型
dtModelDTO.setConvertType(DtModelDTO.FIX_VAL);
dataTypeModel = dtModelDTO.convert();
}
return dataTypeModel.formatDataType();
}
@Override
public void setMod(ModelDTO modelDTO) throws SQLException {
ResultSet result = modelDTO.getResultSet();
String dbEncode = modelDTO.getDbEncode();
// 根据不同的库进行字段处理
// ============== 字段数据类型 ===============
this.dataType = result.getString(DbAliasEnum.DATA_TYPE.getAlias(dbEncode));
// ============== 字段类型、长度 ===============
try{
DbTypeUtil.getEncodeDb(dbEncode).setPartFieldModel(this, result);
this.dtModelDTO.setConvertType(DtModelDTO.DB_VAL).setConvertTargetDtEnum(this.dtModelDTO.getDtEnum());
this.setLength(this.dtModelDTO.convert().getFormatLengthStr());
}catch (Exception e){
e.printStackTrace();
}
// ============== 字段名 ===============
if(this.field == null) this.field = result.getString(DbAliasEnum.FIELD.getAlias(dbEncode));
// ============== 字段注释 ===============
if(this.comment == null) this.comment = result.getString(DbAliasEnum.FIELD_COMMENT.getAlias(dbEncode));
// ============== 字段主键0:非主键、1主键 ==============
if(this.isPrimaryKey == null) this.isPrimaryKey = DbAliasConst.PRIMARY_KEY.getSign(result.getInt(DbAliasEnum.PRIMARY_KEY.getAlias(dbEncode)));
// ============== 字段允空0:空值 NULL、1:非空值 NOT NULL ==============
if(this.nullSign == null) this.nullSign = DbAliasConst.ALLOW_NULL.getSign(result.getInt(DbAliasEnum.ALLOW_NULL.getAlias(dbEncode)));
// ============== 自增(0:非自增 1:自增) ==============
try{
if(this.isAutoIncrement == null && DbBase.MYSQL.equals(dbEncode)){
this.isAutoIncrement = DbAliasConst.AUTO_INCREMENT.getSign(result.getInt(DbAliasEnum.AUTO_INCREMENT.getAlias(dbEncode)));
}
}catch (Exception ignore){}
if(this.isAutoIncrement == null && DbBase.DM.equals(dbEncode)) this.isAutoIncrement = result.getInt(DbAliasEnum.AUTO_INCREMENT.getAlias(dbEncode)) == 1;
if(DbBase.POSTGRE_SQL.equals(dbEncode) || DbBase.KINGBASE_ES.equals(dbEncode)){
String columnDefault = result.getString(DbAliasEnum.COLUMN_DEFAULT.getAlias(dbEncode));
String tableName = result.getString(DbAliasEnum.TABLE_NAME.getAlias(dbEncode));
if(StringUtil.isNotEmpty(columnDefault) && StringUtil.isNotEmpty(tableName) && this.field != null) {
this.isAutoIncrement = ("nextval(\'" + tableName + '_' + this.field + "_seq" + "\'::regclass)").equals(columnDefault);
}
}
if(DbBase.ORACLE.equals(dbEncode)){
if(this.isPrimaryKey){
this.isAutoIncrement = result.getInt(DbAliasEnum.AUTO_TRIGGER.getAlias(dbEncode)) > 0;
}
}
if(this.isAutoIncrement == null && DbBase.SQL_SERVER.equals(dbEncode)) this.isAutoIncrement = result.getInt(DbAliasEnum.IS_IDENTITY.getAlias(dbEncode)) == 1;
}
}

View File

@@ -0,0 +1,243 @@
package com.yunzhupaas.database.model.dbfield;
import com.yunzhupaas.database.constant.DbAliasConst;
import com.yunzhupaas.database.constant.RsColumnKeyConst;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
import com.yunzhupaas.database.model.dbfield.base.DbFieldModelBase;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.util.DbTypeUtil;
import lombok.Cleanup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* JDBC元数据表模型类型
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/06
*/
@Data
@NoArgsConstructor
public class JdbcColumnModel extends DbFieldModelBase {
/**
* 字段别名
*/
private String label;
/**
* 字段类型jdbc编码
*/
private Integer dtJdbcEncode;
/**
* 字段值
*/
private Object value;
/**
* 默认值
*/
protected String defaultValue;
/**
* 所属表名
*/
private String table;
/**
* 字段长度
*/
private String size;
/**
* 字符长度
* (charLength)
*/
private Long columnSize;
/**
* 标度
* (precision)
*/
private Integer numPrecRadix;
/**
* 精度
* (scale)
*/
private Integer decimalDigits;
/**
* 字段位置
*/
private String ordinalPosition;
/**
* 自增
*/
private String autoIncrement;
/**
* java对应数据类型
*/
private String javaDataType;
/* ================== 内部方法 ================= */
/**
* 字段结构
*/
public DbFieldModel convertDbFieldModel(String dbEncode) throws Exception {
DbFieldModel dbFieldModel = new DbFieldModel();
dbFieldModel.setField(getField());
dbFieldModel.setComment(getComment());
dbFieldModel.setDataType(getDataType());
dbFieldModel.setIsPrimaryKey(getIsPrimaryKey());
dbFieldModel.setIsAutoIncrement(convertIsAutoIncrement(dbEncode, getAutoIncrement()));
dbFieldModel.setNullSign(getNullSign());
dbFieldModel.setDefaultValue(getDefaultValue());
DtInterface dtEnum = DtInterface.newInstanceByDt(getDataType(), dbEncode);
assert dtEnum != null;
dbFieldModel.setDtModelDTO(new DtModelDTO(dtEnum, this.columnSize, Integer.parseInt(this.columnSize.toString()),
this.decimalDigits));
return dbFieldModel;
}
/**
* 自增判断
*/
private static Boolean convertIsAutoIncrement(String dbEncode, String sign) {
switch (dbEncode) {
case DbBase.MYSQL:
return sign.equalsIgnoreCase("YES");
case DbBase.ORACLE:
case DbBase.SQL_SERVER:
case DbBase.KINGBASE_ES:
case DbBase.DM:
case DbBase.POSTGRE_SQL:
// TODO 等待补充
default:
return false;
}
}
/* ================== 静态方法 ================= */
/**
* 获取字段元数据对象集合(所有字段)
* 注意:只能获取结构,无法获取值
*
* @param conn 数据连接
* @param table 表名
* @return ignore
* @throws SQLException ignore
*/
public static List<JdbcColumnModel> getList(Connection conn, String table, List<String> primaryFields)
throws Exception {
@Cleanup
ResultSet rs = getColumnMetaDateRs(conn, table);
List<JdbcColumnModel> list = new ArrayList<>();
while (rs.next()) {
JdbcColumnModel column = new JdbcColumnModel();
// 表名
column.setTable(rs.getString(RsColumnKeyConst.TABLE_NAME));
// 列名称:
column.setField(rs.getString(RsColumnKeyConst.COLUMN_NAME));
// java.sql.Types
column.setJavaDataType(rs.getString(RsColumnKeyConst.DATA_TYPE));
// 字段类型:
column.setDataType(rs.getString(RsColumnKeyConst.TYPE_NAME));
// 列的大小(标度)当字符类型表示CharLength数字类型表示Precision
column.setColumnSize(rs.getLong(RsColumnKeyConst.COLUMN_SIZE));
// 小数部分的位数(精度)
column.setDecimalDigits(rs.getInt(RsColumnKeyConst.DECIMAL_DIGITS));
// 描述列的注释:
column.setComment(rs.getString(RsColumnKeyConst.REMARKS));
// 该列的默认值:
column.setDefaultValue(rs.getString(RsColumnKeyConst.COLUMN_DEF));
// 列中的最大字节数:
column.setLength(rs.getString(RsColumnKeyConst.CHAR_OCTET_LENGTH));
// 列的索引:
column.setOrdinalPosition(rs.getString(RsColumnKeyConst.ORDINAL_POSITION));
// 是否允许使用 NULL
String isNull = rs.getString(RsColumnKeyConst.IS_NULLABLE);
column.setNullSign(isNull.equalsIgnoreCase("YES") ? DbAliasConst.NULL : DbAliasConst.NOT_NULL);
// 指示此列是否自动增加:(部分数据库不支持)
try {
column.setAutoIncrement(rs.getString(RsColumnKeyConst.IS_AUTOINCREMENT));
} catch (Exception ignore) {
}
// 是否是主键主键
column.setIsPrimaryKey(primaryFields.stream().anyMatch(o -> o.equalsIgnoreCase(column.getField())));
list.add(column);
}
return list;
}
/**
* 获取字段值相对元数据结果集
*
* @param rs 结果集
* @param isLowercase 别名大小写
* @param isValue 是否取值
* @return 字段集合
* @throws SQLException ignore
*/
public static List<JdbcColumnModel> getList(ResultSet rs, Boolean isLowercase, Boolean isValue)
throws SQLException {
ResultSetMetaData md = rs.getMetaData();
List<JdbcColumnModel> dbColumnModelList = new ArrayList<>();
for (int i = 1; i <= md.getColumnCount(); i++) {
JdbcColumnModel model = new JdbcColumnModel();
model.setTable(md.getTableName(i));
model.setField(md.getColumnName(i));
// 非空判断
model.setNullSign(md.isNullable(i) == 1 ? DbAliasConst.NULL : DbAliasConst.NOT_NULL);
model.setLabel(isLowercase ? md.getColumnLabel(i).toLowerCase() : md.getColumnLabel(i));
model.setDataType(md.getColumnTypeName(i));
model.setValue(isValue ? rs.getObject(i) : null);
dbColumnModelList.add(model);
}
return dbColumnModelList;
}
public void getOracle() {
}
/* ================================== 结果集 ================================== */
/**
* 从conn中获取数据库的表元数据
*
* @param conn 数据连接
* @return 返回表元数据
* @throws SQLException ignore
*/
public static ResultSet getColumnMetaDateRs(Connection conn, String table) throws Exception {
DatabaseMetaData dbMetaData = conn.getMetaData();
/*
* % 代表 *
* ResultSet rs = dbMetaData.getColumns(conn.getCatalog(), "%", table, "%");
*/
switch (DbTypeUtil.getDb(conn).getYunzhupaasDbEncode()) {
case DbBase.SQL_SERVER:
return dbMetaData.getColumns(conn.getCatalog(), "dbo", table, null);
case DbBase.POSTGRE_SQL:
return dbMetaData.getColumns(conn.getCatalog(), "public", table, null);
case DbBase.KINGBASE_ES:
return dbMetaData.getColumns(conn.getCatalog(), conn.getSchema(), table, null);
case DbBase.MYSQL:
default:
return dbMetaData.getColumns(conn.getCatalog(), dbMetaData.getUserName(), table, null);
}
}
}

View File

@@ -0,0 +1,59 @@
package com.yunzhupaas.database.model.dbfield.base;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-09
*/
@Data
public class DbFieldModelBase {
/**
* 数据长度
*/
protected String length;
/**
* 数据类型
*/
protected String dataType;
/**
* 字段名
*/
protected String field;
/**
* 是否主键
*/
protected Boolean isPrimaryKey;
/**
* 是否非空
* 允空非空及0与1较容易混淆故使用标识传作参数
*/
protected String nullSign;
/**
* 是否自增
*/
protected Boolean isAutoIncrement;
/**
* 注释
*/
protected String comment;
/**
* 默认值
*/
protected String defaultValue;
}

View File

@@ -0,0 +1,153 @@
package com.yunzhupaas.database.model.dbtable;
import com.yunzhupaas.database.constant.DbAliasConst;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.model.dbfield.DbFieldModel;
import com.yunzhupaas.database.model.dbtable.base.DbTableModelBase;
import com.yunzhupaas.database.model.dto.ModelDTO;
import com.yunzhupaas.database.model.interfaces.JdbcGetMod;
import io.swagger.v3.oas.annotations.media.Schema;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.util.StringUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
/**
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/06/18 By:YanYu
*/
@Data
@NoArgsConstructor
@ToString(callSuper=true)
@Accessors(chain = true)
public class DbTableFieldModel extends DbTableModelBase implements JdbcGetMod {
/**
* 标识
*/
@Schema(description = "标识")
private String id;
/**
* 数据源主键
*/
@Schema(description = "数据源主键")
private String dbLinkId;
/**
* 数据库编码
*/
@Schema(description = "数据库编码")
private String dbEncode;
/**
* 更新时新表名
*/
@Schema(description = "更新时新表名")
private String updateNewTable;
/**
* 更新前的旧表名
*/
@Schema(description = "更新前的旧表名")
private String updateOldTable;
/**
* 字段信息集合
*/
@Schema(description = "字段信息集合")
private List<DbFieldModel> dbFieldModelList;
/**
* 表是否存在信息
*/
@Schema(description = "表是否存在信息")
private Boolean hasTableData;
/**
* 类型 0-表 1-视图
*/
@Schema(description = "类型 0-表 1-视图")
private Integer type;
/**
* 前端注释
*/
public String getTableName(){
return getComment();
}
public void setTableName(String comment) {
super.setComment(comment);
}
public DbTableFieldModel(String table, String tableComment, List<DbFieldModel> dbFieldModelList){
this.setTable(table);
this.setComment(tableComment);
this.dbFieldModelList = dbFieldModelList;
}
@Override
public void setMod(ModelDTO modelDTO) {
try {
String dbEncode = modelDTO.getDbEncode();
ResultSet resultSet = modelDTO.getResultSet();
// ============== 表名 ==============
try {
String table = resultSet.getString(DbAliasEnum.TABLE_NAME.getAlias(dbEncode));
this.setTable(table);
} catch (Exception e) {
}
// ============== 表注释 ==============
try {
String tableComment = resultSet.getString(DbAliasEnum.TABLE_COMMENT.getAlias(dbEncode));
this.setComment(tableComment);
} catch (Exception e) {
}
// ============== 表总数 ==============
this.setSum("0");
try {
String sum = resultSet.getString(DbAliasEnum.TABLE_SUM.getAlias(dbEncode));
if(sum != null)
this.setSum(sum);
} catch (Exception e) {
}
this.setType(0);
try {
String tableType = resultSet.getString(DbAliasEnum.TABLE_TYPE.getAlias(dbEncode));
if (StringUtil.isNotEmpty(tableType)) {
if (dbEncode.equals(DbBase.SQL_SERVER) && tableType.equalsIgnoreCase("V ")) {
this.setType(1);
} else if ((dbEncode.equals(DbBase.ORACLE) || dbEncode.equals(DbBase.MYSQL)
|| dbEncode.equals(DbBase.DM) || dbEncode.equals(DbBase.POSTGRE_SQL) || dbEncode.equals(DbBase.KINGBASE_ES)
)
&& tableType.equalsIgnoreCase("VIEW")) {
this.setType(1);
}
}
} catch (Exception e) {
}
// ============== 表大小(由于部分数据库,版本取消了此功能)==============
/*String size = resultSet.getString(DbAliasEnum.TABLE_SIZE.AS());*/
this.setDbEncode(dbEncode);
// this.setSize(size);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,256 @@
package com.yunzhupaas.database.model.dbtable;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.constant.TableFieldsNameConst;
import com.yunzhupaas.database.constant.RsColumnKeyConst;
import com.yunzhupaas.database.constant.RsTableKeyConst;
import com.yunzhupaas.database.model.dbfield.DbFieldModel;
import com.yunzhupaas.database.model.dbfield.JdbcColumnModel;
import com.yunzhupaas.database.model.entity.DbLinkEntity;
import com.yunzhupaas.database.model.interfaces.DbSourceOrDbLink;
import com.yunzhupaas.database.util.ConnUtil;
import com.yunzhupaas.exception.DataException;
import lombok.Cleanup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* JDBC元数据字段模型类型
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/21
*/
@Data
@NoArgsConstructor
public class JdbcTableModel {
/**
* 数据库类型
*/
private String dbEncode;
/**
* 表名
*/
private String table;
/**
* 表类型
*/
private String tableType;
/**
* 表注释
*/
private String comment;
/**
* 主键字段
*/
private String primaryField;
/**
* 主键字段列表
*/
private List<String> primaryFields;
/**
* jdbc字段集合
*/
private List<JdbcColumnModel> jdbcColumnModelList;
/* ================== 构造方法 ================= */
public JdbcTableModel(DbLinkEntity dbLinkEntity, String table) throws Exception {
// @Cleanup Connection conn = PrepSqlDTO.getConn(dbLinkEntity);
@Cleanup Connection conn = ConnUtil.ConnCommon.getConnRemarks(dbLinkEntity);
@Cleanup ResultSet rs = getTableMetaDateRs(conn, table);
List<String> primaryKeys = getPrimaryKeys(conn, table).stream().sorted((o1, o2) -> {
return (TableFieldsNameConst.F_ID.equalsIgnoreCase(o2) || TableFieldsNameConst.ID.equalsIgnoreCase(o2)) ? 1 : 0;
}).collect(Collectors.toList());
if (rs.next()) {
this.dbEncode = dbLinkEntity.getDbType();
this.table = rs.getString(RsTableKeyConst.TABLE_NAME);
this.tableType = rs.getString(RsTableKeyConst.TABLE_TYPE);
this.comment = rs.getString(RsTableKeyConst.REMARKS);
this.primaryField = primaryKeys.isEmpty() ? null : primaryKeys.get(0);
this.primaryFields = primaryKeys;
this.jdbcColumnModelList = JdbcColumnModel.getList(conn, table, primaryFields);
}else {
throw new DataException(MsgCode.DB009.get(table));
}
}
/* ================== 内部方法 ================= */
public DbTableFieldModel convertDbTableFieldModel() throws Exception {
// 转换表
DbTableFieldModel dbTableFieldModel = new DbTableFieldModel();
dbTableFieldModel.setTable(this.table);
dbTableFieldModel.setComment(this.comment);
// 转换字段集合
List<DbFieldModel> dbFieldModelList = new ArrayList<>();
for (JdbcColumnModel jdbcColumnModel : this.jdbcColumnModelList) {
dbFieldModelList.add(jdbcColumnModel.convertDbFieldModel(this.dbEncode));
}
dbTableFieldModel.setDbFieldModelList(dbFieldModelList);
return dbTableFieldModel;
}
/* ================== 静态方法 ================= */
/**
* 获取表元数据对象(所有表)
* @param conn 数据连接
* @return ignore
* @throws SQLException ignore
*/
public static List<JdbcTableModel> getList(Connection conn) throws Exception {
@Cleanup ResultSet rs = getTableMetaDateRs(conn);
List<JdbcTableModel> list = new ArrayList<>();
while (rs.next()) {
JdbcTableModel jdbcTableModel = new JdbcTableModel();
jdbcTableModel.setTable(rs.getString(RsTableKeyConst.TABLE_NAME));
jdbcTableModel.setTableType(rs.getString(RsTableKeyConst.TABLE_TYPE));
jdbcTableModel.setComment(rs.getString(RsTableKeyConst.REMARKS));
jdbcTableModel.setJdbcColumnModelList(JdbcColumnModel.getList(conn, jdbcTableModel.getTable(), jdbcTableModel.getPrimaryFields()));
list.add(jdbcTableModel);
}
return list;
}
public static String getPrimary(DbSourceOrDbLink dbSourceOrDbLink, String table) throws SQLException {
@Cleanup Connection conn = ConnUtil.getConnOrDefault(dbSourceOrDbLink);
return getPrimary(conn, table);
}
/**
* 获取第一个主键, 排除某些主键
*/
public static String getPrimaryExculde(Connection conn, String table, String... excludeField) throws SQLException {
List<String> primaryKeys = getPrimaryKeys(conn, table);
if(!primaryKeys.isEmpty()){
for (String primaryKey : primaryKeys) {
boolean exlude = false;
for (String exclude : excludeField) {
if(primaryKey.equalsIgnoreCase(exclude)){
exlude = true;
break;
}
}
if(!exlude){
return primaryKey;
}
}
}
return "";
}
/**
* 获取第一个主键, 排除某些主键
*/
public static String getPrimaryExculde(DbSourceOrDbLink dbSourceOrDbLink, String table, String... excludeField) throws SQLException {
@Cleanup Connection conn = ConnUtil.getConnOrDefault(dbSourceOrDbLink);
return getPrimaryExculde(conn, table, excludeField);
}
/**
* 如有多个主键返回第一个主键
*/
public static String getPrimary(Connection conn, String table) throws SQLException {
List<String> primaryKeys = getPrimaryKeys(conn, table);
return primaryKeys.isEmpty()? "" : primaryKeys.get(0);
}
public static String getPrimaryIdFirst(DbSourceOrDbLink dbSourceOrDbLink, String table) throws SQLException {
@Cleanup Connection conn = ConnUtil.getConnOrDefault(dbSourceOrDbLink);
return getPrimaryIdFirst(conn, table);
}
/**
* 如有多个主键返回第一个主键, id优先返回
*/
public static String getPrimaryIdFirst(Connection conn, String table) throws SQLException {
List<String> primaryKeys = getPrimaryKeys(conn, table);
String findedId = "";
for (String primaryKey : primaryKeys) {
findedId = primaryKey;
// 联合主键优先返回f_id, id字段
if(TableFieldsNameConst.F_ID.equalsIgnoreCase(findedId) || TableFieldsNameConst.ID.equalsIgnoreCase(findedId)){
break;
}
}
return findedId;
}
/**
* 返回全部主键
*/
public static List<String> getPrimaryKeys(DbSourceOrDbLink dbSourceOrDbLink, String table) throws SQLException {
@Cleanup Connection conn = ConnUtil.getConnOrDefault(dbSourceOrDbLink);
return getPrimaryKeys(conn, table);
}
/**
* 返回全部主键
*/
public static List<String> getPrimaryKeys(Connection conn, String table) throws SQLException {
//获取表主键
@Cleanup ResultSet rs = conn.getMetaData().getPrimaryKeys(conn.getCatalog(), null, table);
List<String> primaryKeys = new ArrayList<>();
while(rs.next()){
primaryKeys.add(rs.getString(RsColumnKeyConst.COLUMN_NAME));
}
return primaryKeys;
}
/**
* 返回全部表的主键信息
* @return [{表名:主键名}]
*/
public static List<Map<String, String>> getPrimaryMapList(Connection conn, String schema) throws SQLException {
//获取表主键
@Cleanup ResultSet rs = conn.getMetaData().getPrimaryKeys(conn.getCatalog(), schema, null);
List<Map<String, String>> list = new ArrayList<>();
while (rs.next()){
Map<String, String> map = new HashMap<>();
map.put(rs.getString(RsColumnKeyConst.TABLE_NAME), rs.getString(RsColumnKeyConst.COLUMN_NAME));
list.add(map);
}
return list;
}
/* ================================== 结果集 ================================== */
/**
* 从conn中获取数据库的表元数据
* @param conn 数据连接
* @return 返回表元数据
* @throws SQLException ignore
*/
public static ResultSet getTableMetaDateRs(Connection conn, String table) throws SQLException {
return conn.getMetaData().getTables(conn.getCatalog(), null, table, new String[]{"TABLE"});
}
private static ResultSet getTableMetaDateRs(Connection conn) throws SQLException {
return getTableMetaDateRs(conn, null);
}
}

View File

@@ -0,0 +1,42 @@
package com.yunzhupaas.database.model.dbtable.base;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-09
*/
@Data
public class DbTableModelBase {
/**
* 表名
*/
private String table;
/**
* 表说明
*/
private String comment;
/**
* 大小
*/
private String size;
/**
* 数据条数
*/
private String sum;
/**
* 主键
*/
private String primaryKeyField;
}

View File

@@ -0,0 +1,35 @@
package com.yunzhupaas.database.model.dto;//package com.yunzhupaas.database.model.dto;
//
//import com.yunzhupaas.database.sql.model.DbStruct;
//import com.yunzhupaas.database.util.DataSourceUtil;
//import com.yunzhupaas.util.StringUtil;
//import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
//
///**
// * 数据源参数传输对象
// * -- 注意这里的参数dataSourceUtil是spring托管的全局唯一变量此数据传输对象防止数据源互串
// *
// * @author 云筑产品开发平台组
// * @version V3.2.0
// * @copyright 深圳市乐程软件有限公司
// * @date 2024/10/28
// */
//@Data
//public class DataSourceDTO extends DataSourceUtil{
//
// /**
// * 数据来源
// * 0自身创建 1配置 2数据连接
// */
// private Integer dataSourceFrom;
//
// /**
// * 表名
// */
// private String tableName;
//
//
//
//}

View File

@@ -0,0 +1,50 @@
package com.yunzhupaas.database.model.dto;
import com.yunzhupaas.database.model.interfaces.DbSourceOrDbLink;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.util.DataSourceUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.sql.Connection;
import java.util.function.Function;
/**
* 数据连接相关数据传输对象
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/12
*/
@Data
@NoArgsConstructor
public class DbConnDTO {
public DbConnDTO(DbBase dbBase, DataSourceUtil dbSource, Connection conn){
this.dbBase = dbBase;
this.dbSourceInfo = dbSource;
this.conn = conn;
}
/**
* 数据库基类
*/
private DbBase dbBase;
/**
* 数据源信息
*/
private DbSourceOrDbLink dbSourceInfo;
/**
* 数据连接
*/
private Connection conn;
private Function<String, Connection> connFunc;
}

View File

@@ -0,0 +1,54 @@
package com.yunzhupaas.database.model.dto;
import lombok.*;
import lombok.experimental.Accessors;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version v3.4.3
* @copyrignt 深圳市乐程软件有限公司
* @date 2024-10-20
*/
@Data
@Accessors(chain = true)
public class JdbcResult<R> {
/**
* 别名小写开关
*/
private Boolean isLowerCase = false;
/**
* 别名开关
*/
private Boolean isAlias = false;
/**
* 是查询结构还是查询值
*/
private Boolean isValue = true;
@Getter(value = AccessLevel.NONE)
@Setter(value = AccessLevel.NONE)
private MyFunction<JdbcResult<R>, R> func;
public JdbcResult(MyFunction<JdbcResult<R>, R> func){
this.func = func;
}
/**
* 在get的时候才进行查询操作
*/
public R get() throws Exception {
return this.func.apply(this);
}
@FunctionalInterface
public static interface MyFunction<T, R>{
R apply(T t) throws Exception;
}
}

View File

@@ -0,0 +1,40 @@
package com.yunzhupaas.database.model.dto;
import com.yunzhupaas.database.source.DbBase;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.sql.ResultSet;
/**
* 自定义模板参数对象
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/18
*/
@Data
public class ModelDTO {
public ModelDTO(ResultSet resultSet, String dbEncode){
this.resultSet = resultSet;
this.dbEncode = dbEncode;
}
public ModelDTO(ResultSet resultSet, DbBase dbBase){
this.resultSet = resultSet;
}
/**
* 结果集
*/
private ResultSet resultSet;
/**
* 数据基类
*/
private String dbEncode;
}

View File

@@ -0,0 +1,222 @@
package com.yunzhupaas.database.model.dto;
import com.yunzhupaas.database.model.entity.DbLinkEntity;
import com.yunzhupaas.database.util.ConnUtil;
import com.yunzhupaas.database.util.DataSourceUtil;
import com.yunzhupaas.database.util.DynamicDataSourceUtil;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.XSSEscape;
import com.yunzhupaas.util.context.SpringContext;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.function.Function;
/**
* Dynamic SQL参数传输对象
*
* @author 云筑产品开发平台组 GuanMengYu,YanYu
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/6/21
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class PrepSqlDTO {
private static DataSource getDataSource(){
return SpringContext.getBean(DataSource.class);
}
/**
* 数据连接方法接口函数
*/
public static Function<String, DbLinkEntity> DB_LINK_FUN;
/**
* conn连接
*/
// @Getter(value = AccessLevel.NONE)
// @Setter(value = AccessLevel.NONE)
// private Connection connection;
private DbLinkEntity dbLinkEntity;
private Connection preConnection;
/**
* 执行的sql语句用占位符代替
* 注意一个对象只对应一条SQL
*/
private String sql;
/**
* sql对应占位符的值
*/
private List<?> dataList = new ArrayList<>();
/**
* 批量参数
*/
private List<List<?>> multiDataList = new ArrayList<>();
/**
* SQL命令类型
*/
private String sqlCommandType;
public final static String INSERT = "insert";
public final static String DELETE = "delete";
public final static String UPDATE = "update";
public final static String SELECT = "select";
public final static String CRE_UP_DE = "creUpDe";
/**
* 获取切源后的数据源连接, 并清除自动切源记录
* @param dbLinkEntity
* @return
* @throws DataException
*/
public static Connection getConn(DbLinkEntity dbLinkEntity) throws DataException {
try{
return new PrepSqlDTO().withConn(dbLinkEntity).switchConn().getConnection();
}catch (SQLException d){
d.printStackTrace();
throw new DataException(d.getMessage());
}
}
/**
* 获取切源后的数据源连接, 并清除自动切源记录
* @return
* @throws SQLException
*/
private Connection getConnection() throws SQLException {
try {
Connection conn = DynamicDataSourceUtil.getCurrentConnection();
ConnUtil.switchConnectionSchema(conn);
return conn;
} finally{
DynamicDataSourceUtil.clearSwitchDataSource();
}
}
/**
* 该方法会自动将数据源切换至配置的目标源
* 调用完后若没有使用获取Connection方法需要手动调用 DynamicDataSourceUtil.clearSwitchDataSource()清除切源记录
*
* @return
* @throws SQLException
* @throws DataException
*/
public PrepSqlDTO switchConn() throws SQLException, DataException {
if(preConnection == null){
if (this.dbLinkEntity != null) {
if (this.dbLinkEntity.getId() != null && !"0".equals(this.dbLinkEntity.getId())) {
// 增加并切换数据源
DynamicDataSourceUtil.switchToDataSource(dbLinkEntity);
} else {
if (dbLinkEntity.getUrl() != null) {
DynamicDataSourceUtil.switchToDataSource(dbLinkEntity.getUserName(), dbLinkEntity.getPassword(), dbLinkEntity.getUrl(), dbLinkEntity.getDbType());
} else {
//切换只主库
DynamicDataSourceUtil.switchToDataSource(null);
}
}
} else {
throw new SQLException("dbLinkEntity数据库连接对象不能为空");
}
}
return this;
}
/* =============================== 构造方法 ============================== */
/**
* 无参数SQL语句
*/
public PrepSqlDTO(String sql){
this.sql = sql;
}
/**
* 快捷有参SQL语句
*/
public PrepSqlDTO(String sql, Object ...objs){
this.sql = sql;
this.dataList = Arrays.asList(objs);
}
/**
* 有参SQL语句
*/
public PrepSqlDTO(String sql, List<?> prepareDataList){
this.sql = sql;
this.dataList = prepareDataList;
}
// public PrepSqlDTO withConn(Connection conn){
// this.connection = conn;
// return this;
// }
public PrepSqlDTO withConn(String dbLinkId){
this.dbLinkEntity = DB_LINK_FUN.apply(dbLinkId);
return this;
}
public PrepSqlDTO withConn(DbLinkEntity dbLinkEntity){
this.dbLinkEntity = dbLinkEntity;
return this;
}
public PrepSqlDTO withConn(DataSourceUtil dataSourceUtil, String dbName){
this.dbLinkEntity = dataSourceUtil.init(dbName);
return this;
}
public PrepSqlDTO withConn(String user, String password, String url){
this.dbLinkEntity = new DbLinkEntity();
dbLinkEntity.setUserName(user);
dbLinkEntity.setPassword(password);
dbLinkEntity.setUrl(url);
return this;
}
public PrepSqlDTO withConn(Connection conn){
preConnection = conn;
return this;
}
/* =================== 同一条语句,多个组参数 ======================== */
public void addMultiData(List<?> prepareDataList){
this.multiDataList.add(prepareDataList);
}
public void addMultiData(Object ...objs){
this.multiDataList.add(Arrays.asList(objs));
}
public Map<String, Object> getMapParams() {
String sql = XSSEscape.escapeEmpty(this.sql);
int index = 0;
while (sql.contains("?") && index <= this.dataList.size()){
sql = sql.replaceFirst("\\?", "\\#{param_" + index + "}");
index++;
}
Map<String, Object> params = new HashMap<>();
params.put("sql", sql);
for (int i = 0 ; i < this.dataList.size() ; i++) {
Object dataObject = this.dataList.get(i);
params.put("param_" + i, dataObject);
}
return params;
}
}

View File

@@ -0,0 +1,54 @@
package com.yunzhupaas.database.model.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.yunzhupaas.database.model.dto.PrepSqlDTO;
import com.yunzhupaas.database.util.DataSourceUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* 数据连接
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2023/09/27
*/
@Data
@TableName("base_db_link")
@NoArgsConstructor
public class DbLinkEntity extends DataSourceUtil {
/**
* 连接主键
*/
@TableId("f_id")
private String id;
/**
* 连接名称
*/
@TableField("f_full_name")
private String fullName;
/**
* Oracle扩展开关
*/
@TableField("f_oracle_extend")
private Integer oracleExtend;
public static DbLinkEntity newInstance(String dbLinkId){
return PrepSqlDTO.DB_LINK_FUN.apply(dbLinkId);
}
public DbLinkEntity(String dbType){
super.setDbType(dbType);
}
}

View File

@@ -0,0 +1,24 @@
package com.yunzhupaas.database.model.interfaces;
import com.yunzhupaas.database.model.entity.DbLinkEntity;
import com.yunzhupaas.database.sql.model.DbStruct;
/**
* 数据源接口
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/28
*/
public interface DbSourceOrDbLink {
DbStruct getDbStruct();
DbLinkEntity init();
DbLinkEntity init(String dbName);
}

View File

@@ -0,0 +1,47 @@
package com.yunzhupaas.database.model.interfaces;
import com.yunzhupaas.exception.DataException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.4.2
* @copyright 深圳市乐程软件有限公司
* @date 2024/8/17 0017
*/
@FunctionalInterface
public interface JdbcCreUpDel<T> {
T execute() throws SQLException;
/**
* 参数配置
*/
static void setData(PreparedStatement preparedStatement, List<?> data) throws SQLException {
if(data != null){
for (int i = 0; i < data.size(); i++) {
preparedStatement.setObject(i + 1, data.get(i));
}
}
}
static <T>T get(Connection conn, JdbcCreUpDel<T> creUpDel) throws SQLException {
try{
conn.setAutoCommit(false);
T result= creUpDel.execute();
conn.commit();
return result;
} catch (SQLException e) {
//捕捉回滚操作
throw DataException.rollbackDataException(e, conn);
}
}
}

View File

@@ -0,0 +1,25 @@
package com.yunzhupaas.database.model.interfaces;
import com.yunzhupaas.database.model.dto.ModelDTO;
import java.sql.SQLException;
/**
* 数据模板接口
*
* @author 云筑产品开发平台组 YY
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/06
*/
public interface JdbcGetMod {
/**
* 设置自定义模板接口
* @param modelDTO 模板相关参数
* @throws SQLException ignore
*/
void setMod(ModelDTO modelDTO) throws SQLException;
}

View File

@@ -0,0 +1,19 @@
package com.yunzhupaas.database.model.page;
import com.yunzhupaas.base.Pagination;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 表数据页面对象
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/12 15:31
*/
@Data
public class DbTableDataForm extends Pagination {
private String field;
}

View File

@@ -0,0 +1,39 @@
package com.yunzhupaas.database.model.page;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* jdbc分页模型
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/11/3
*/
@Data
public class JdbcPageMod {
/**
* 页面大小
*/
private Integer pageSize;
/**
* 当前页
*/
private Integer currentPage;
/**
* 数据总条数
*/
private Integer totalRecord;
/**
* 数据
*/
private List<?> dataList;
}

View File

@@ -0,0 +1,27 @@
package com.yunzhupaas.database.model.superQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 高级查询
*
* @author 云筑产品开发平台组
* @version V3.4.2
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2022/5/31
*/
@Data
public class ConditionJsonModel {
private String field;
private String fieldValue;
private String symbol;
private String tableName;
private String yunzhupaasKey;
private String defaultValue;
private String attr;
/**
* 表单字段是否多选
*/
private boolean formMultiple;
}

View File

@@ -0,0 +1,15 @@
package com.yunzhupaas.database.model.superQuery;
import com.yunzhupaas.emnus.SearchMethodEnum;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class SuperJsonModel {
private Boolean authorizeLogic = true;
private String matchLogic = SearchMethodEnum.And.getSymbol();
private List<SuperQueryJsonModel> conditionList = new ArrayList<>();
}

View File

@@ -0,0 +1,26 @@
package com.yunzhupaas.database.model.superQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* 高级查询(代码生成器)
*
* @author 云筑产品开发平台组
* @version V3.4.2
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2022/6/23
*/
@Data
@AllArgsConstructor
public class SuperQueryConditionModel<T> {
private QueryWrapper<T> obj;
private List<ConditionJsonModel> conditionList;
private String matchLogic;
private String tableName;
}

View File

@@ -0,0 +1,23 @@
package com.yunzhupaas.database.model.superQuery;
import com.yunzhupaas.emnus.SearchMethodEnum;
import com.yunzhupaas.model.visualJson.FieLdsModel;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 高级查询
*
* @author 云筑产品开发平台组
* @version V3.1.0
* @copyright 深圳市乐程软件有限公司http://www.szlecheng.cn
* @date 2022/6/1
*/
@Data
public class SuperQueryJsonModel {
private String logic = SearchMethodEnum.And.getSymbol();
private List<FieLdsModel> groups = new ArrayList<>();
}

View File

@@ -0,0 +1,76 @@
package com.yunzhupaas.database.plugins;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationInterceptor;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.processor.DsProcessor;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.yunzhupaas.database.util.ConnUtil;
import com.yunzhupaas.database.util.DataSourceUtil;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.context.SpringContext;
import org.aopalliance.intercept.MethodInvocation;
public class DynamicGeneratorInterceptor extends DynamicDataSourceAnnotationInterceptor {
private DynamicRoutingDataSource dynamicRoutingDataSource;
private DefaultDataSourceCreator dataSourceCreator;
public DynamicGeneratorInterceptor(Boolean allowedPublicOnly, DsProcessor dsProcessor) {
super(allowedPublicOnly, dsProcessor);
}
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
try {
//是否继承动态生成源接口
if (methodInvocation.getThis() instanceof DynamicSourceGeneratorInterface) {
DS ds = methodInvocation.getThis().getClass().getAnnotation(DS.class);
if (ds != null && StringUtil.isNotEmpty(ds.value())) {
String datasourceName = ds.value();
DynamicSourceGeneratorInterface m = (DynamicSourceGeneratorInterface) methodInvocation.getThis();
String now = null;
try {
boolean invalid = true;
if (Boolean.TRUE.equals(m.cachedConnection())) {
if (dynamicRoutingDataSource == null) {
dynamicRoutingDataSource = SpringContext.getBean(DynamicRoutingDataSource.class);
dataSourceCreator = SpringContext.getBean(DefaultDataSourceCreator.class);
}
if (dynamicRoutingDataSource.getDataSources().containsKey(datasourceName)) {
// if (dynamicRoutingDataSource.getCurrentDataSources().get(datasourceName).getConnection().isValid(5)) {
//已存在当前动态数据源且数据源可用则不重新获取数据源配置
invalid = false;
// }
}
}
if (invalid) {
//重新生成动态数据源
//设置为默认数据源获取动态数据源信息
now = DynamicDataSourceContextHolder.push(null);
DataSourceUtil dataSource = m.getDataSource();
if (dataSource != null) {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
dataSourceProperty.setUsername(dataSource.getUserName());
dataSourceProperty.setPassword(dataSource.getPassword());
dataSourceProperty.setUrl(ConnUtil.getUrl(dataSource));
dataSourceProperty.setDriverClassName(dataSource.getDriver());
dynamicRoutingDataSource.addDataSource(datasourceName, dataSourceCreator.createDataSource(dataSourceProperty));
}
}
} finally {
if (now != null) {
DynamicDataSourceContextHolder.poll();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return methodInvocation.proceed();
}
}

View File

@@ -0,0 +1,29 @@
package com.yunzhupaas.database.plugins;
import com.yunzhupaas.database.util.DataSourceUtil;
/**
* 动态生成数据源接口
*
* @author 云筑产品开发平台组
* @copyright 深圳市乐程软件有限公司
*/
public interface DynamicSourceGeneratorInterface {
/**
* 获取当前需要切换的数据源配置
* @return
*/
DataSourceUtil getDataSource();
/**
* 是否缓存链接
* @return true: 不可用时重新获取, false: 每次都重新获取配置
*/
default boolean cachedConnection(){
return true;
}
}

View File

@@ -0,0 +1,40 @@
package com.yunzhupaas.database.plugins;
import cn.dev33.satoken.context.SaHolder;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.UserProvider;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.function.Consumer;
public interface ITenantPlugin {
default void printNoTenant(Consumer<NoTenantInfoModel> logConsumer){
String token = null;
String url = null;
String stack = null;
String userId = UserProvider.getUser().getTenantId();
try{
token = UserProvider.getToken();
url = SaHolder.getRequest().getRequestPath();
}catch (Exception e){}
if(url == null){
try{
stack = StringUtil.join(Thread.currentThread().getStackTrace(), "\n");
}catch (Exception e){}
}
logConsumer.accept(new NoTenantInfoModel(token, url, stack, userId));
}
}
@Data
@AllArgsConstructor
class NoTenantInfoModel{
private String token;
private String url;
private String stack;
private String userId;
}

View File

@@ -0,0 +1,76 @@
package com.yunzhupaas.database.plugins;
import com.yunzhupaas.constant.TableFieldsNameConst;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.schema.Column;
import java.util.List;
/**
* @author 云筑产品开发平台组
* @user N
* @copyright 深圳市乐程软件有限公司
* @date 2023/1/3 15:07
*/
public interface LogicDeleteHandler {
String DELETE_FIELD = TableFieldsNameConst.F_DELETE_MARK;
String DELETESQL = "UPDATE a SET " + DELETE_FIELD + " = 1";
/**
* 获取租户 ID 值表达式,只支持单个 ID 值
* <p>
*
* @return 租户 ID 值表达式
*/
Expression getNotDeletedValue();
/**
* 获取租户字段名
* <p>
* 默认字段名叫: tenant_id
*
* @return 租户字段名
*/
default String getLogicDeleteColumn() {
return DELETE_FIELD;
}
/**
* 获取租户字段名
* <p>
* 默认字段名叫: tenant_id
*
* @return 租户字段名
*/
default String getDeleteSql() {
return DELETESQL;
}
/**
* 根据表名判断是否忽略拼接多租户条件
* <p>
* 默认都要进行解析并拼接多租户条件
*
* @param tableName 表名
* @return 是否忽略, true:表示忽略false:需要解析并拼接多租户条件
*/
default boolean ignoreTable(String tableName) {
return false;
}
/**
* 忽略插入租户字段逻辑
*
* @param columns 插入字段
* @param tenantIdColumn 租户 ID 字段
* @return
*/
default boolean ignoreInsert(List<Column> columns, String tenantIdColumn) {
return columns.stream().map(Column::getColumnName).anyMatch(i -> i.equalsIgnoreCase(tenantIdColumn));
}
}

View File

@@ -0,0 +1,69 @@
package com.yunzhupaas.database.plugins;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.enums.DdConstants;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.dynamic.datasource.tx.TransactionContext;
import com.yunzhupaas.database.util.DynamicDataSourceUtil;
import com.yunzhupaas.util.TenantHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
/**
* 主库读写分离
*/
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@Slf4j
public class MyDefaultMasterSlaveAutoRoutingPlugin implements Interceptor {
protected DynamicRoutingDataSource dynamicDataSource;
public MyDefaultMasterSlaveAutoRoutingPlugin(DataSource dataSource){
this.dynamicDataSource = (DynamicRoutingDataSource) dataSource;
}
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 连接隔离模式多租户不处理, 当前非主数据源不处理, 未添加从库不处理
if (TenantHolder.isRemote()
|| !DynamicDataSourceUtil.isPrimaryDataSoure()
|| !dynamicDataSource.getGroupDataSources().containsKey(DdConstants.SLAVE)) {
return invocation.proceed();
}
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
String pushedDataSource = null;
try {
// 存在事务只使用主库
boolean hasTrans = TransactionSynchronizationManager.isActualTransactionActive();
if (!hasTrans) {
hasTrans = StringUtils.hasText(TransactionContext.getXID());
}
String dataSource = !hasTrans && SqlCommandType.SELECT == ms.getSqlCommandType() ? DdConstants.SLAVE : DynamicDataSourceUtil.dynamicDataSourceProperties.getPrimary();
pushedDataSource = DynamicDataSourceContextHolder.push(dataSource);
return invocation.proceed();
} finally {
if (pushedDataSource != null) {
DynamicDataSourceContextHolder.poll();
}
}
}
}

View File

@@ -0,0 +1,163 @@
package com.yunzhupaas.database.plugins;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.AbstractSqlInjector;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import com.yunzhupaas.config.ApplicationStartErrorCheck;
import com.yunzhupaas.config.ConfigValueUtil;
import com.yunzhupaas.util.ReflectionUtil;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* MyBatisPlus自定义方法实现
* 给默认方法新增IgnoreLogic结尾的方法用于操作已逻辑删除的数据
* @author 云筑产品开发平台组
* @user N
* @copyright 深圳市乐程软件有限公司
* @date 2023/02/06 10:29
*/
public class MyDefaultSqlInjector extends DefaultSqlInjector {
private AbstractSqlInjector sqlInjector;
private ConfigValueUtil configValueUtil;
public static final String ignoreLogicPrefix = "Ilg";
//MP、MPJ的MP方法名集合
public static final Set<String> IGNOREMETHOD = new HashSet<>();
public MyDefaultSqlInjector(ConfigValueUtil configValueUtil) {
this(null, configValueUtil);
}
public MyDefaultSqlInjector(ISqlInjector sqlInjector, ConfigValueUtil configValueUtil) {
this.configValueUtil = configValueUtil;
if (Objects.nonNull(sqlInjector) && sqlInjector instanceof AbstractSqlInjector) {
this.sqlInjector = (AbstractSqlInjector) sqlInjector;
}
}
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> innerMethod;
if (Objects.nonNull(sqlInjector)) {
innerMethod = methodFilter(sqlInjector.getMethodList(mapperClass, tableInfo));
} else {
innerMethod = methodFilter(super.getMethodList(mapperClass, tableInfo));
}
//将内置列表加入排除列表
return innerMethod;
}
@Override
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
// 多线程初始化Mybatis接口
ApplicationStartErrorCheck.getApplicationInitThreadPool().execute(() -> {
try {
super.inspectInject(builderAssistant, mapperClass);
} catch (Exception e) {
ApplicationStartErrorCheck.setStartError();
throw e;
}
});
}
private List<AbstractMethod> methodFilter(List<AbstractMethod> list) {
if (!configValueUtil.isEnableLogicDelete()) {
return list;
}
for (int i = 0; i < list.size(); i++) {
AbstractMethod abstractMethod = list.get(i);
abstractMethod = enhancerMethod(abstractMethod);
list.set(i, abstractMethod);
}
return list;
}
private AbstractMethod enhancerMethod(AbstractMethod method) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(method.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
handleAddMappedStatement(o, method, objects, methodProxy);
handleInject(o, method, objects, methodProxy);
return methodProxy.invokeSuper(o, objects);
}
});
return (AbstractMethod) enhancer.create(new Class[]{String.class}, new Object[]{ReflectionUtil.getFieldValue(method, "methodName")});
}
public void handleAddMappedStatement(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws IllegalAccessException {
//记录自带的方法
if (method.getName().equals("addMappedStatement") && objects.length > 1 && objects[1] instanceof String) {
String id = (String) objects[1];
Field builderAssistantField = ReflectionUtils.findField(AbstractMethod.class, "builderAssistant");
if (builderAssistantField != null) {
ReflectionUtils.makeAccessible(builderAssistantField);
MapperBuilderAssistant builderAssistant = (MapperBuilderAssistant) ReflectionUtils.getField(builderAssistantField, o);
String namespace = builderAssistant.getCurrentNamespace();
String msId = builderAssistant.applyCurrentNamespace(id, false);
Field ignoreCacheField = ReflectionUtils.findField(InterceptorIgnoreHelper.class, "IGNORE_STRATEGY_CACHE");
if (ignoreCacheField != null) {
ReflectionUtils.makeAccessible(ignoreCacheField);
Map<String, IgnoreStrategy> cache = (Map<String, IgnoreStrategy>) ignoreCacheField.get(null);
//将自带方法加入排除列表
IgnoreStrategy ignoreStrategy;
if (cache.containsKey(msId)) {
ignoreStrategy = cache.get(msId);
} else {
ignoreStrategy = IgnoreStrategy.builder().build();
if (cache.containsKey(namespace)) {
BeanUtil.copyProperties(cache.get(namespace), ignoreStrategy);
}
cache.put(msId, ignoreStrategy);
}
Map<String, Boolean> others = ignoreStrategy.getOthers();
if (others == null) {
others = new HashMap<>();
ignoreStrategy.setOthers(others);
}
others.putIfAbsent(ignoreLogicPrefix, true);
}
}
}
}
public void handleInject(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
String packageName = o.getClass().getPackage().getName();
//生成忽略逻辑删除的MP、MPJ的MP自带方法
if (method.getName().equals("inject") &&
(packageName.startsWith("com.baomidou.mybatisplus.core.injector.methods") || packageName.startsWith("com.github.yulichang.method.mp"))) {
TableInfo tableInfo = (TableInfo) objects[3];
if (tableInfo.isWithLogicDelete()) {
String methodName = (String) ReflectionUtil.getFieldValue(o, "methodName");
try {
ReflectionUtil.setFieldValue(tableInfo, "withLogicDelete", false);
ReflectionUtil.setFieldValue(o, "methodName", methodName + ignoreLogicPrefix);
methodProxy.invokeSuper(o, objects);
IGNOREMETHOD.add(methodName);
} finally {
ReflectionUtil.setFieldValue(o, "methodName", methodName);
ReflectionUtil.setFieldValue(tableInfo, "withLogicDelete", true);
}
}
}
}
}

View File

@@ -0,0 +1,75 @@
package com.yunzhupaas.database.plugins;
import com.baomidou.dynamic.datasource.tx.TransactionContext;
import com.yunzhupaas.database.util.ConnUtil;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.StringUtils;
import java.sql.Connection;
import java.sql.Savepoint;
import java.util.Properties;
/**
* @author 云筑产品开发平台组
* @user N
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/28 17:42
*/
@Intercepts(
{
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
}
)
public class MyDynamicDataSourceAutoRollbackInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
boolean hasTrans = TransactionSynchronizationManager.isActualTransactionActive();
if (!hasTrans) {
hasTrans = StringUtils.hasText(TransactionContext.getXID());
}
//Postgre Oracle Kingbase 连接报错后连接不可使用必须主动调用回滚才可以继续使用当前连接
Savepoint savepoint = null;
Connection connection = null;
if(hasTrans){
Executor executor = (Executor) invocation.getTarget();
Connection conn = executor.getTransaction().getConnection();
if(conn != null && !conn.getAutoCommit()){
connection = ConnUtil.getRealConnection(conn);
try {
savepoint = connection.setSavepoint();
}catch (Exception e){ }
}
}
try {
return invocation.proceed();
} catch (Throwable e) {
if(connection != null) {
if (savepoint != null) {
connection.rollback(savepoint);
}else{
connection.rollback();
}
}
throw e;
}
}
@Override
public Object plugin(Object target) {
return Interceptor.super.plugin(target);
}
@Override
public void setProperties(Properties properties) {
Interceptor.super.setProperties(properties);
}
}

View File

@@ -0,0 +1,88 @@
package com.yunzhupaas.database.plugins;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.dynamic.datasource.tx.ConnectionFactory;
import com.baomidou.dynamic.datasource.tx.ConnectionProxy;
import com.baomidou.dynamic.datasource.tx.TransactionContext;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.database.util.ConnUtil;
import com.yunzhupaas.database.util.DynamicDataSourceUtil;
import com.yunzhupaas.database.util.TenantDataSourceUtil;
import com.yunzhupaas.exception.ConnectDatabaseException;
import com.yunzhupaas.util.TenantHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* 自定义动态数据源类
* @author 云筑产品开发平台组
* @user N
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/8 16:06
*/
@Slf4j
public class MyDynamicRoutingDataSource extends DynamicRoutingDataSource {
public MyDynamicRoutingDataSource(List<DynamicDataSourceProvider> providers) {
super(providers);
}
@Override
public Connection getConnection() throws SQLException {
String xid = TransactionContext.getXID();
String ds = DynamicDataSourceContextHolder.peek();
if(DynamicDataSourceUtil.isPrimaryDataSoure() && TenantHolder.isRemote()){
//租户系统指定数据源, 如果当前源为主库 直接切换至指定源, 处理事务开启时Spring先行获取连接未切库问题
ds = TenantDataSourceUtil.getTenantAssignDataSourceMasterKeyName();
}
if (!StringUtils.hasText(xid)) {
return getMyDataSource(ds);
} else {
String tKey = !StringUtils.hasText(ds) ? "default" : ds;
ConnectionProxy connection = ConnectionFactory.getConnection(xid, tKey);
return connection == null ? getConnectionProxy(xid, tKey, getMyDataSource(ds)) : connection;
}
}
private Connection getMyDataSource(String dsKey) throws SQLException {
try{
DataSource dataSource = getDataSource(dsKey);
Connection connection = dataSource.getConnection();
ConnUtil.switchConnectionSchema(connection);
return connection;
}catch (SQLException e){
//移除运行中动态创建的数据源
//避免第三方数据库关闭后一直尝试重新创建连接
if (DynamicDataSourceUtil.containsLink(dsKey)) {
try {
//Druid数据源如果正在获取数据源 有概率连接创建线程无法停止
//if(((ItemDataSource) dataSource).getRealDataSource() instanceof DruidDataSource){
// ((DruidDataSource) ((ItemDataSource) dataSource).getRealDataSource()).setBreakAfterAcquireFailure(true);
//}
removeDataSource(dsKey);
} catch (Exception ee) {
log.error("关闭动态数据源【" + dsKey + "】失败", ee);
}
}else if(TenantHolder.isRemote()){
//租户指定数据源 连接失败全部移除
TenantDataSourceUtil.removeAllAssignDataSource();
}
throw new ConnectDatabaseException(MsgCode.DB302.get(), e);
}
}
private Connection getConnectionProxy(String xid, String ds, Connection connection) {
ConnectionProxy connectionProxy = new ConnectionProxy(connection, ds);
ConnectionFactory.putConnection(xid, ds, connectionProxy);
return connectionProxy;
}
}

View File

@@ -0,0 +1,340 @@
package com.yunzhupaas.database.plugins;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.baomidou.mybatisplus.extension.toolkit.PropertyMapper;
import com.yunzhupaas.database.util.IgnoreLogicDeleteHolder;
import com.yunzhupaas.util.StringUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.*;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.update.UpdateSet;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;
/**
* 逻辑删除插件
* @author 云筑产品开发平台组
* @user N
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/14 10:29
*/
@Data
@Slf4j
public class MyLogicDeleteInnerInterceptor extends TenantLineInnerInterceptor implements InnerInterceptor {
private LogicDeleteHandler logicDeleteHandler;
private static List<String> tableName = new ArrayList<>();
public MyLogicDeleteInnerInterceptor() {
super.setTenantLineHandler(new TenantLineHandler() {
@Override
public String getTenantIdColumn() {
return logicDeleteHandler.getLogicDeleteColumn();
}
@Override
public Expression getTenantId() {
return logicDeleteHandler.getNotDeletedValue();
}
});
}
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
//MybatisPlus自带方法不处理 兼容Plus、PlusJoin 见MyDefaultSqlInjector
if (InterceptorIgnoreHelper.willIgnoreOthersByKey(ms.getId(), MyDefaultSqlInjector.ignoreLogicPrefix)) return;
//代码中临时标记忽略逻辑删除不处理
if(IgnoreLogicDeleteHolder.isIgnoreLogicDelete()){
return;
}
//方法名包含ignorelogic不过滤
if (ms.getId().endsWith(MyDefaultSqlInjector.ignoreLogicPrefix)) return;
try {
if(boundSql.getSql().toLowerCase().contains(logicDeleteHandler.getLogicDeleteColumn().toLowerCase())){
//包含逻辑删除字段不处理
return;
}
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
mpBs.sql(parserSingle(mpBs.sql(), null));
} catch (Exception e){
//特殊语句解析失败
if(log.isDebugEnabled()){
log.debug("语句解析失败", e);
}
}
}
@Override
public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
//代码中临时标记忽略逻辑删除不处理
if(IgnoreLogicDeleteHolder.isIgnoreLogicDelete()){
return;
}
MappedStatement ms = mpSh.mappedStatement();
//MybatisPlus自带方法不处理 兼容Plus、PlusJoin 见MyDefaultSqlInjector
if (InterceptorIgnoreHelper.willIgnoreOthersByKey(ms.getId(), MyDefaultSqlInjector.ignoreLogicPrefix)) {
return;
}
//方法名包含ignorelogic不过滤
if (ms.getId().endsWith(MyDefaultSqlInjector.ignoreLogicPrefix)) return;
SqlCommandType sct = ms.getSqlCommandType();
if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
if(mpSh.mPBoundSql().sql().toLowerCase().contains(logicDeleteHandler.getLogicDeleteColumn().toLowerCase())){
//包含逻辑删除字段不处理
return;
}
try {
PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
mpBs.sql(parserMulti(mpBs.sql(), null));
} catch (Exception e){
//特殊语句解析失败
if(log.isDebugEnabled()){
log.debug("语句解析失败", e);
}
}
}
}
@Override
protected String processParser(Statement statement, int index, String sql, Object obj) {
if (logger.isDebugEnabled()) {
logger.debug("SQL to parse, SQL: " + sql);
}
if (statement instanceof Insert) {
this.processInsert((Insert) statement, index, sql, obj);
} else if (statement instanceof Select) {
this.processSelect((Select) statement, index, sql, obj);
} else if (statement instanceof Update) {
this.processUpdate((Update) statement, index, sql, obj);
} else if (statement instanceof Delete) {
//把删除语句替换为修改语句
statement = this.processDeleteToLogicDelete((Delete) statement, index, sql, obj);
}
sql = statement.toString();
if (logger.isDebugEnabled()) {
logger.debug("parse the finished SQL: " + sql);
}
return sql;
}
@Override
protected void processInsert(Insert insert, int index, String sql, Object obj) {
if (ignoreTable(insert.getTable().getName())) {
// 过滤退出执行
return;
}
List<Column> columns = insert.getColumns();
if (CollectionUtils.isEmpty(columns)) {
// 针对不给列名的insert 不处理
return;
}
String logicDeleteColumn = logicDeleteHandler.getLogicDeleteColumn();
if (logicDeleteHandler.ignoreInsert(columns, logicDeleteColumn)) {
// 针对已给出逻辑列的insert 不处理
return;
}
columns.add(new Column(logicDeleteColumn));
Expression notDeletedValue = logicDeleteHandler.getNotDeletedValue();
// fixed gitee pulls/141 duplicate update
List<UpdateSet> duplicateUpdateColumns = insert.getDuplicateUpdateSets();
if (CollectionUtils.isNotEmpty(duplicateUpdateColumns)) {
duplicateUpdateColumns.add(new UpdateSet(new Column(logicDeleteColumn), notDeletedValue));
}
Select select = insert.getSelect();
if (select instanceof PlainSelect) { //fix github issue 4998 修复升级到4.5版本的问题
this.processInsertSelect(select, (String) obj);
} else if (insert.getValues() != null) {
// fixed github pull/295
Values values = insert.getValues();
ExpressionList<Expression> expressions = (ExpressionList<Expression>) values.getExpressions();
if (expressions instanceof ParenthesedExpressionList) {
expressions.addExpression(notDeletedValue);
} else {
if (CollectionUtils.isNotEmpty(expressions)) {//fix github issue 4998 jsqlparse 4.5 批量insert ItemsList不是MultiExpressionList 了,需要特殊处理
int len = expressions.size();
for (int i = 0; i < len; i++) {
Expression expression = expressions.get(i);
if (expression instanceof ParenthesedExpressionList) {
((ParenthesedExpressionList<Expression>) expression).addExpression(notDeletedValue);
} else {
expressions.add(notDeletedValue);
}
}
} else {
expressions.add(notDeletedValue);
}
}
} else {
throw ExceptionUtils.mpe("Failed to process multiple-table update, please exclude the tableName or statementId");
}
}
/**
* update 语句处理
*/
@Override
protected void processUpdate(Update update, int index, String sql, Object obj) {
final Table table = update.getTable();
if (ignoreTable(table.getName())) {
// 过滤退出执行
return;
}
super.processUpdate(update, index, sql, obj);
}
/**
* delete 语句处理
*/
protected Statement processDeleteToLogicDelete(Delete delete, int index, String sql, Object obj) {
if (ignoreTable(delete.getTable().getName())) {
// 过滤退出执行
return delete;
}
Update updateStatement = null;
try {
updateStatement = (Update) CCJSqlParserUtil.parse(logicDeleteHandler.getDeleteSql());
} catch (JSQLParserException e) {
throw new RuntimeException(e);
}
updateStatement.setTable(delete.getTable());
updateStatement.setWhere(delete.getWhere());
return updateStatement;
}
/**
* 处理条件
*/
@Override
protected Expression builderExpression(Expression currentExpression, List<Table> tables, final String whereSegment) {
// 没有表需要处理直接返回
if (CollectionUtils.isEmpty(tables)) {
return currentExpression;
}
// 过滤不处理的表
tables = tables.stream()
.filter(x -> !ignoreTable(x.getName()))
.collect(Collectors.toList());
// 构造每张表的条件
List<Expression> expressions = tables.stream()
.map(item -> buildTableExpression(item, currentExpression, whereSegment))
.filter(Objects::nonNull)
.collect(Collectors.toList());
// 没有表需要处理直接返回
if (CollectionUtils.isEmpty(expressions)) {
return currentExpression;
}
// 注入的表达式
Expression injectExpression = expressions.get(0);
// 如果有多表,则用 and 连接
if (expressions.size() > 1) {
for (int i = 1; i < expressions.size(); i++) {
injectExpression = new AndExpression(injectExpression, expressions.get(i));
}
}
if (currentExpression == null) {
return injectExpression;
}
if (currentExpression instanceof OrExpression) {
return new AndExpression(new ParenthesedExpressionList<>(currentExpression), injectExpression);
} else {
return new AndExpression(currentExpression, injectExpression);
}
}
protected Expression getLogicExpression(Expression column, Expression val){
if(val.toString().equalsIgnoreCase("null")){
IsNullExpression isNullExpression = new IsNullExpression();
isNullExpression.setLeftExpression(column);
isNullExpression.setNot(false);
return isNullExpression;
}else {
return new EqualsTo(column, val);
}
}
/**
* 逻辑字段别名设置
* <p>F_DELETEMARK 或 tableAlias.F_DELETEMARK</p>
*
* @param table 表对象
* @return 字段
*/
@Override
protected Column getAliasColumn(Table table) {
StringBuilder column = new StringBuilder();
// 为了兼容隐式内连接,没有别名时条件就需要加上表名
if (table.getAlias() != null) {
column.append(table.getAlias().getName());
} else {
column.append(table.getName());
}
column.append(StringPool.DOT).append(logicDeleteHandler.getLogicDeleteColumn());
return new Column(column.toString());
}
private boolean ignoreTable(String table){
if(StringUtil.isEmpty(table) || logicDeleteHandler.ignoreTable(table)){
return true;
}
TableInfo tableInfo = TableInfoHelper.getTableInfo(table);
//无实体暂不执行, 非逻辑删除表不执行
if(tableInfo != null){
return !tableInfo.isWithLogicDelete();
}
return true;
}
@Override
public void setProperties(Properties properties) {
PropertyMapper.newInstance(properties).whenNotBlank("logicDeleteHandler",
ClassUtils::newInstance, this::setLogicDeleteHandler);
}
@Override
public Expression buildTableExpression(Table table, Expression where, String whereSegment) {
if(ignoreTable(table.getName())){
return null;
}
return getLogicExpression(this.getAliasColumn(table), logicDeleteHandler.getNotDeletedValue());
}
}

View File

@@ -0,0 +1,92 @@
package com.yunzhupaas.database.plugins;
import com.baomidou.mybatisplus.core.override.MybatisMapperProxy;
import com.yunzhupaas.base.mapper.SuperMapper;
import com.yunzhupaas.database.util.IgnoreLogicDeleteHolder;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.ibatis.session.SqlSession;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 开启逻辑删除之后, 调用Mapper方法时, 若设置忽略逻辑删除强制替换调用的方法
* 可调用mapper.setIgnoreLogicDelete service.setIgnoreLogicDelete 设置忽略标记
* 调用mapper.clearIgnoreLogicDelete service.clearIgnoreLogicDelete 清除忽略标记
* 例:
* mapper.setIgnoreLogicDelete();
* mapper.list(); //调用list方法会动态替换为listIgnoreLogicDelete方法
* mapper.clearIgnoreLogicDelete();
*
* @see MyDefaultSqlInjector 生成Mapper实现类的非逻辑删除版本SQL代码
* @see IgnoreLogicDeleteHolder 存储是否暂时忽略逻辑删除标记
*/
@Configuration
@ConditionalOnProperty(prefix = "config", name = "EnableLogicDelete", havingValue = "true", matchIfMissing = false)
public class MyLogicServiceBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
Object obj = BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
if(obj != null && SuperMapper.class.isAssignableFrom(obj.getClass())){
ProxyFactory factory = new ProxyFactory();
factory.setTarget(obj);
factory.addAdvice(new MethodInterceptor() {
@Nullable
@Override
public Object invoke(@Nonnull MethodInvocation invocation) throws Throwable {
if(IgnoreLogicDeleteHolder.isIgnoreLogicDelete()) {
try {
Method invokeMethod = invocation.getMethod();
// 非Object自带方法 且是MP、MPJ的自带方法
if (!Object.class.equals(invokeMethod.getDeclaringClass()) && MyDefaultSqlInjector.IGNOREMETHOD.contains(invokeMethod.getName())) {
if (invocation.getThis() != null && Proxy.isProxyClass(invocation.getThis().getClass())) {
InvocationHandler proxyHandler = Proxy.getInvocationHandler(invocation.getThis());
if(proxyHandler instanceof MybatisMapperProxy) {
//从MybatisMapperProxy中获取原Mapper接口
Field mapperInterfaceField = ReflectionUtils.findField(proxyHandler.getClass(), "mapperInterface");
Field sqlSessionField = ReflectionUtils.findField(proxyHandler.getClass(), "sqlSession");
if (mapperInterfaceField != null && sqlSessionField != null) {
ReflectionUtils.makeAccessible(mapperInterfaceField);
ReflectionUtils.makeAccessible(sqlSessionField);
Class<?> mapperInterface = (Class<?>) ReflectionUtils.getField(mapperInterfaceField, proxyHandler);
SqlSession sqlSession = (SqlSession) ReflectionUtils.getField(sqlSessionField, proxyHandler);
if (mapperInterface != null && sqlSession != null) {
Method newInvokeMathod = ReflectionUtils.findMethod(mapperInterface, invocation.getMethod().getName() + MyDefaultSqlInjector.ignoreLogicPrefix, invokeMethod.getParameterTypes());
if(newInvokeMathod != null){
Field methodField = ReflectionUtils.findField(invocation.getClass(), "method");
if (methodField != null) {
//直接替换Method Mybatis调用根据方法名称获取对应的SQL
ReflectionUtils.makeAccessible(methodField);
ReflectionUtils.setField(methodField, invocation, newInvokeMathod);
}
}
}
}
}
}
}
} catch (Exception e){
e.printStackTrace();
}
}
return invocation.proceed();
}
});
return factory.getProxy();
}
return obj;
}
}

View File

@@ -0,0 +1,161 @@
package com.yunzhupaas.database.plugins;
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.core.toolkit.TableNameParser;
import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.database.util.DataSourceUtil;
import com.yunzhupaas.database.util.DynamicDataSourceUtil;
import com.yunzhupaas.database.util.NotTenantPluginHolder;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.TenantHolder;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Schema模式租户插件
* @author 云筑产品开发平台组
* @user N
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/14 10:35
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class MySchemaInnerInterceptor extends DynamicTableNameInnerInterceptor implements ITenantPlugin {
private Runnable hook;
public void setHook(Runnable hook) {
this.hook = hook;
}
/**
* 表名处理器,是否处理表名的情况都在该处理器中自行判断
*/
private TableNameHandler tableNameHandler;
@Autowired
private DataSourceUtil dataSourceUtil;
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
if(TenantHolder.getLocalTenantCache() == null){
printNoTenant(v -> log.warn("未获取到线程租户ID, 跳过切库, {}, {}, {}, {}", v.getUserId(), v.getUrl(), v.getToken(), v.getStack()));
//未设置租户信息不允许操作数据库
throw new DataException(MsgCode.LOG113.get());
}
//租户指定数据源不处理
if (!TenantHolder.getLocalTenantCache().isSchema()) {
return;
}
if (NotTenantPluginHolder.isNotSwitch()) {
NotTenantPluginHolder.clearNotSwitchFlag();
return;
}
//非主库不切库
if(!DynamicDataSourceUtil.isPrimaryDataSoure()){
return;
}
//不绑定数据源的接口不切库
/*if(NotTenantPluginHolder.isNotSwitchAlways()){
return;
}*/
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
if (!InterceptorIgnoreHelper.willIgnoreDynamicTableName(ms.getId())) {
// 非忽略执行
mpBs.sql(this.changeTable(mpBs.sql()));
}
}
@Override
public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
if(TenantHolder.getLocalTenantCache() == null){
printNoTenant(v -> log.warn("未获取到线程租户ID, 跳过切库, {}, {}, {}, {}", v.getUserId(), v.getUrl(), v.getToken(), v.getStack()));
//未设置租户信息不允许操作数据库
throw new DataException(MsgCode.LOG113.get());
}
//租户指定数据源不处理
if (!TenantHolder.getLocalTenantCache().isSchema()) {
return;
}
if (NotTenantPluginHolder.isNotSwitch()) {
NotTenantPluginHolder.clearNotSwitchFlag();
return;
}
//非主库不切库
if(!DynamicDataSourceUtil.isPrimaryDataSoure()){
return;
}
//不绑定数据源的接口不切库
/*if(NotTenantPluginHolder.isNotSwitchAlways()){
return;
}*/
PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
MappedStatement ms = mpSh.mappedStatement();
SqlCommandType sct = ms.getSqlCommandType();
if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
if (!InterceptorIgnoreHelper.willIgnoreDynamicTableName(ms.getId())) {
// 非忽略执行
PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
mpBs.sql(this.changeTable(mpBs.sql()));
/*
//只有修改、新增、删除数据才切库
//先保留代码看后续需求
SQLStatement sqlStatement = SQLParserUtils.createSQLStatementParser(mpBs.sql(), DbTypeUtil.getDb(dataSourceUtil).getDruidDbType()).parseStatement();
if (sqlStatement instanceof SQLSelectStatement
|| sqlStatement instanceof SQLUpdateStatement
|| sqlStatement instanceof SQLInsertStatement
|| sqlStatement instanceof SQLDeleteStatement) {
mpBs.sql(this.changeTable(mpBs.sql()));
}*/
}
}
}
public String changeTable(String sql) {
ExceptionUtils.throwMpe(null == tableNameHandler, "Please implement TableNameHandler processing logic");
TableNameParser parser = new TableNameParser(sql);
List<TableNameParser.SqlToken> names = new ArrayList<>();
parser.accept(names::add);
StringBuilder builder = new StringBuilder();
int last = 0;
for (TableNameParser.SqlToken name : names) {
int start = name.getStart();
if (start != last) {
builder.append(sql, last, start);
builder.append(tableNameHandler.dynamicTableName(sql, name.getValue()));
}
last = name.getEnd();
}
if (last != sql.length()) {
builder.append(sql.substring(last));
}
if (hook != null) {
hook.run();
}
return builder.toString();
}
}

View File

@@ -0,0 +1,159 @@
package com.yunzhupaas.database.plugins;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.database.util.DynamicDataSourceUtil;
import com.yunzhupaas.database.util.NotTenantPluginHolder;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.TenantHolder;
import jodd.util.StringPool;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.*;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* Column模式租户插件
* @author 云筑产品开发平台组
* @user N
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/14 10:29
*/
@Slf4j
public class MyTenantLineInnerInterceptor extends TenantLineInnerInterceptor implements ITenantPlugin {
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
if(TenantHolder.getLocalTenantCache() == null){
printNoTenant(v -> log.warn("未获取到线程租户ID, 跳过切库, {}, {}, {}, {}", v.getUserId(), v.getUrl(), v.getToken(), v.getStack()));
//未设置租户信息不允许操作数据库
throw new DataException(MsgCode.LOG113.get());
}
//租户指定数据源不处理
if (!TenantHolder.getLocalTenantCache().isColumn()) {
return;
}
if (NotTenantPluginHolder.isNotSwitch()) {
NotTenantPluginHolder.clearNotSwitchFlag();
return;
}
//非主库不切库
if(!DynamicDataSourceUtil.isPrimaryDataSoure()){
return;
}
//不绑定数据源的接口不切库
/*if(NotTenantPluginHolder.isNotSwitchAlways()){
return;
}*/
try {
super.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
} catch (Exception e){
//特殊语句解析失败
if(log.isDebugEnabled()){
log.debug("语句解析失败", e);
}
}
}
@Override
public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
if(TenantHolder.getLocalTenantCache() == null){
printNoTenant(v -> log.warn("未获取到线程租户ID, 跳过切库, {}, {}, {}, {}", v.getUserId(), v.getUrl(), v.getToken(), v.getStack()));
//未设置租户信息不允许操作数据库
throw new DataException(MsgCode.LOG113.get());
}
//租户指定数据源不处理
if (!TenantHolder.getLocalTenantCache().isColumn()) {
return;
}
if (NotTenantPluginHolder.isNotSwitch()) {
NotTenantPluginHolder.clearNotSwitchFlag();
return;
}
//非主库不切库
if(!DynamicDataSourceUtil.isPrimaryDataSoure()){
return;
}
//不绑定数据源的接口不切库
/*if(NotTenantPluginHolder.isNotSwitchAlways()){
return;
}*/
try {
super.beforePrepare(sh, connection, transactionTimeout);
} catch (Exception e){
//特殊语句解析失败
if(log.isDebugEnabled()){
log.debug("语句解析失败", e);
}
}
}
@Override
protected Column getAliasColumn(Table table) {
return getAliasColumnWithFromItem(table);
}
protected Column getAliasColumnWithFromItem(FromItem table) {
StringBuilder column = new StringBuilder();
if (table.getAlias() != null) {
column.append(table.getAlias().getName());
}else{
if(table instanceof Table){
column.append(((Table)table).getName());
}
}
column.append(StringPool.DOT).append(super.getTenantLineHandler().getTenantIdColumn());
return new Column(column.toString());
}
protected void appendSelectItem(List<SelectItem<?>> selectItems, FromItem from) {
if (CollectionUtils.isEmpty(selectItems)) {
return;
}
if (selectItems.size() == 1) {
SelectItem item = selectItems.get(0);
Expression expression = item.getExpression();
if (expression instanceof AllColumns) {
return;
}
}
// 改
selectItems.add(new SelectItem<>(getAliasColumnWithFromItem(from)));
}
@Override
protected void processInsertSelect(Select selectBody, final String whereSegment) {
if (selectBody instanceof PlainSelect) {
PlainSelect plainSelect = (PlainSelect)selectBody;
FromItem fromItem = plainSelect.getFromItem();
if (fromItem instanceof Table) {
this.processPlainSelect(plainSelect, whereSegment);
// 改
this.appendSelectItem(plainSelect.getSelectItems(), fromItem);
} else if (fromItem instanceof Select) {
Select subSelect = (Select)fromItem;
// 改
this.appendSelectItem(plainSelect.getSelectItems(), fromItem);
this.processInsertSelect(subSelect, whereSegment);
}
} else if (selectBody instanceof ParenthesedSelect) {
ParenthesedSelect parenthesedSelect = (ParenthesedSelect)selectBody;
this.processInsertSelect(parenthesedSelect.getSelect(), whereSegment);
}
}
}

View File

@@ -0,0 +1,76 @@
package com.yunzhupaas.database.plugins;
import cn.hutool.core.text.StrPool;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.enums.DdConstants;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.dynamic.datasource.tx.TransactionContext;
import com.yunzhupaas.database.util.DynamicDataSourceUtil;
import com.yunzhupaas.util.TenantHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
import java.util.Optional;
/**
* 租户连接模式读写分离
*
* @author TaoYu
* @since 2.5.1
*/
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@Slf4j
public class MyTenantMasterSlaveAutoRoutingPlugin implements Interceptor {
protected DynamicRoutingDataSource dynamicDataSource;
public MyTenantMasterSlaveAutoRoutingPlugin(DataSource dataSource){
this.dynamicDataSource = (DynamicRoutingDataSource) dataSource;
}
@Override
public Object intercept(Invocation invocation) throws Throwable {
if (TenantHolder.getLocalTenantCache() == null
|| !TenantHolder.getLocalTenantCache().isRemote()
|| !DynamicDataSourceUtil.isPrimaryDataSoure()) {
return invocation.proceed();
}
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
String pushedDataSource = null;
try {
String tenantId = Optional.ofNullable(TenantHolder.getLocalTenantCache().getEnCode()).orElse("");
String masterKey = tenantId + StrPool.DASHED +DdConstants.MASTER;
String slaveKey = tenantId + StrPool.DASHED +DdConstants.SLAVE;
// 存在事务只使用主库
boolean hasTrans = TransactionSynchronizationManager.isActualTransactionActive();
if (!hasTrans) {
hasTrans = StringUtils.hasText(TransactionContext.getXID());
}
// 判断切库
String dataSource = SqlCommandType.SELECT == ms.getSqlCommandType() ? slaveKey :masterKey;
if (hasTrans || !dynamicDataSource.getGroupDataSources().containsKey(dataSource)) {
dataSource = masterKey;
}
pushedDataSource = DynamicDataSourceContextHolder.push(dataSource);
return invocation.proceed();
} finally {
if (pushedDataSource != null) {
DynamicDataSourceContextHolder.poll();
}
}
}
}

View File

@@ -0,0 +1,56 @@
package com.yunzhupaas.database.plugins;
import com.yunzhupaas.database.util.ResetSetHolder;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Mybatis ResultSet拦截器
* @see ResetSetHolder
* @author 云筑产品开发平台组
* @user N
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/14 16:29
*/
@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})
public class ResultSetInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
Statement statement = (Statement) args[0];
ResultSet rs = getFirstResultSet(statement);
if (rs != null) {
ResetSetHolder.setResultSet(rs);
}
Object result;
try{
result = invocation.proceed();
}finally{
ResetSetHolder.clear();
}
return result;
}
private ResultSet getFirstResultSet(Statement stmt) throws SQLException {
ResultSet rs = stmt.getResultSet();
while (rs == null) {
if (stmt.getMoreResults()) {
rs = stmt.getResultSet();
} else if (stmt.getUpdateCount() == -1) {
break;
}
}
return rs;
}
}

View File

@@ -0,0 +1,210 @@
package com.yunzhupaas.database.source;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import com.yunzhupaas.database.constant.DbConst;
import com.yunzhupaas.database.datatype.db.interfaces.DtInterface;
import com.yunzhupaas.database.datatype.model.DtModelDTO;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.model.dbfield.DbFieldModel;
import com.yunzhupaas.database.model.entity.DbLinkEntity;
import com.yunzhupaas.database.model.interfaces.DbSourceOrDbLink;
import com.yunzhupaas.database.source.impl.*;
import com.yunzhupaas.database.sql.model.DbStruct;
import com.yunzhupaas.database.util.DbTypeUtil;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.TenantHolder;
import lombok.Data;
import java.sql.ResultSet;
import java.util.Collections;
import java.util.List;
/**
* 数据库基础模型表
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/6/21
*/
@Data
public abstract class DbBase {
/**
* YUNZHUPAAS数据库编码标准
*/
public static final String MYSQL = "MySQL";
public static final String DM = "DM";
public static final String KINGBASE_ES = "KingbaseES";
public static final String ORACLE = "Oracle";
public static final String POSTGRE_SQL = "PostgreSQL";
public static final String SQL_SERVER = "SQLServer";
public static final String DORIS = "Doris";
public static final DbBase[] DB_BASES = { new DbMySQL(), new DbSQLServer(), new DbDM(),
new DbOracle(), new DbKingbase(), new DbPostgre(), new DbDoris() };
public static final String[] DB_ENCODES = { MYSQL, ORACLE, SQL_SERVER, DM, KINGBASE_ES, POSTGRE_SQL, DORIS };
/**
* YUNZHUPAAS数据库编码
*/
protected String yunzhupaasDbEncode;
/**
* MybatisPlus数据库编码
*/
protected DbType mpDbType;
/**
* DruidDbType
*/
protected com.alibaba.druid.DbType druidDbType;
/**
* url里数据库标识
*/
protected String connUrlEncode;
/**
* 数据库驱动
*/
protected String driver;
/**
* 默认端口
*/
protected String defaultPort;
/**
* 管理员用户名
*/
protected String dbaUsername;
/**
* 默认预备url
*/
protected String defaultPrepareUrl;
/**
* oracle连接扩展参数
*/
public String oracleParam;
/**
* 无参构造
*/
protected DbBase() {
init();
}
/**
* 初始赋值
*/
protected abstract void init();
/**
* 数据库对象初始化
* 指定子类被创建时,需要提供的参数
*/
protected void setInstance(String yunzhupaasDbEncode, DbType mpDbType, com.alibaba.druid.DbType druidDbType,
String defaultPort, String dbaUsername, String connUrlEncode,
String driver, String defaultPrepareUrl) {
// 绑定YUNZHUPAAS数据库编码
this.yunzhupaasDbEncode = yunzhupaasDbEncode;
// 绑定MybatisPlus数据库编码
this.mpDbType = mpDbType;
this.druidDbType = druidDbType;
// 绑定Url数据库标识
this.connUrlEncode = connUrlEncode;
this.driver = driver;
this.defaultPrepareUrl = defaultPrepareUrl;
// 默认端口
this.defaultPort = defaultPort;
this.dbaUsername = dbaUsername;
}
public static List<String> dynamicAllTableName = Collections.emptyList();
public DbBase[] DB_BASES() {
return null;
}
/**
* 获取最终动态表名, 处理是否动态表名
*
* @return
*/
public TableNameHandler getDynamicTableNameHandler() {
return (sql, tableName) -> {
// 是否指定数据源, 且在初始库中包含的表
if (StringUtil.isNotEmpty(TenantHolder.getDatasourceName())) {
return getDynamicTableName(tableName);
}
return tableName;
};
}
/**
* 获取动态组合表名
*
* @param tableName
* @return
*/
protected String getDynamicTableName(String tableName) {
return TenantHolder.getDatasourceName() + "." + tableName;
}
/**
* 不同库间设置字段信息
*
* @param model 字段模型
* @param result 结果集
* @return 表字段模型
* @throws DataException ignore
*/
public void setPartFieldModel(DbFieldModel model, ResultSet result) throws Exception {
model.setDtModelDTO(new DtModelDTO(
DtInterface.newInstanceByDt(model.getDataType(), this.getYunzhupaasDbEncode()),
result.getLong(DbAliasEnum.CHAR_LENGTH.getAlias(yunzhupaasDbEncode)),
result.getInt(DbAliasEnum.NUM_PRECISION.getAlias(yunzhupaasDbEncode)),
result.getInt(DbAliasEnum.NUM_SCALE.getAlias(yunzhupaasDbEncode))));
}
/**
* 获取数据库连接Url 关键参数:
* 1、地址
* 2、端口
* 3、数据库名
* 4、模式 (参数:?currentSchema = schema
* 5、jdbc-url自定义参数
*
* 此方法对DbTypeUtil与内部开放对外关闭。外部调用url用DbTypeUtil.getUrl()方法
*
* @return String 连接
*/
protected String getConnUrl(String prepareUrl, String host, Integer port, DbStruct struct) {
// 配置文件是否存在自定义数据连接url
prepareUrl = StringUtil.isNotEmpty(prepareUrl) ? prepareUrl : defaultPrepareUrl;
// 当地址为空,用本地回环地址
prepareUrl = prepareUrl.replace(DbConst.HOST, StringUtil.isNotEmpty(host) ? host : "127.0.0.1");
// 当端口为空,用数据库一般默认端口
prepareUrl = prepareUrl.replace(DbConst.PORT, port != null ? port.toString() : defaultPort);
return prepareUrl;
}
/*
* 提供内部封装方法所独有的方法调用
* 保持全局只有一处显性getUrl,getConn的方法即在ConnUtil里=====================================
* =
*/
public static class BaseCommon {
public static String getDbBaseConnUrl(DbSourceOrDbLink dbSourceOrDbLink, String dbName) {
DbLinkEntity dsd = dbSourceOrDbLink.init(dbName);
try {
return DbTypeUtil.getDb(dbSourceOrDbLink).getConnUrl(dsd.getPrepareUrl(), dsd.getHost(), dsd.getPort(),
dsd.getDbStruct());
} catch (DataException e) {
e.printStackTrace();
}
return "";
}
}
}

View File

@@ -0,0 +1,65 @@
package com.yunzhupaas.database.source;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/21
*/
@Data
public class DbModel {
public DbModel(Connection connection){
try {
//从conn中获取数据库的元数据
DatabaseMetaData databaseMetaData = connection.getMetaData();
/*============库信息===========*/
//连接的库名目录
this.catalog = connection.getCatalog();
//数据库类型 MYSQL ORACLE
this.jdbcDbType = databaseMetaData.getDatabaseProductName();
//数据库版本号 8.0.15
this.version = databaseMetaData.getDatabaseProductVersion();
//数据库大版本 8
this.majorVersion = databaseMetaData.getDatabaseMajorVersion();
//jdbc连接的url
this.url = databaseMetaData.getURL();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 数据库目录
*/
private String catalog;
/**
* jdbc数据库类型
*/
private String jdbcDbType;
/**
* 数据库版本号 例8.0.15
*/
private String version;
/**
* 数据库大版本 例8
*/
private Integer majorVersion;
/**
* 数据库连接
*/
private String url;
}

View File

@@ -0,0 +1,60 @@
package com.yunzhupaas.database.source.impl;
import com.baomidou.mybatisplus.annotation.DbType;
import com.yunzhupaas.database.constant.DbConst;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.model.DbStruct;
/**
* 达梦模型
*
* @author 云筑产品开发平台组 YY
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/06
*/
public class DbDM extends DbBase {
@Override
protected void init() {
setInstance(
DM,
DbType.DM,
com.alibaba.druid.DbType.dm,
"5236",
"SYSDBA",
"dm",
"dm.jdbc.driver.DmDriver",
"jdbc:dm://{host}:{port}/{schema}");
}
@Override
protected String getConnUrl(String prepareUrl, String host, Integer port, DbStruct struct){
prepareUrl = super.getConnUrl(prepareUrl, host, port, null);
return prepareUrl.replace(DbConst.DB_SCHEMA, struct.getDmDbSchema());
}
// public static void setDmTableModel(DbConnDTO connDTO, List<DbTableModel> tableModelList) {
// //达梦特殊方法
// try {
// @Cleanup Connection dmConn = connDTO.getConn();
// tableModelList.forEach(tm -> {
// try {
// Integer sum = DbDM.getSum(dmConn, tm.getTable());
// tm.setSum(sum);
// } catch (DataException e) {
// e.printStackTrace();
// }
// });
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
// private static Integer getSum(Connection connection, String table) throws DataException {
// String sql = "SELECT COUNT(*) as F_SUM FROM " + table;
// return JdbcUtil.queryOneInt(connection, sql, "F_SUM");
// }
}

View File

@@ -0,0 +1,54 @@
package com.yunzhupaas.database.source.impl;
import com.baomidou.mybatisplus.annotation.DbType;
import com.yunzhupaas.database.constant.DbConst;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.model.dbfield.DbFieldModel;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import java.sql.ResultSet;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version v3.4.5
* @copyrignt 深圳市乐程软件有限公司
* @date 2024-12-08
*/
public class DbDoris extends DbBase {
@Override
protected void init() {
setInstance(
DORIS,
DbType.MYSQL,
com.alibaba.druid.DbType.mysql,
"9030",
"root",
"mysql",
"com.mysql.cj.jdbc.Driver",
"jdbc:mysql://{host}:{port}/{dbname}?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false"
// connUrl =
// "jdbc:mysql://{host}:{port}/{dbname}?useUnicode=true&autoReconnect=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8";
);
}
@Override
public String getConnUrl(String prepareUrl, String host, Integer port, DbStruct struct) {
prepareUrl = super.getConnUrl(prepareUrl, host, port, null);
return prepareUrl.replace(DbConst.DB_NAME, struct.getMysqlDbName());
}
@Override
public void setPartFieldModel(DbFieldModel model, ResultSet result) throws Exception {
long charLength = result.getLong(DbAliasEnum.CHAR_LENGTH.getAlias(this.getYunzhupaasDbEncode()));
// Doris 长文本格式为String但Jdbc查出的数据类型为varchar & charLength = 2147483643
if (model.getDataType().equalsIgnoreCase("varchar") && charLength == 2147483643) {
model.setDataType("text");
}
super.setPartFieldModel(model, result);
}
}

View File

@@ -0,0 +1,57 @@
package com.yunzhupaas.database.source.impl;
import com.baomidou.mybatisplus.annotation.DbType;
import com.yunzhupaas.database.constant.DbConst;
import com.yunzhupaas.database.model.dbfield.DbFieldModel;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import com.yunzhupaas.util.StringUtil;
import java.sql.ResultSet;
/**
* 金仓模型
*
* @author 云筑产品开发平台组 YY
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/06
*/
public class DbKingbase extends DbBase {
public static String DEF_SCHEMA = "public";
@Override
protected void init() {
setInstance(
KINGBASE_ES,
DbType.KINGBASE_ES,
com.alibaba.druid.DbType.kingbase,
"54321",
"system",
"kingbase8",
"com.kingbase8.Driver",
"jdbc:kingbase8://{host}:{port}/{dbname}?currentSchema={schema}");
}
@Override
public String getConnUrl(String prepareUrl, String host, Integer port, DbStruct struct) {
prepareUrl = super.getConnUrl(prepareUrl, host, port, null);
return prepareUrl.replace(DbConst.DB_NAME, struct.getKingBaseDbName()).replace(DbConst.DB_SCHEMA, struct.getKingBaseDbSchema());
}
@Override
public void setPartFieldModel(DbFieldModel model, ResultSet result) throws Exception {
new DbPostgre().setPartFieldModel(model, result);
}
private String getCheckSchema(String schema){
if(StringUtil.isEmpty(schema)){
// 默认public模式
schema = DEF_SCHEMA;
}
return schema;
}
}

View File

@@ -0,0 +1,40 @@
package com.yunzhupaas.database.source.impl;
import com.baomidou.mybatisplus.annotation.DbType;
import com.yunzhupaas.database.constant.DbConst;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.model.DbStruct;
/**
* MySQL模型
*
* @author 云筑产品开发平台组 YY
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/06
*/
public class DbMySQL extends DbBase {
@Override
protected void init(){
setInstance(
MYSQL,
DbType.MYSQL,
com.alibaba.druid.DbType.mysql,
"3306",
"root",
"mysql",
"com.mysql.cj.jdbc.Driver",
"jdbc:mysql://{host}:{port}/{dbname}?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true"
//connUrl = "jdbc:mysql://{host}:{port}/{dbname}?useUnicode=true&autoReconnect=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8";
);
}
@Override
public String getConnUrl(String prepareUrl, String host, Integer port, DbStruct struct) {
prepareUrl = super.getConnUrl(prepareUrl, host, port, null);
return prepareUrl.replace(DbConst.DB_NAME, struct.getMysqlDbName());
}
}

View File

@@ -0,0 +1,156 @@
package com.yunzhupaas.database.source.impl;
import com.baomidou.mybatisplus.annotation.DbType;
import com.yunzhupaas.database.constant.DbConst;
import com.yunzhupaas.database.model.dbfield.DbFieldModel;
import com.yunzhupaas.database.model.entity.DbLinkEntity;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import com.yunzhupaas.database.util.ConnUtil;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.JsonUtil;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.TenantHolder;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Properties;
/**
* Oracle模型
*
* @author 云筑产品开发平台组 YY
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/06
*/
public class DbOracle extends DbBase {
/*================Oracle4种数据库连接url=================*/
/**
* SID
* 或jdbc:oracle:thin:@{host}:{port}/{SID}
*/
private static final String SID_URL = "jdbc:oracle:thin:@{host}:{port}:{schema}";
private static final String SID_SIGN = "SID";
/**
* SERVICE服务名
*/
private static final String SERVICE_URL = "jdbc:oracle:thin:@//{host}:{port}/{schema}";
private static final String SERVICE_SIGN = "SERVICE";
/**
* SCHEMA模式
*/
private static final String SCHEMA_URL =
"jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={host})(PORT={port})))(CONNECT_DATA=(SERVICE_NAME={schema})))";
private static final String SCHEMA_SIGN = "SCHEMA";
/**
* TNS
*/
private static final String TNS_URL = "jdbc:oracle:thin:@{schema}";
private static final String TNS_SIGN = "TNS";
public static final String ORACLE_SERVICE = "oracleService";
/**
* 连接扩展参数
*/
public static final String ORACLE_LINK_TYPE = "oracleLinkType";
public static final String ORACLE_ROLE = "oracleRole";
@Override
protected void init() {
setInstance(
ORACLE,
DbType.ORACLE,
com.alibaba.druid.DbType.oracle,
"1521",
"sys",
"oracle",
"oracle.jdbc.OracleDriver",
"");
}
@Override
public String getConnUrl(String prepareUrl, String host, Integer port, DbStruct struct) {
String schema = struct.getOracleDbSchema();
if(StringUtil.isNotEmpty(struct.getOracleParam()) && StringUtil.isEmpty(prepareUrl)) {
Map<String, Object> oracleParamMap = JsonUtil.stringToMap(struct.getOracleParam());
if (oracleParamMap.size() > 0) {
schema = oracleParamMap.get(DbOracle.ORACLE_SERVICE).toString();
String urlType = oracleParamMap.get(DbOracle.ORACLE_LINK_TYPE).toString();
switch (urlType) {
case SID_SIGN:
prepareUrl = SID_URL;
break;
case SERVICE_SIGN:
prepareUrl = SERVICE_URL;
break;
case SCHEMA_SIGN:
prepareUrl = SCHEMA_URL;
break;
case TNS_SIGN:
prepareUrl = TNS_URL;
break;
default:
// throw new DataException("Oracle连接类型指定失败");
break;
}
}
}
if(StringUtil.isEmpty(prepareUrl)){
prepareUrl = SID_URL;
}
return super.getConnUrl(prepareUrl, host, port, null).replace(DbConst.DB_SCHEMA, schema);
}
@Override
protected String getDynamicTableName(String tableName) {
return TenantHolder.getDatasourceName().toUpperCase()+"."+tableName;
}
public void setPartFieldModel(DbFieldModel model, ResultSet result) throws Exception{
if(model.getDataType().toUpperCase().contains("TIMESTAMP")){
model.setDataType("TIMESTAMP");
}
super.setPartFieldModel(model, result);
}
/**
* Oracle特殊添加数据连接方式
*/
public Connection getOracleConn(DbLinkEntity dsd, String url) throws DataException {
String logonUser = "";
if(StringUtil.isNotEmpty(dsd.getOracleParam())){
Map<String, Object> oracleParamMap = JsonUtil.stringToMap(dsd.getOracleParam());
if(oracleParamMap.size() > 0){
logonUser = oracleParamMap.get(DbOracle.ORACLE_ROLE).toString();
}
}
return createOracleConn(driver, logonUser, dsd.getUserName(), dsd.getPassword(), url);
}
private static Connection createOracleConn(String driver, String logonUser, String userName, String password, String url) throws DataException {
//Oracle登录角色设置DefaultSYSDBASYSOPER
Properties conProps = DbOracle.setConnProp(logonUser, userName, password);
return ConnUtil.ConnCommon.createConnByProp(driver, conProps.getProperty("user"), password, url, conProps);
}
public static Properties setConnProp(String logonUser, String userName, String password){
Properties conProps = new Properties();
// 使用角色登录userName + :@{角色}
if(!logonUser.isEmpty()){
//defaultRowPrefetch从服务器预取的默认行数(默认值为“10”) String (containing integer value)
conProps.put("defaultRowPrefetch", "15");
/* 这里有一个风险由于客户userName中含有一个或多个:@导致连接失败 */
//internal_logon允许您作为sys登录的权限如sysdba或sysoper
conProps.put("internal_logon", logonUser);
conProps.put("user", userName);
}
conProps.put("user", userName);
conProps.setProperty("password", password);
return conProps;
}
}

View File

@@ -0,0 +1,82 @@
package com.yunzhupaas.database.source.impl;
import com.baomidou.mybatisplus.annotation.DbType;
import com.yunzhupaas.database.constant.DbAliasConst;
import com.yunzhupaas.database.constant.DbConst;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.model.dbfield.DbFieldModel;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.TenantHolder;
import java.sql.ResultSet;
import java.util.regex.Pattern;
/**
* PostgreSQL模型
*
* @author 云筑产品开发平台组 YY
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/06
*/
public class DbPostgre extends DbBase {
public static String DEF_SCHEMA = "public";
@Override
protected void init() {
setInstance(
POSTGRE_SQL,
DbType.POSTGRE_SQL,
com.alibaba.druid.DbType.postgresql,
"5432",
"postgres",
"postgresql",
"org.postgresql.Driver",
"jdbc:postgresql://{host}:{port}/{dbname}");
}
@Override
public String getConnUrl(String prepareUrl, String host, Integer port, DbStruct struct) {
prepareUrl = super.getConnUrl(prepareUrl, host, port, null);
return prepareUrl.replace(DbConst.DB_NAME, struct.getPostGreDbName()).replace(DbConst.DB_SCHEMA,
struct.getPostGreDbSchema());
}
@Override
protected String getDynamicTableName(String tableName) {
return TenantHolder.getDatasourceName().toLowerCase() + "." + tableName;
}
@Override
public void setPartFieldModel(DbFieldModel model, ResultSet result) throws Exception {
String nullSignStr = result.getString(DbAliasEnum.ALLOW_NULL.getAlias(this.getYunzhupaasDbEncode()));
model.setNullSign(DbAliasConst.ALLOW_NULL.getSign(nullSignStr.equals("YES") ? 1 : 0));
super.setPartFieldModel(model, result);
}
private String getCheckSchema(String schema) {
if (StringUtil.isEmpty(schema)) {
// 默认public模式
schema = DEF_SCHEMA;
}
return schema;
}
/**
* 表存在大写与小写,导致大小写敏感,需要双引号
*
* @param originTable 原始表名
* @return 表名
*/
public static String getTable(String originTable) {
if (Pattern.compile("[A-Z]").matcher(originTable).find()) {
return "\"" + originTable + "\"";
} else {
return originTable;
}
}
}

View File

@@ -0,0 +1,50 @@
package com.yunzhupaas.database.source.impl;
import com.baomidou.mybatisplus.annotation.DbType;
import com.yunzhupaas.database.constant.DbConst;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import com.yunzhupaas.util.TenantHolder;
/**
* SQLServer模型
*
* @author 云筑产品开发平台组 YY
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/06
*/
public class DbSQLServer extends DbBase {
/**
* 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。
* 错误:“sun.security.validator.ValidatorException: PKIX path building failed
*
* 可以尝试连接jdbc:sqlserver://{host}:{port};databaseName={dbname};encrypt=true;trustServerCertificate=true
*/
@Override
protected void init() {
setInstance(
SQL_SERVER,
DbType.SQL_SERVER,
com.alibaba.druid.DbType.sqlserver,
"1433",
"sa",
"sqlserver",
"com.microsoft.sqlserver.jdbc.SQLServerDriver",
"jdbc:sqlserver://{host}:{port};databaseName={dbname};trustServerCertificate=true");
}
@Override
public String getConnUrl(String prepareUrl, String host, Integer port, DbStruct struct) {
prepareUrl = super.getConnUrl(prepareUrl, host, port, null);
return prepareUrl.replace(DbConst.DB_NAME, struct.getSqlServerDbName()).replace(DbConst.DB_SCHEMA, struct.getSqlServerDbSchema());
}
@Override
protected String getDynamicTableName(String tableName) {
return TenantHolder.getDatasourceName()+".dbo." + tableName;
}
}

View File

@@ -0,0 +1,61 @@
package com.yunzhupaas.database.sql;
import com.yunzhupaas.database.model.dbfield.JdbcColumnModel;
import com.yunzhupaas.database.model.interfaces.DbSourceOrDbLink;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.source.impl.DbMySQL;
import com.yunzhupaas.database.util.DbTypeUtil;
import com.yunzhupaas.exception.DataException;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* SQL语句模板基类
* 用以一些SQL语句不同库的特殊处理
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/10/6
*/
@Data
public abstract class SqlBase {
/**
* 数据基类
*/
protected String dbEncode;
protected DbBase getDb(){
try {
return DbTypeUtil.getEncodeDb(this.dbEncode);
} catch (DataException e) {
e.printStackTrace();
}
return new DbMySQL();
}
/**
* 初始结构参数
*/
public abstract void initStructParams(String table, DbSourceOrDbLink dbSourceOrDbLink);
/**
* 批量添加数据
*/
// TODO 其余几个数据还没有添加方法
public String batchInsertSql(List<List<JdbcColumnModel>> dataList, String table) {
return "";
}
}

View File

@@ -0,0 +1,257 @@
package com.yunzhupaas.database.sql.enums;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.enums.ParamEnum;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.enums.base.SqlFrameBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import com.yunzhupaas.util.StringUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
import java.util.Map;
/**
* 达梦 SQL语句模板
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/17
*/
@Getter
@AllArgsConstructor
public enum SqlDMEnum implements SqlFrameBase{
/* =============================== 系统语句 ==================================== */
FIELDS(
"SELECT \n" +
"\tA.COLUMN_NAME AS " + DbAliasEnum.FIELD.getAlias() + ",\n" +
"\tA.DATA_TYPE AS " + DbAliasEnum.DATA_TYPE.getAlias() + ",\n" +
"\tA.DATA_LENGTH AS " + DbAliasEnum.CHAR_LENGTH.getAlias() + ",\n" +
"\tA.DATA_PRECISION AS " + DbAliasEnum.NUM_PRECISION.getAlias() + ",\n" +
"\tA.DATA_SCALE AS " + DbAliasEnum.NUM_SCALE.getAlias() + ",\n" +
"\tCASE WHEN E.CONSTRAINT_TYPE IS NOT NULL THEN '1' ELSE '0' END AS " + DbAliasEnum.PRIMARY_KEY.getAlias() + ",\n" +
"\tCASE A.NULLABLE WHEN 'N' THEN '0' ELSE '1' END AS " + DbAliasEnum.ALLOW_NULL.getAlias() + ",\n" +
"\tB.COMMENTS AS " + DbAliasEnum.FIELD_COMMENT.getAlias() + ",\n" +
"\tH.IS_AUTO AS " + DbAliasEnum.AUTO_INCREMENT.getAlias() + "\n" +
"FROM \n" +
"\tALL_TAB_COLUMNS A -- 表&字段 OWNER、TABLE_NAME、COLUMN_NAME_\t\n" +
"LEFT JOIN \n" +
"\tALL_COL_COMMENTS B -- 字段注释 TABLE_NAME、COLUMN_NAME\n" +
"ON \n" +
"\tA.OWNER = B.SCHEMA_NAME AND A.TABLE_NAME = B.TABLE_NAME AND A.COLUMN_NAME = B.COLUMN_NAME \n" +
"LEFT JOIN \n" +
"\t(\n" +
"\t\tSELECT \n" +
"\t\t\tC.OWNER, C.TABLE_NAME, C.COLUMN_NAME, D.CONSTRAINT_TYPE \n" +
"\t\tFROM \n" +
"\t\t\tALL_CONS_COLUMNS C\n" +
"\t\tLEFT JOIN \n" +
"\t\t\tALL_CONSTRAINTS D \n" +
"\t\tON \n" +
"\t\t\tC.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND D.CONSTRAINT_TYPE = 'P'\n" +
"\t\tWHERE\n" +
"\t\t\tC.OWNER = " + ParamEnum.DB_NAME.getParamSign() + "\n" +
"\t\t\tAND C.TABLE_NAME = " + ParamEnum.TABLE.getParamSign() + "\n" + // 添加模式与表,增加查询效率
"\t) E\n" +
"ON\n" +
"\tA.OWNER = E.OWNER AND A.TABLE_NAME = E.TABLE_NAME AND A.COLUMN_NAME = E.COLUMN_NAME \n" +
"LEFT JOIN \n" +
"\t(\n" +
"\t\tSELECT \n"+
"\t\t\tF.NAME, DECODE(F.INFO2,1,'1','0') AS IS_AUTO \n" +
"\t\tFROM \n"+
"\t\t\tSYS.SYSCOLUMNS F\n" +
"\t\tWHERE\n" +
"\t\t\tID ="+
"\t(\n"+
"\t\tSELECT \n"+
"\t\t\tOBJECT_ID \n" +
"\t\tFROM \n" +
"\t\t\tDBA_OBJECTS G \n"+
"\t\tWHERE \n" +
"\t\t\tG.OWNER = " + ParamEnum.DB_NAME.getParamSign() + "\n" +
"\t\t\tAND G.OBJECT_NAME = " + ParamEnum.TABLE.getParamSign() + "\n" +
"\t\t\tAND G.OBJECT_TYPE = 'TABLE') \n" +
"\t) H\n" +
"ON \n" +
"\tA.COLUMN_NAME = H.NAME \n" +
"WHERE\n" +
" A.OWNER = " + ParamEnum.DB_NAME.getParamSign() + "\n" +
"\tAND A.TABLE_NAME = " + ParamEnum.TABLE.getParamSign() + "\n" +
"\tORDER BY A.COLUMN_ID"
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getDmDbSchema());
list.add(table);
list.add(dbStruct.getDmDbSchema());
list.add(table);
list.add(dbStruct.getDmDbSchema());
list.add(table);
}
},
TABLES(
// 作用:DBMS_STATS.GATHER_TABLE_STATS统计表,列,索引的统计信息(默认参数下是对表进行直方图信息收集,
// 包含该表的自身-表的行数、数据块数、行长等信息;列的分析--列值的重复数、列上的空值、数据在列上的分布情况;
// 索引的分析-索引页块的数量、索引的深度、索引聚合因子).
// "dbms_stats.GATHER_SCHEMA_stats (" + ParamEnum.DB_SCHEMA.getParamSign() +");\n" +
"SELECT\n" +
"ut.TABLE_NAME " + DbAliasEnum.TABLE_NAME.getAlias() + ",utc.COMMENTS " + DbAliasEnum.TABLE_COMMENT.getAlias() + "\n" +
",ut.num_rows " + DbAliasEnum.TABLE_SUM.getAlias() + "\n" +
"FROM ALL_TABLES AS ut\n" +
"LEFT JOIN\n" +
"all_tab_comments AS utc\n" +
"ON\n" +
"ut.TABLE_NAME = utc.TABLE_NAME AND ut.OWNER = utc.OWNER\n" +
"WHERE ut.OWNER = " + ParamEnum.DB_SCHEMA.getParamSign() + "\n" +
"ORDER BY F_TABLE_NAME;"
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getDmDbSchema());
}
},
TABLESANDVIEW(
// 作用:DBMS_STATS.GATHER_TABLE_STATS统计表,列,索引的统计信息(默认参数下是对表进行直方图信息收集,
// 包含该表的自身-表的行数、数据块数、行长等信息;列的分析--列值的重复数、列上的空值、数据在列上的分布情况;
// 索引的分析-索引页块的数量、索引的深度、索引聚合因子).
// "dbms_stats.GATHER_SCHEMA_stats (" + ParamEnum.DB_SCHEMA.getParamSign() +");\n" +
" select\tTABLE_NAME as " + DbAliasEnum.TABLE_NAME.getAlias() +
",'TABLE' as " + DbAliasEnum.TABLE_TYPE.getAlias() + " from all_tab_comments WHERE owner = " + ParamEnum.DB_NAME.getParamSign() + "\n" +
" UNION\n" +
" select\t view_name as " + DbAliasEnum.TABLE_NAME.getAlias() +
",'VIEW' as " + DbAliasEnum.TABLE_TYPE.getAlias() + " from all_views WHERE owner = " + ParamEnum.DB_NAME.getParamSign()
// "select atcs.table_name " + DbAliasEnum.TABLE_NAME.getAlias()
// + ",atcs.comments " + DbAliasEnum.TABLE_COMMENT.getAlias()
// + ",atcs.table_type " + DbAliasEnum.TABLE_TYPE.getAlias()
// + "\nfrom all_views alv left join all_tab_comments atcs on alv.owner = atcs.owner where atcs.owner = " + ParamEnum.DB_NAME.getParamSign() + ""
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getDmDbSchema());
list.add(dbStruct.getPostGreDbSchema());
}
},
TABLE(
TABLES.sqlFrame.replace("ORDER BY", "AND ut.TABLE_NAME = " + ParamEnum.TABLE.getParamSign() + " ORDER BY")
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getDmDbSchema());
list.add(table);
}
},
EXISTS_TABLE(
"SELECT COUNT (*) AS TOTAL FROM (" +
"SELECT\n" +
"ut.TABLE_NAME " + DbAliasEnum.TABLE_NAME.getAlias() + " FROM ALL_TABLES AS ut\n" +
"WHERE ut.OWNER = " + ParamEnum.DB_SCHEMA.getParamSign() +
" and ut.TABLE_NAME = "+ ParamEnum.TABLE.getParamSign()
+ ") AS TOTAL"
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getDmDbSchema());
list.add(table);
}
},
/* =============================== 定义语句 ==================================== */
// Data Definition Language简称 DDL用来建立数据库、数据库对象和定义列的命令。包括create、alter、drop
/*=============================== ALTER ====================================*/
CREATE_TABLE (
"<CREATE> <TABLE> {table}<(>\n" +
"【{column} {dataType} [[NOT] [NULL]] [<DEFAULT> {defaultValue}] 】" +
"\n{primarykeys}" +
"\n<)>"
){
@Override
public String createIncrement(String sqlFrame, Map<String, String> paramsMap) {
// 自增标识IDENTITY(1, 1)
if (StringUtil.isNotEmpty(paramsMap.get("[AUTO_INCREMENT]"))){
sqlFrame = super.createIncrement(sqlFrame, paramsMap)
.replace("{dataType}", "{dataType} IDENTITY(1, 1)");
String openIdentity = OPEN_IDENTITY.sqlFrame
.replace("{table}", paramsMap.get("{table}"))
.replace("<ON|OFF>", "ON");
return sqlFrame + ";\n" + openIdentity;
}
return sqlFrame;
}
@Override
public String createIndex(){
// 添加唯一索引
String createIndex = "CREATE UNIQUE {uniqueName} TO {table}【{column}】";
return null;
}
},
OPEN_IDENTITY("SET IDENTITY_INSERT {table} <ON|OFF>"),
ALTER_DROP("ALTER TABLE 《schema》.{table} DROP COLUMN {column}"),
/**
* 添加字段
*/
ALTER_ADD("ALTER TABLE 《schema》.{table} ADD {column} {dataType}"),
/**
* 修改字段
*/
ALTER_TYPE("ALTER TABLE 《schema》.{table} <MODIFY> {column} {dataType}"),
/**
* 修改表名
*/
ALTER_TABLE_NAME("ALTER TABLE 《schema》.{table} ALTER column {oldColumn} RENAME TO {newColumn};"),
/* =============================== DML操作语句 ==================================== */
// Data Manipulation Language简称 DML用来操纵数据库中数据的命令。包括select、insert、update、delete。
DB_TIME_SQL ("select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as TIME "),
INSERT(
"INSERT INTO 《schema》.{table} (【{column},】) VALUES (【{value},】)"
),
/**
*
*/
CREATE_SCHEMA(
"CREATE SCHEMA \"{schema}\";"
),
DROP_SCHEMA(
"DROP SCHEMA \"{schema}\" RESTRICT"
),
DROP_TABLE(
SqlPostgreSQLEnum.DROP_TABLE
),
COMMENT_COLUMN(
SqlPostgreSQLEnum.COMMENT_COLUMN
),
COMMENT_TABLE(
SqlPostgreSQLEnum.COMMENT_TABLE
),
CREATE(
SqlPostgreSQLEnum.CREATE
),
/*=============================== 其他 ====================================*/
;
private final String dbEncode = DbBase.DM;
private final String sqlFrame;
SqlDMEnum(SqlFrameBase sqlEnum){
this.sqlFrame = sqlEnum.getSqlFrame();
}
}

View File

@@ -0,0 +1,182 @@
package com.yunzhupaas.database.sql.enums;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.enums.ParamEnum;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.enums.base.SqlFrameBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
import java.util.Map;
/**
* 金仓 SQL语句模板
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/17
*/
@Getter
@AllArgsConstructor
public enum SqlKingbaseESEnum implements SqlFrameBase {
/* =============================== 系统语句 ==================================== */
FIELDS(
SqlPostgreSQLEnum.FIELDS.getSqlFrame()
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
SqlPostgreSQLEnum.FIELDS.setStructParams(table, dbStruct, list);
}
},
TABLES(
"SELECT DISTINCT t.TABLE_NAME AS " + DbAliasEnum.TABLE_NAME.getAlias() + ",c.DESCRIPTION AS " + DbAliasEnum.TABLE_COMMENT.getAlias() + ", 0 AS " + DbAliasEnum.TABLE_SUM.getAlias() + " FROM\n" +
"information_schema.TABLES AS t\n" +
"LEFT JOIN\n" +
"(SELECT * FROM PG_DESCRIPTION WHERE OBJSUBID = 0)AS c\n" +
"ON\n" +
"TABLE_NAME::REGCLASS::OID = C.OBJOID\n"
+ "WHERE\n" +
" TABLE_SCHEMA = " + ParamEnum.DB_SCHEMA.getParamSign()
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getKingBaseDbSchema());
}
},
TABLESANDVIEW(
"SELECT t.table_name AS " + DbAliasEnum.TABLE_NAME.getAlias() +
",c.DESCRIPTION AS " + DbAliasEnum.TABLE_COMMENT.getAlias() +
",t.table_type AS " + DbAliasEnum.TABLE_TYPE.getAlias() +
"\n FROM information_schema.TABLES\n" +
"\tAS T LEFT JOIN " +
"(SELECT * FROM PG_DESCRIPTION WHERE OBJSUBID = 0)AS c\n" +
"ON\n" +
"TABLE_NAME::REGCLASS::OID = C.OBJOID\n" +
"WHERE\n" +
"\tTABLE_SCHEMA = " + ParamEnum.DB_SCHEMA.getParamSign()
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getKingBaseDbSchema());
}
},
SqlKingbaseESEnum(
"SELECT t.TABLE_NAME AS " + DbAliasEnum.TABLE_NAME.getAlias() + ",c.DESCRIPTION AS " + DbAliasEnum.TABLE_COMMENT.getAlias() + ", 0 AS " + DbAliasEnum.TABLE_SUM.getAlias() + " FROM\n" +
"information_schema.TABLES AS t\n" +
"LEFT JOIN\n" +
"(SELECT * FROM PG_DESCRIPTION WHERE OBJSUBID = 0)AS c\n" +
"ON\n" +
"TABLE_NAME::REGCLASS::OID = C.OBJOID\n"
+ "WHERE\n" +
" TABLE_SCHEMA = " + ParamEnum.DB_SCHEMA.getParamSign()
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getKingBaseDbSchema());
}
},
TABLE(
TABLES.sqlFrame + " AND t.TABLE_NAME = " + ParamEnum.TABLE.getParamSign()
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getKingBaseDbSchema());
list.add(table);
}
},
EXISTS_TABLE(
"SELECT COUNT (*) AS TOTAL FROM (" +
"SELECT t.TABLE_NAME AS " + DbAliasEnum.TABLE_NAME.getAlias() + " FROM\n" +
"information_schema.TABLES AS t WHERE TABLE_SCHEMA = " + ParamEnum.DB_SCHEMA.getParamSign() +
" and t.TABLE_NAME = " + ParamEnum.TABLE.getParamSign()
+ ") AS COUNT_TAB"
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getKingBaseDbSchema());
list.add(table);
}
},
/**
* 建库
*/
CREATE_DATABASE(
"CREATE DATABASE WITH owner=\"{database}\" "
),
DROP_DATABASE(
"DROP DATABASE \"{database}\""
),
CREATE_SCHEMA(
"CREATE SCHEMA AUTHORIZATION \"{schema}\""
),
DROP_SCHEMA(
"DROP SCHEMA \"{schema}\" CASCADE;"
),
/*==================== 操作表 ======================*/
DROP(
"DROP TABLE {table}"
),
DROP_TABLE(
SqlPostgreSQLEnum.DROP_TABLE
),
COMMENT_COLUMN(
SqlPostgreSQLEnum.COMMENT_COLUMN
),
COMMENT_TABLE(
SqlPostgreSQLEnum.COMMENT_TABLE
),
CREATE(
SqlPostgreSQLEnum.CREATE
),
/*=============================== ALTER ====================================*/
CREATE_TABLE(SqlPostgreSQLEnum.CREATE_TABLE.getSqlFrame()){
@Override
public String createIncrement(String sqlFrame, Map<String, String> paramsMap) {
return SqlPostgreSQLEnum.CREATE_TABLE.createIncrement(sqlFrame, paramsMap);
}
},
ALTER_DROP(
"ALTER TABLE 《schema》.{table} DROP COLUMN {column}"
),
/**
* 添加字段
*/
ALTER_ADD(
"ALTER TABLE 《schema》.{table} ADD COLUMN {column} {dataType}"
),
/**
* 修改字段
*/
ALTER_TYPE(
"ALTER TABLE 《schema》.{table} ALTER COLUMN {column} TYPE {dataType}"
),
/**
* 修改: 表名
*/
RE_TABLE_NAME(
SqlPostgreSQLEnum.RE_TABLE_NAME
),
/*=============================== ALTER ====================================*/
INSERT(
"INSERT INTO 《schema》.{table} (【{column},】) VALUES (【{value},】)"
),
;
// ALTER TABLE flow_taskoperator DROP COLUMN F_DraftData
private final String dbEncode = DbBase.KINGBASE_ES;
private String sqlFrame;
SqlKingbaseESEnum(SqlFrameBase sqlEnum){
this.sqlFrame = sqlEnum.getSqlFrame();
}
}

View File

@@ -0,0 +1,171 @@
package com.yunzhupaas.database.sql.enums;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.enums.ParamEnum;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.enums.base.SqlFrameBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
/**
* MySQL SQL语句模板
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/17
*/
@Getter
@AllArgsConstructor
public enum SqlMySQLEnum implements SqlFrameBase {
/* =============================== 系统语句 ==================================== */
FIELDS("SELECT\n" +
"\tNUMERIC_SCALE AS " + DbAliasEnum.NUM_SCALE.getAlias() + ",\n" +
"\tNUMERIC_PRECISION AS " + DbAliasEnum.NUM_PRECISION.getAlias() + ",\n" +
"\tCHARACTER_MAXIMUM_LENGTH AS " + DbAliasEnum.CHAR_LENGTH.getAlias() + ",\n" +
"\tCOLUMN_NAME AS " + DbAliasEnum.FIELD.getAlias() + ",\n" +
"\tDATA_TYPE AS " + DbAliasEnum.DATA_TYPE.getAlias() + ",\n" +
"\tCOLUMN_COMMENT AS " + DbAliasEnum.FIELD_COMMENT.getAlias() + ",\n" +
"\tCOLUMN_DEFAULT AS " + DbAliasEnum.DEFAULT_VALUE.getAlias() + ",\n" +
" IF( EXTRA = 'auto_increment', '1', '0') AS " + DbAliasEnum.AUTO_INCREMENT.getAlias() + ",\n" +
" IF( IS_NULLABLE = 'YES', '1', '0' ) AS " + DbAliasEnum.ALLOW_NULL.getAlias() + ",\n" +
" IF( COLUMN_KEY = 'PRI', '1', '0' ) AS " + DbAliasEnum.PRIMARY_KEY.getAlias() + " \n" +
"FROM\n" +
"\tINFORMATION_SCHEMA.COLUMNS \n" +
"WHERE\n" +
"\tTABLE_NAME = " + ParamEnum.TABLE.getParamSign() + "\n" +
"\tAND TABLE_SCHEMA = " + ParamEnum.DB_SCHEMA.getParamSign() + " \n" +
"ORDER BY\n" +
"\tORDINAL_POSITION;") {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(table);
list.add(dbStruct.getMysqlDbName());
}
},
TABLES(
"SELECT\n" +
"\ttable_name AS " + DbAliasEnum.TABLE_NAME.getAlias() + ",\n" +
"\ttable_rows AS " + DbAliasEnum.TABLE_SUM.getAlias() + ",\n" +
"\tdata_length AS " + DbAliasEnum.TABLE_SIZE.getAlias() + ",\n" +
"\ttable_comment AS " + DbAliasEnum.TABLE_COMMENT.getAlias() + "\n" +
"FROM\n" +
"\tINFORMATION_SCHEMA.TABLES \n" +
"WHERE\n" +
"\tTABLE_SCHEMA = " + ParamEnum.DB_NAME.getParamSign() + "\n" +
"AND \n" +
"\tTABLE_TYPE != 'VIEW'") {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getMysqlDbName());
}
},
TABLESANDVIEW(
"SELECT\n" +
"\ttable_name AS " + DbAliasEnum.TABLE_NAME.getAlias() + ",\n" +
"\ttable_rows AS " + DbAliasEnum.TABLE_SUM.getAlias() + ",\n" +
"\tdata_length AS " + DbAliasEnum.TABLE_SIZE.getAlias() + ",\n" +
"\ttable_comment AS " + DbAliasEnum.TABLE_COMMENT.getAlias() + ",\n" +
"\ttable_type AS " + DbAliasEnum.TABLE_TYPE.getAlias() + "\n" +
"FROM\n" +
"\tINFORMATION_SCHEMA.TABLES \n" +
"WHERE\n" +
"\tTABLE_SCHEMA = " + ParamEnum.DB_NAME.getParamSign() + "\n") {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getMysqlDbName());
}
},
TABLE(
TABLES.sqlFrame + "AND table_name = " + ParamEnum.TABLE.getParamSign()) {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getMysqlDbName());
list.add(table);
}
},
EXISTS_TABLE(
"SELECT COUNT(*) AS TOTAL FROM (" +
"SELECT "
+ "table_name AS " + DbAliasEnum.TABLE_NAME.getAlias() + " "
+ "FROM "
+ "information_schema.TABLES "
+ "WHERE "
+ "TABLE_SCHEMA = " + ParamEnum.DB_NAME.getParamSign() + " "
+ "and "
+ "table_name = " + ParamEnum.TABLE.getParamSign()
+ ") AS COUNT_TAB") {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getMysqlDbName());
list.add(table);
}
},
/* =============================== 定义语句 ==================================== */
// Data Definition Language简称 DDL用来建立数据库、数据库对象和定义列的命令。包括create、alter、drop
CREATE_TABLE("<CREATE> <TABLE> {table} <(>\n" +
"【{column} {dataType} [[NOT] [NULL]] [<DEFAULT> {defaultValue}] [AUTO_INCREMENT] [<COMMENT> {comment}]】" +
"\n{primarykeys}" +
"\n<)> "),
CREATE(
"<CREATE> <TABLE> {table} <(>\n" +
"\r" +
"1:(<PRIMARY> <KEY> <(>{primaryColumn}<)> [<USING> {useValue}])|" +
"3:(<INDEX> {indexValue} <(>{column}<)>)|" +
"2:({column} {dataType} [[NOT] [NULL]] [<DEFAULT> {defaultValue}] [<COMMENT> {comment}])" +
",\n】" +
"<)> [<COMMENT> <=> {comment}]"),
DROP_TABLE("<DROP> <TABLE> [<IF> <EXISTS>] {table}"),
/**
* 表重命名
*/
RE_TABLE_NAME("ALTER TABLE {oldTable} RENAME [TO] {newTable}"),
ALTER_ADD_MODIFY(
"<ALTER> <TABLE> {table} <ADD|MODIFY> [COLUMN] {column} {dataType} [[NOT] [NULL]] [<DEFAULT> {defaultValue}] [<COMMENT> {comment}]"),
ALTER_ADD_MODIFY_MULTI(
"<ALTER> <TABLE> {table} <ADD|MODIFY><(>\n" +
"【[COLUMN] {column} {dataType} [[NOT] [NULL]] [<DEFAULT> {defaultValue}] [<COMMENT> {comment}],\n】"
+
"<)>"),
ALTER_CHANGE(
"<ALTER> <TABLE> {table} <CHANGE> {oldColumn} {newColumn} {dataType} [[NOT] [NULL]] [<DEFAULT> {defaultValue}] [<COMMENT> {comment}]"),
COMMENT_TABLE("<ALTER> <TABLE> {table} <COMMENT> = '{comment}'"),
COMMENT_COLUMN(
"<ALTER> <TABLE> {table} <MODIFY> `{column}` {dataType} [DEFAULT {defaultValue}] <COMMENT> '{comment}'"),
/*
* =============================== DML操作语句 ====================================
*/
// Data Manipulation Language简称
// DML用来操纵数据库中数据的命令。包括select、insert、update、delete。
/*
* mysql可以用 SELECT SQL_CALC_FOUND_ROWS * FROM table
* LIMIT index;SELECT FOUND_ROWS();方法获得两个结果集
*/
SELECT_TABLE("SELECT * FROM {table}"),
DB_TIME_SQL("SELECT DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i:%s') as TIME"),
COUNT_SIZE("SELECT COUNT(*) AS {totalAlias} FROM ({selectSql}) YUNZHUPAAS_TABLE"),
COUNT_TABLE_SIZE(COUNT_SIZE.sqlFrame.replace("({selectSql})", "{table}")),
INSERT("<INSERT> <INTO> {table} ([【{column},】]) <VALUES> (【{value},】)"),
DELETE_ALL("DELETE FROM {table}"),
/* =============================== 后缀 ==================================== */
// LIMIT必须在ORDER之后在前报错。顺序先排序再分页。
ORDER_PAGE("{selectSql} ORDER BY {orderColumn} [DESC] LIMIT {beginIndex},{pageSize}"),
PAGE("{selectSql} LIMIT {beginIndex},{pageSize}"),
ORDER("{selectSql} ORDER BY {column} [DESC]"),
LIKE("{selectSql} WHERE {column} like {condition}"),
;
/**
*
*/
private final String sqlFrame;
private final String dbEncode = DbBase.MYSQL;
}

View File

@@ -0,0 +1,304 @@
package com.yunzhupaas.database.sql.enums;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.enums.ParamEnum;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.enums.base.SqlFrameBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
/**
* Oracle SQL语句模板
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/30
*/
@Getter
@AllArgsConstructor
public enum SqlOracleEnum implements SqlFrameBase {
/* =============================== 系统语句 ==================================== */
FIELDS(
"SELECT \n" +
"\tA.COLUMN_NAME AS " + DbAliasEnum.FIELD.getAlias() + ",\n" +
"\tA.DATA_TYPE AS " + DbAliasEnum.DATA_TYPE.getAlias() + ",\n" +
"\tA.DATA_LENGTH AS " + DbAliasEnum.CHAR_LENGTH.getAlias() + ",\n" +
"\tA.DATA_PRECISION AS " + DbAliasEnum.NUM_PRECISION.getAlias() + ",\n" +
"\tA.DATA_SCALE AS " + DbAliasEnum.NUM_SCALE.getAlias() + ",\n" +
"\tCASE WHEN E.CONSTRAINT_TYPE IS NOT NULL THEN '1' ELSE '0' END AS "
+ DbAliasEnum.PRIMARY_KEY.getAlias() + ",\n" +
"\tCASE A.NULLABLE WHEN 'N' THEN '0' ELSE '1' END AS " + DbAliasEnum.ALLOW_NULL.getAlias() + ",\n" +
"\t(SELECT COUNT(*) FROM ALL_TRIGGERS WHERE TABLE_NAME = A.TABLE_NAME AND TABLE_OWNER = A.OWNER AND INSTR(TRIGGER_NAME, 'AUTO_') >0) AS "
+ DbAliasEnum.AUTO_TRIGGER.getAlias() + ",\n" +
"\tB.COMMENTS AS " + DbAliasEnum.FIELD_COMMENT.getAlias() + "\n" +
"FROM \n" +
"\tALL_TAB_COLUMNS A -- 表&字段 OWNER、TABLE_NAME、COLUMN_NAME_\t\n" +
"LEFT JOIN \n" +
"\tALL_COL_COMMENTS B -- 字段注释 TABLE_NAME、COLUMN_NAME\n" +
"ON \n" +
"\tA.OWNER = B.OWNER AND A.TABLE_NAME = B.TABLE_NAME AND A.COLUMN_NAME = B.COLUMN_NAME \n" +
"LEFT JOIN \n" +
"\t(SELECT \n" +
"\t\t\tC.OWNER, C.TABLE_NAME, C.COLUMN_NAME, D.CONSTRAINT_TYPE \n" +
"\t\tFROM \n" +
"\t\t\tALL_CONS_COLUMNS C, ALL_CONSTRAINTS D \n" +
"\t\tWHERE \n" +
"\t\t\tC.CONSTRAINT_NAME = D.CONSTRAINT_NAME AND D.CONSTRAINT_TYPE = 'P'\n" +
"\t) E\n" +
"ON\n" +
"\tA.OWNER = E.OWNER AND A.TABLE_NAME = E.TABLE_NAME AND A.COLUMN_NAME = E.COLUMN_NAME \n" +
"WHERE\n" +
" A.OWNER = " + ParamEnum.DB_NAME.getParamSign() + "\n" +
"\tAND A.TABLE_NAME = " + ParamEnum.TABLE.getParamSign()) {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getOracleDbSchema());
list.add(table);
}
},
// "SELECT atcs.table_name " + DbAliasConst.TABLE_NAME + ", atcs.comments " +
// DbAliasConst.TABLE_COMMENT + ", ats.num_rows " + DbAliasConst.TABLE_SUM +
// "\n" +
// "FROM user_tab_comments atcs,all_tables ats WHERE atcs.table_name =
// ats.table_name AND ats.owner = '" + ParamEnum.DB_NAME.getParamSign() + "'"
TABLES("SELECT atcs.table_name " + DbAliasEnum.TABLE_NAME.getAlias() + ", atcs.comments "
+ DbAliasEnum.TABLE_COMMENT.getAlias() + ", ats.num_rows " + DbAliasEnum.TABLE_SUM.getAlias() + "\n" +
"FROM all_tab_comments atcs,all_tables ats WHERE atcs.table_name = ats.table_name AND ats.owner = atcs.owner AND ats.owner = "
+ ParamEnum.DB_NAME.getParamSign() + ""
// "SELECT " +
// "a.TABLE_NAME " + DbAliasConst.TABLE_NAME + ", " +
// "b.COMMENTS " + DbAliasConst.TABLE_COMMENT + ", " +
// "a.num_rows " + DbAliasConst.TABLE_SUM +
// "\nFROM user_tables a, user_tab_comments b "
// + "WHERE a.TABLE_NAME = b.TABLE_NAME "
/* + "and a.TABLESPACE_NAME='"+ ParamEnum.TABLE_SPACE.getTarget()+"'" */
) {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getOracleDbSchema());
}
},
TABLESANDVIEW("SELECT\n" +
"\tatcs.table_name " + DbAliasEnum.TABLE_NAME.getAlias() + ",\n" +
"\tatcs.comments " + DbAliasEnum.TABLE_COMMENT.getAlias() + ",\n" +
"\tatcs.table_type " + DbAliasEnum.TABLE_TYPE.getAlias() + " \n" +
"FROM\n" +
"\tall_tab_comments atcs\n" +
"\tLEFT JOIN all_views alv ON alv.owner = atcs.owner \n" +
"WHERE\n" +
"\tatcs.owner = " + ParamEnum.DB_NAME.getParamSign()
) {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getOracleDbSchema());
}
},
TABLE(
TABLES.sqlFrame + " AND ats.TABLE_NAME = " + ParamEnum.TABLE.getParamSign()) {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getOracleDbSchema());
list.add(table);
}
},
EXISTS_TABLE(
"SELECT COUNT(*) AS TOTAL FROM ALL_TABLES WHERE OWNER = UPPER(" + ParamEnum.DB_NAME.getParamSign()
+ ") AND TABLE_NAME = UPPER(" + ParamEnum.TABLE.getParamSign() + ")") {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getOracleDbSchema());
list.add(table);
}
},
/* =============================== 定义语句 ==================================== */
// Data Definition Language简称 DDL用来建立数据库、数据库对象和定义列的命令。包括create、alter、drop
CREATE_TABLE("<CREATE> <TABLE> {table} <(>\n" +
"【{column} {dataType} [[NOT] [NULL]] [<DEFAULT> {defaultValue}] 】" +
"\n{primarykeys}" +
"\n<)>") {
public String createIndex() {
String model = "CREATE UNIQUE INDEX {indexName} ON {table}(【column】)";
return null;
}
},
// 添加自增
CREATE_AUTO_INCREMENT(
"CREATE SEQUENCE {table}_seq\n" +
"INCREMENT by 1\n" + // 每次增加1
"START WITH 1\n" + // 从1开始计数
"NOMAXVALUE\n" + // 无最大值
"NOCYCLE\n" + // 一直累加,不循环
"NOCACHE"),
// 添加自增触发器1、结尾需要用斜杠/;代表行结束,/代表块结束。2、触发器与序列名字长度有限制
// select 1 from dual用来做过渡;封号
CREATE_AUTO_INCREMENT_TRIGGER(
"CREATE OR REPLACE TRIGGER AUTO_{table}_tg\n" +
"BEFORE INSERT ON {table}\n" +
"FOR EACH ROW\n" +
"BEGIN\n" +
"\tSELECT {table}_seq.NEXTVAL INTO :new.{autoInc_field} FROM dual;\n" +
"END;"),
DROP_SEQ(
"DROP sequence {seqName}"),
DROP_TRIGGER(
"DROP trigger {triggerName}"),
CREATE("CREATE TABLE 《schema》.{table}(\n" +
"" +
"1:(PRIMARY KEY ({primaryColumn}))|" +
"2:({column} {dataType} [[NOT] [NULL]] [DEFAULT {defaultValue}])" +
",\n】)"),
DROP_TABLE("DROP TABLE {table}"),
/**
* 注意Oracle DDL:COMMENT 无法在Mybatis Mapper.xml里面使用?占位符
* 会出现ORA-01780: 要求文字字符串
*/
COMMENT_TABLE("COMMENT ON TABLE 《schema》.{table} IS '{comment}'"),
COMMENT_COLUMN("COMMENT ON COLUMN 《schema》.{table}.{column} IS '{comment}'"),
DROP_COLUMN("ALTER TABLE 《schema》.{table} DROP COLUMN {column}"),
ADD_COLUMN("ALTER TABLE 《schema》.{table} ADD {column} {dataType}"),
MODIFY_TYPE("ALTER TABLE 《schema》.{table} ALTER COLUMN {column} TYPE {dataType}"),
ALTER_TABLE("ALTER TABLE 《schema》.{oldTable} RENAME TO {newTable}"),
/*
* =============================== DML操作语句 ====================================
*/
/*
* Data Manipulation Language简称
* DML用来操纵数据库中数据的命令。包括select、insert、update、delete。
* 注意有一些Oracle版本中的语法子查询不支持别名关键词 AS
*/
/* =============================== ALTER ==================================== */
ORDER_PAGE("SELECT * FROM " +
"(SELECT YUNZHUPAAS_TEMP.*, ROWNUM YUNZHUPAAS_RowNo " +
"FROM " +
"({selectSql}) YUNZHUPAAS_TEMP " +
"ORDER BY {orderColumn} [DESC]) YUNZHUPAAS_TAB " +
"WHERE YUNZHUPAAS_TAB.YUNZHUPAAS_RowNo BETWEEN {beginIndex} AND {endIndex}"),
DB_TIME_SQL("select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as TIME from dual"),
INSERT("INSERT INTO 《schema》.{table} (【{column},】) VALUES (【{value},】)"),
/**
* 【注意Oracle所有插入字符也就是''之间的内容都会隐式转成varchar2类型都不得超过4000】
* 尾部用;结尾,不然会报错
*/
CLOB_INSERT("DECLARE\n" +
"\tclobVal {table}.{column}%TYPE;\n" +
"BEGIN\t\n" +
"\tclobVal := '{value}';\n" +
"INSERT INTO {table} (【{clobColumn},{column},】) VALUES (【{clobVal},{value},】);\n" +
"END"),
CLOB_UPDATE(
"DECLARE \n" +
"-- 此表为:{table}\n" +
"\tv_context NCLOB;\n" +
"BEGIN\n" +
"\tDBMS_LOB.CREATETEMPORARY(v_context,TRUE);\n" +
// "\tcontext := '' ;\n" +
"\t【DBMS_LOB.APPEND(v_context, '{context}');】\n" +
"\tUPDATE {table} SET {column} = v_context WHERE {key} = '{value}';\n" +
"END") {
@Override
public String getFastSql(List<String> values) {
String sql = this.getSqlFrame();
List<String> keys = Arrays.asList(
"{table}",
"{column}",
"\t【DBMS_LOB.APPEND(v_context, '{context}');】\n",
"{key}",
"{value}");
for (int i = 0; i < values.size(); i++) {
if (values.get(i) != null) {
sql = sql.replace(keys.get(i), values.get(i));
}
}
return sql;
}
},
CLOB_APPEND("DBMS_LOB.APPEND(v_context, '{context}')"),
BLOB_UPDATE(
"DECLARE \n" +
"-- 此表为:{table}\n" +
"\tv_context BLOB;\n" +
"BEGIN\n" +
"\tDBMS_LOB.CREATETEMPORARY(v_context,TRUE);\n" +
"\t【DBMS_LOB.APPEND(v_context, HEXTORAW('{context}'))】\n" +
"\tUPDATE {table} SET {column} = v_context WHERE {key} = '{value}';\n" +
"END") {
@Override
public String getFastSql(List<String> values) {
String sql = this.getSqlFrame();
List<String> keys = Arrays.asList(
"{table}",
"{column}",
"\t【DBMS_LOB.APPEND(v_context, HEXTORAW('{context}'))】\n",
"{key}",
"{value}");
for (int i = 0; i < values.size(); i++) {
if (values.get(i) != null) {
sql = sql.replace(keys.get(i), values.get(i));
}
}
return sql;
}
},
BLOB_APPEND("DBMS_LOB.APPEND(v_context, HEXTORAW('{context}'))"),
/* =============================== 其他 ==================================== */
/**
* oracle 时间格式转换
*/
TO_TIME("TO_DATE('{datetime}','YYYY-MM-DD HH24:MI:SS')"),
/**
* 查看现有表空间信息
*/
SELECT_TABLESPACE(
"SELECT TABLESPACE_NAME,FILE_ID,FILE_NAME,round(bytes/(1024*1024),0) total_space FROM DBA_DATA_FILES ORDER BY TABLESPACE_NAME"),
/**
* 创建临时表空间
*/
CREATE_TEMP_TABLESPACE("CREATE TEMPORARY TABLESPACE UQSM_TEMP TEMPFILE '/{path}/{tempTablespaceName}.dbf' " +
"size 8000m autoextend on next 50m maxsize unlimited extent management local;"),
/**
* 创建表空间
*/
CREATE_TABLESPACE("\n" + "CREATE TABLESPACE UQSM_DATA LOGGING DATAFILE '/{path}/{tempTablespaceName}.dbf' " +
"SIZE 8000m autoextendon next 50M maxsize unlimited extent management local;\n"),
/**
* 创建用户
*/
CREATE_USER(
"CREATE USER {user} IDENTIFIED BY {password} DEFAULT TABLESPACE {tablespace} TEMPORARY TABLESPACE {tempTablespace}"),
/**
* 删除用户
*/
DROP_USER("DROP USER {user}"),
/**
* 给用户授予权限
*/
GRANT_ROLE("GRANT connect,RESOURCE,dba to {user};"),
/**
* 修改用户的密码
*/
ALTER_USER_PASSWORD("ALTER USER {user} IDENTIFIED BY {password}"),
;
private final String sqlFrame;
private final String dbEncode = DbBase.ORACLE;
public String getFastSql(List<String> values) {
return this.getSqlFrame();
}
}

View File

@@ -0,0 +1,219 @@
package com.yunzhupaas.database.sql.enums;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.enums.ParamEnum;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.enums.base.SqlFrameBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import com.yunzhupaas.util.StringUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
import java.util.Map;
/**
* Postgre SQL语句模板
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/17
*/
@Getter
@AllArgsConstructor
public enum SqlPostgreSQLEnum implements SqlFrameBase {
/* =============================== 系统语句 ==================================== */
FIELDS(
"SELECT\n" +
"\tcol.column_name AS " + DbAliasEnum.FIELD.getAlias() + ",\n" +
"\tcol.udt_name AS " + DbAliasEnum.DATA_TYPE.getAlias() + ",\n" +
"\tis_nullable AS " + DbAliasEnum.ALLOW_NULL.getAlias() + ",\n" +
"\tcol_description (pa.pg_oid, attnum) " + DbAliasEnum.FIELD_COMMENT.getAlias() + ",\n" +
"\tcharacter_maximum_length AS " + DbAliasEnum.CHAR_LENGTH.getAlias() + ",\n" +
"\tnumeric_precision AS " + DbAliasEnum.NUM_PRECISION.getAlias() + ",\n" +
"\tcolumn_default AS " + DbAliasEnum.COLUMN_DEFAULT.getAlias() + ",\n" +
"\ttable_name AS " + DbAliasEnum.TABLE_NAME.getAlias() + ",\n" +
"\tnumeric_scale AS " + DbAliasEnum.NUM_SCALE.getAlias() + ",\n" +
"\t(CASE WHEN ( SELECT pa.attnum = ANY ( conkey ) FROM pg_constraint WHERE conrelid = pa.pg_oid AND contype = 'p' ) = 't' \n" +
"\tTHEN 1 ELSE 0 END ) " + DbAliasEnum.PRIMARY_KEY.getAlias() + "\t\n" +
"FROM\n" +
"\tinformation_schema.COLUMNS AS col\n" +
"LEFT JOIN (\n" +
"\tSELECT\n" +
"\t\t\t\t\t* \n" +
"\tFROM\n" +
" (SELECT *,oid AS pg_oid FROM pg_class WHERE relnamespace IN ( SELECT oid FROM pg_namespace WHERE nspname = " + ParamEnum.DB_SCHEMA.getParamSign() + " )) AS pc\n" +
"\tLEFT JOIN\n" +
"\t pg_attribute AS pat \n" +
"\tON \n" +
"\t\tpat.attrelid = pc.pg_oid\n" +
"\tWHERE \n" +
"\t\t\tpc.relname = " + ParamEnum.TABLE.getParamSign() + "\n" +
"\t) AS pa \n" +
"ON \n" +
"\tpa.attname = col.column_name \n" +
"WHERE\n" +
"\tcol.table_schema = " + ParamEnum.DB_SCHEMA.getParamSign() + " \n" +
"\tAND TABLE_NAME = " + ParamEnum.TABLE.getParamSign()
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getPostGreDbSchema());
list.add(table);
list.add(dbStruct.getPostGreDbSchema());
list.add(table);
}
},
/* POSITION()函数返回一个整数该整数表示子字符串在字符串中的位置。如果在字符串中未找到子字符串则POSITION()函数将返回零(0)。
如果子字符串或字符串参数为null则返回null */
TABLES(
"SELECT\n" +
" pt.*,\n" +
" pg_tab.relname AS " + DbAliasEnum.TABLE_NAME.getAlias() + ",\n" +
" pg_tab.reltuples AS " + DbAliasEnum.TABLE_SUM.getAlias() + ",\n" +
" pg_tab.nspname,\n" +
" CAST ( obj_description ( pg_tab.relfilenode, 'pg_class' ) AS VARCHAR ) AS " + DbAliasEnum.TABLE_COMMENT.getAlias() + "\n" +
"FROM\n" +
" pg_tables pt\n" +
"LEFT JOIN \n" +
"(SELECT \n" +
" * \n" +
"FROM\n" +
" pg_class pc\n" +
"LEFT JOIN \n" +
" pg_namespace pns\n" +
"ON\n" +
" pns.oid = pc.relnamespace\n" +
"WHERE\n" +
" pns.nspname = " + ParamEnum.DB_SCHEMA.getParamSign() + ") AS pg_tab\n" +
"ON\n" +
" pt.tablename = pg_tab.relname\n" +
"WHERE pt.schemaname = " + ParamEnum.DB_SCHEMA.getParamSign()
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getPostGreDbSchema());
list.add(dbStruct.getPostGreDbSchema());
}
},
/* POSITION()函数返回一个整数该整数表示子字符串在字符串中的位置。如果在字符串中未找到子字符串则POSITION()函数将返回零(0)。
如果子字符串或字符串参数为null则返回null */
TABLESANDVIEW(
"SELECT viewname as " + DbAliasEnum.TABLE_NAME.getAlias() + ", 'VIEW' as " + DbAliasEnum.TABLE_TYPE.getAlias() + " FROM pg_views WHERE schemaname = " + ParamEnum.DB_SCHEMA.getParamSign() + "\n" +
"UNION\n" +
"SELECT tablename as " + DbAliasEnum.TABLE_NAME.getAlias() + ",'TABLE' as " + DbAliasEnum.TABLE_TYPE.getAlias() + " FROM pg_tables WHERE schemaname = " + ParamEnum.DB_SCHEMA.getParamSign()
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getPostGreDbSchema());
list.add(dbStruct.getPostGreDbSchema());
}
},
TABLE(
TABLES.sqlFrame + " AND pg_tab.relname = " + ParamEnum.TABLE.getParamSign()
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getPostGreDbSchema());
list.add(dbStruct.getPostGreDbSchema());
list.add(table);
}
},
EXISTS_TABLE(
"SELECT COUNT (*) AS TOTAL \n" +
"FROM\n" +
"( \n" +
" SELECT relname AS F_TABLE_NAME FROM pg_class C WHERE relname = lower(" + ParamEnum.TABLE.getParamSign() + ") AND relnamespace IN \n" +
" ( \n" +
" SELECT oid FROM pg_namespace WHERE nspname = " + ParamEnum.DB_SCHEMA.getParamSign() + "\n" +
" ) \n" +
") AS COUNT_TAB"
){
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(table);
list.add(dbStruct.getPostGreDbSchema());
}
},
/* =============================== 定义语句 ==================================== */
// Data Definition Language简称 DDL用来建立数据库、数据库对象和定义列的命令。包括create、alter、drop
/**
* 建表语句
*/
CREATE(
"CREATE TABLE 《schema》.{table}(\n" +
"" +
"1:(PRIMARY KEY ({primaryColumn}))|" +
"2:({column} {dataType} [[NOT] [NULL]] [DEFAULT {defaultValue}])" +
",\n】)"
),
// SERIAL自增标识自增时1、不定义数据类型2、不定义默认值3、非空
CREATE_TABLE ("<CREATE> <TABLE> 《schema》.{table} <(>\n" +
"【{column} {dataType} [[NOT] [NULL]] [<DEFAULT> {defaultValue}] 】" +
"\n{primarykeys}" +
"\n<)>"){
@Override
public String createIncrement(String sqlFrame, Map<String, String> paramsMap) {
// 自增标识SERIAL
if(StringUtil.isNotEmpty(paramsMap.get("[AUTO_INCREMENT]"))){
sqlFrame = super.createIncrement(sqlFrame, paramsMap)
.replace("{dataType}", "[SERIAL]");
}
return sqlFrame;
}
public String createIndex(){
String model = "CREATE UNIQUE INDEX {indexName} ON {table}(【column】)";
return null;
}
},
COMMENT_TABLE ("COMMENT ON TABLE 《schema》.{table} IS {comment}"),
COMMENT_COLUMN ("COMMENT ON COLUMN 《schema》.{table}.{column} IS {comment}"),
DROP_TABLE ("DROP TABLE IF EXISTS 《schema》.{table}"),
ADD_COLUMN ("<ALTER> <TABLE> 《schema》.{table} ADD {column} {dataType}"),
DROP_COLUMN ("ALTER TABLE 《schema》.{table} DROP {column}"),
MODIFY_TYPE ("<ALTER> <TABLE> 《schema》.{table} <ALTER> <COLUMN> {column} <TYPE> {dataType}"),
RE_COLUMN_NAME ("<ALTER> <TABLE> 《schema》.{table} RENAME <COLUMN> {oldColumn} <TO> {newColumn}"),
RE_TABLE_NAME ("<ALTER> <TABLE> 《schema》.{oldTable} RENAME <TO> {newTable}"),
/**
* 修改: NOT NULL 约束
*/
ALTER_NOT_NULL ("<ALTER> <TABLE> 《schema》.{table} <MODIFY> {column} {datatype} [[NOT] [NULL]]"),
/**
* 修改: 默认值
*/
ALTER_DEFAULT ("<ALTER> <TABLE> 《schema》.{table} <ALTER> {column} <SET> <DEFAULT> {defaultValue}"),
/**
* 添加: 主键约束
*/
ALTER_PRIMARY ("<ALTER> <TABLE> 《schema》.{table} <ADD> CONSTRAINT {primaryKey} PRIMARY KEY (【{column},】)"),
/* =============================== DML操作语句 ==================================== */
// Data Manipulation Language简称 DML用来操纵数据库中数据的命令。包括select、insert、update、delete。
INSERT ("INSERT INTO 《schema》.{table}(【{column},】) VALUES (【{value},】)"),
DELETE_INFO ("DELETE FROM 《schema》.{table} WHERE {column} = {value}"),
ORDER_PAGE ("{selectSql} ORDER BY {orderColumn} [DESC] LIMIT {pageSize} OFFSET {beginIndex}"),
/* =============================== 其他 ==================================== */
CREATE_DATABASE("CREATE DATABASE \"{database}\""),
DROP_DATABASE("DROP DATABASE [IF EXISTS] {database}"),
CREATE_SCHEMA("CREATE SCHEMA \"{schema}\";"),
DROP_SCHEMA("DROP SCHEMA \"{schema}\" CASCADE"),
;
private String sqlFrame;
private final String dbEncode = DbBase.POSTGRE_SQL;
}

View File

@@ -0,0 +1,233 @@
package com.yunzhupaas.database.sql.enums;
import com.yunzhupaas.database.enums.DbAliasEnum;
import com.yunzhupaas.database.enums.ParamEnum;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.enums.base.SqlFrameBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
import java.util.Map;
/**
* SqlServer SQL语句模板
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/30
*/
@Getter
@AllArgsConstructor
public enum SqlSQLServerEnum implements SqlFrameBase {
/* =============================== 系统语句 ==================================== */
FIELDS("SELECT cast(a.name as varchar(50)) " + DbAliasEnum.FIELD.getAlias() + " ," +
" cast(case when exists(SELECT 1 FROM sysobjects where xtype='PK' and name in ( " +
" SELECT name FROM sysindexes WHERE indid in( " +
" SELECT indid FROM sysindexkeys WHERE id = a.id AND colid=a.colid ))) " +
" then '1' else '0' end as varchar(50)) " + DbAliasEnum.PRIMARY_KEY.getAlias() + ", " +
" cast(b.name as varchar(50)) " + DbAliasEnum.DATA_TYPE.getAlias() + ", " +
// " cast(COLUMNPROPERTY(a.id,a.name,'PRECISION') as varchar(50)) " +
// DbAliasConst.DATA_LENGTH + ", " +
" a.length " + DbAliasEnum.CHAR_LENGTH.getAlias() + ", " +
" a.xprec " + DbAliasEnum.NUM_PRECISION.getAlias() + ", " +
" a.xscale " + DbAliasEnum.NUM_SCALE.getAlias() + ", " +
" h.is_identity " + DbAliasEnum.IS_IDENTITY.getAlias() + ", " +
" cast(case when a.isnullable=0 then '0'else '1' end as varchar(50)) " + DbAliasEnum.ALLOW_NULL.getAlias()
+ ", " +
" cast(isnull(e.text,'') as varchar(50)) " + DbAliasEnum.DEFAULT_VALUE.getAlias() + ", " +
" cast(isnull(g.[value],'') as varchar(50)) " + DbAliasEnum.FIELD_COMMENT.getAlias() +
"\nFROM syscolumns a " +
"left join systypes b on a.xusertype=b.xusertype " +
"inner join sysobjects d on a.id=d.id and (d.xtype='U' or d.xtype='V') and d.name<>'dtproperties' " +
"left join syscomments e on a.cdefault=e.id " +
"left join sys.extended_properties g on a.id=g.major_id and a.colid=g.minor_id " +
"left join sys.extended_properties f on d.id=f.major_id and f.minor_id=0 " +
"left join sys.columns h ON d.id= h.object_id and a.name = h.name " +
"where d.name = " + ParamEnum.DB_NAME.getParamSign() +
"\norder by a.id,a.colorder") {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(table);
}
},
TABLES(
"SET NOCOUNT ON DECLARE\n" +
"@TABLEINFO TABLE (\n" +
"\tNAME VARCHAR ( 50 ),\n" +
"\tSUMROWS VARCHAR ( 11 ),\n" +
"\tRESERVED VARCHAR ( 50 ),\n" +
"\tDATA VARCHAR ( 50 ),\n" +
"\tINDEX_SIZE VARCHAR ( 50 ),\n" +
"\tUNUSED VARCHAR ( 50 ),\n" +
"\tPK VARCHAR ( 50 ) \n" +
") DECLARE\n" +
"@TABLENAME TABLE ( NAME VARCHAR ( 50 ) ) DECLARE\n" +
"@NAME VARCHAR ( 50 ) DECLARE\n" +
"@PK VARCHAR ( 50 ) INSERT INTO @TABLENAME ( NAME ) SELECT\n" +
"O.NAME \n" +
"FROM\n" +
"\tsysobjects O,\n" +
"\tsysindexes I \n" +
"WHERE\n" +
"\tO.ID = I.ID \n" +
"\tAND O.XTYPE = 'U' \n" +
"\tAND I.INDID < 2 \n" +
"\tAND O.UID = (SELECT schema_id FROM sys.schemas where name = "
+ ParamEnum.DB_SCHEMA.getParamSign() + ")\n" +
"ORDER BY\n" +
"\tI.ROWS DESC,\n" +
"\tO.NAME\n" +
"WHILE\n" +
"\t\tEXISTS ( SELECT 1 FROM @TABLENAME ) BEGIN\n" +
"\t\tSELECT TOP\n" +
"\t\t\t1 @NAME = NAME \n" +
"\t\tFROM\n" +
"\t\t\t@TABLENAME DELETE @TABLENAME \n" +
"\t\tWHERE\n" +
"\t\t\tNAME = @NAME DECLARE\n" +
"\t\t\t@OBJECTID INT \n" +
"\t\t\tSET @OBJECTID = OBJECT_ID( @NAME ) SELECT\n" +
"\t\t\t@PK = COL_NAME( @OBJECTID, COLID ) \n" +
"\t\tFROM\n" +
"\t\t\tsysobjects AS O\n" +
"\t\t\tINNER JOIN sysindexes AS I ON I.NAME = O.NAME\n" +
"\t\t\tINNER JOIN sysindexkeys AS K ON K.INDID = I.INDID \n" +
"\t\tWHERE\n" +
"\t\t\tO.XTYPE = 'PK' \n" +
"\t\t\tAND PARENT_OBJ = @OBJECTID \n" +
"\t\t\tAND K.ID = @OBJECTID INSERT INTO @TABLEINFO ( NAME, SUMROWS, RESERVED, DATA, INDEX_SIZE, UNUSED ) EXEC sys.sp_spaceused @NAME UPDATE @TABLEINFO \n"
+
"\t\t\tSET PK = @PK \n" +
"\t\tWHERE\n" +
"\t\t\tNAME = @NAME \n" +
"\tEND SELECT CAST\n" +
"\t\t( F.NAME AS VARCHAR ( 50 ) ) " + DbAliasEnum.TABLE_NAME.getAlias() + ",\n" +
"\t\tCAST ( ISNULL( P.TDESCRIPTION, F.NAME ) AS VARCHAR ( 50 ) ) "
+ DbAliasEnum.TABLE_COMMENT.getAlias() + ",\n" +
"\t\tCAST ( F.RESERVED AS VARCHAR ( 50 ) ) " + DbAliasEnum.TABLE_SIZE.getAlias() + ",\n" +
"\t\tCAST ( RTRIM( F.SUMROWS ) AS VARCHAR ( 50 ) ) " + DbAliasEnum.TABLE_SUM.getAlias() + ",\n" +
"\t\tCAST ( F.PK AS VARCHAR ( 50 ) ) " + DbAliasEnum.PRIMARY_KEY.getAlias() + " \n" +
"\tFROM\n" +
"\t\t@TABLEINFO F\n" +
"\t\tLEFT JOIN (\n" +
"\t\tSELECT\n" +
"\t\t\tNAME =\n" +
"\t\tCASE\n" +
"\t\t\t\t\n" +
"\t\t\t\tWHEN A.COLORDER = 1 THEN\n" +
"\t\t\t\tD.NAME ELSE '' \n" +
"\t\t\tEND,\n" +
"\t\t\tTDESCRIPTION =\n" +
"\t\tCASE\n" +
"\t\t\t\t\n" +
"\t\t\t\tWHEN A.COLORDER = 1 THEN\n" +
"\t\t\t\tISNULL( F.VALUE, '' ) ELSE '' \n" +
"\t\t\tEND \n" +
"\t\t\tFROM\n" +
"\t\t\t\tsyscolumns A\n" +
"\t\t\t\tLEFT JOIN systypes B ON A.XUSERTYPE = B.XUSERTYPE\n" +
"\t\t\t\tINNER JOIN sysobjects D ON A.ID = D.ID \n" +
"\t\t\t\tAND D.XTYPE = 'U' \n" +
"\t\t\t\tAND D.NAME <> 'DTPROPERTIES'\n" +
"\t\t\t\tLEFT JOIN sys.extended_properties F ON D.ID = F.MAJOR_ID \n" +
"\t\t\tWHERE\n" +
"\t\t\t\tA.COLORDER = 1 \n" +
"\t\t\t\tAND F.MINOR_ID = 0 \n" +
"\t\t\t) P ON F.NAME = P.NAME \n" +
"\t\tWHERE\n" +
"\t\t\t1 = 1 \n" +
"\tORDER BY\n" +
"\t" + DbAliasEnum.TABLE_NAME.getAlias()) {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getSqlServerDbSchema());
}
},
TABLESANDVIEW(
"SELECT s.Name as " + DbAliasEnum.TABLE_NAME.getAlias()
+ ",Convert(varchar(max),tbp.value) as " + DbAliasEnum.TABLE_COMMENT.getAlias()
+ ",s.type as " + DbAliasEnum.TABLE_TYPE.getAlias()
+ "\nFROM sysobjects s\n" +
"LEFT JOIN sys.extended_properties as tbp ON s.id=tbp.major_id and tbp.minor_id=0 AND (tbp.Name='MS_Description' OR tbp.Name is null) WHERE s.xtype IN('V','U')") {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getSqlServerDbSchema());
}
},
TABLE(
TABLES.sqlFrame.replace("1 = 1", "F.NAME = " + ParamEnum.TABLE.getParamSign())) {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(dbStruct.getSqlServerDbSchema());
list.add(table);
}
},
EXISTS_TABLE(
"SELECT COUNT (*) AS TOTAL FROM (" +
"SELECT table_name FROM INFORMATION_SCHEMA.TABLES where table_type = 'BASE TABLE' and TABLE_NAME = "
+ ParamEnum.TABLE.getParamSign()
+ ") AS COUNT_TAB") {
@Override
public void setStructParams(String table, DbStruct dbStruct, List<String> list) {
list.add(table);
}
},
/* =============================== 定义语句 ==================================== */
CREATE_TABLE(SqlDMEnum.CREATE_TABLE.getSqlFrame()) {
@Override
public String createIncrement(String sqlFrame, Map<String, String> paramsMap) {
return SqlDMEnum.CREATE_TABLE.createIncrement(sqlFrame, paramsMap);
}
},
// Data Definition Language简称 DDL用来建立数据库、数据库对象和定义列的命令。包括create、alter、drop
RE_TABLE_NAME("EXEC sp_rename {oldTable}, {newTable}"),
COMMENT_TABLE("EXEC sp_addextendedproperty 'MS_Description',N'{comment}','SCHEMA',N'dbo','TABLE',N'{table}'"),
COMMENT_COLUMN(
"EXEC sp_addextendedproperty 'MS_Description',N'{comment}','SCHEMA',N'dbo','TABLE',N'{table}','COLUMN',N'{column}'"),
ALTER_COLUMN("<ALTER> <TABLE> {table} <ADD> {column} {dataType} [[NOT] [NULL]] [<DEFAULT> {defaultValue}]"),
/*
* =============================== DML操作语句 ====================================
*/
// Data Manipulation Language简称
// DML用来操纵数据库中数据的命令。包括select、insert、update、delete。
/* 第二种方式offset fetch next方式SQL2012以上的版本才支持推荐使用 - */
SELECT_PAGE_NEW("{selectSql} [orderSql] OFFSET {beginIndex} rows fetch next {pageSize} rows only"),
/*
* row_number() over(order by {column})
* row_number() over(order by RAND()) 随机字段
* row_number() over(order by NEWID()) 临时ID
*/
ORDER_PAGE("SELECT * " +
"FROM " +
"(SELECT TOP {endIndex} ROW_NUMBER() OVER(ORDER BY {orderColumn}) YUNZHUPAAS_ROW,* " +
"FROM " +
"({selectSql}) AS YUNZHUPAAS_TAB ORDER BY YUNZHUPAAS_ROW) AS YUNZHUPAAS_TEMP_TABLE " +
"WHERE " +
"YUNZHUPAAS_ROW BETWEEN ({beginIndex}+1) AND {endIndex}"),
// offset /fetch next关键字 2012版本及以上才有
ORDER_PAGE2(
"SELECT \n" +
"\t*\n" +
"FROM\n" +
"\t({selectSql}) AS YUNZHUPAAS_TAB \n" +
"ORDER BY\n" +
"\t{orderColumn} \n" +
"OFFSET {beginIndex} ROWS FETCH NEXT {pageSize} ROWS ONLY"),
DB_TIME_SQL("Select CONVERT(varchar(100), GETDATE(), 120) as TIME"),
/* =============================== 其他 ==================================== */
;
public String sqlFrame;
private final String dbEncode = DbBase.SQL_SERVER;
}

View File

@@ -0,0 +1,302 @@
package com.yunzhupaas.database.sql.enums.base;
import com.yunzhupaas.database.model.dto.PrepSqlDTO;
import com.yunzhupaas.database.model.interfaces.DbSourceOrDbLink;
import com.yunzhupaas.database.sql.enums.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* 通用 SQL语句模板
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/17
*/
@Getter
@AllArgsConstructor
public enum SqlComEnum implements SqlFrameBase {
/*
* []:可选、<>:必填 《》:配置开关填写、{}:参数、【】:循环 N:(选择框架 =========================================
*/
/* =============================== 系统语句 ==================================== */
TABLES( SqlMySQLEnum.TABLES,
SqlOracleEnum.TABLES,
SqlSQLServerEnum.TABLES,
SqlDMEnum.TABLES,
SqlKingbaseESEnum.TABLES,
SqlPostgreSQLEnum.TABLES
),
TABLESANDVIEW( SqlMySQLEnum.TABLESANDVIEW,
SqlOracleEnum.TABLESANDVIEW,
SqlSQLServerEnum.TABLESANDVIEW,
SqlDMEnum.TABLESANDVIEW,
SqlKingbaseESEnum.TABLESANDVIEW,
SqlPostgreSQLEnum.TABLESANDVIEW
),
TABLE( SqlMySQLEnum.TABLE,
SqlOracleEnum.TABLE,
SqlSQLServerEnum.TABLE,
SqlDMEnum.TABLE,
SqlKingbaseESEnum.TABLE,
SqlPostgreSQLEnum.TABLE
),
FIELDS( SqlMySQLEnum.FIELDS,
SqlOracleEnum.FIELDS,
SqlSQLServerEnum.FIELDS,
SqlDMEnum.FIELDS,
SqlKingbaseESEnum.FIELDS,
SqlPostgreSQLEnum.FIELDS
),
EXISTS_TABLE( SqlMySQLEnum.EXISTS_TABLE,
SqlOracleEnum.EXISTS_TABLE,
SqlSQLServerEnum.EXISTS_TABLE,
SqlDMEnum.EXISTS_TABLE,
SqlKingbaseESEnum.EXISTS_TABLE,
SqlPostgreSQLEnum.EXISTS_TABLE
),
/* =============================== 定义语句 ==================================== */
// Data Definition Language简称 DDL用来建立数据库、数据库对象和定义列的命令。包括create、alter、drop
/**
* 创表
*/
CREATE_TABLE (SqlOracleEnum.CREATE_TABLE,
Arrays.asList(
"{table}",
"{column}",
"{dataType}",
"[<DEFAULT> {defaultValue}]",
"[[NOT] [NULL]]",
"[AUTO_INCREMENT]",
"[<COMMENT> {comment}]",
"{primarykeys}"
),
SqlMySQLEnum.CREATE_TABLE,
SqlSQLServerEnum.CREATE_TABLE,
SqlDMEnum.CREATE_TABLE,
SqlKingbaseESEnum.CREATE_TABLE,
SqlPostgreSQLEnum.CREATE_TABLE
),
ADD_COLUMN (SqlMySQLEnum.ALTER_ADD_MODIFY,
Arrays.asList(
"<ADD|MODIFY>",
"{table}",
"{column}",
"{dataType}",
"[[NOT] [NULL]]",
"[<DEFAULT> {defaultValue}]",
"{comment}"
),
SqlOracleEnum.ADD_COLUMN,
SqlPostgreSQLEnum.ADD_COLUMN,
SqlDMEnum.ALTER_ADD,
SqlKingbaseESEnum.ALTER_ADD,
SqlSQLServerEnum.ALTER_COLUMN
),
/**
* 删除表
*/
DROP_TABLE (SqlOracleEnum.DROP_TABLE,
Arrays.asList(
"{table}"
),
SqlMySQLEnum.DROP_TABLE
),
/**
* 表重命名
*/
RE_TABLE_NAME (SqlMySQLEnum.RE_TABLE_NAME,
Arrays.asList(
"{oldTable}",
"{newTable}"
),
SqlKingbaseESEnum.RE_TABLE_NAME,
SqlPostgreSQLEnum.RE_TABLE_NAME,
SqlSQLServerEnum.RE_TABLE_NAME
),
/**
* 表注释
*/
COMMENT_TABLE (SqlOracleEnum.COMMENT_TABLE,
Arrays.asList(
"{table}",
"'{comment}'"
),
SqlMySQLEnum.COMMENT_TABLE,
SqlSQLServerEnum.COMMENT_TABLE
),
/**
* 字段注释
*/
COMMENT_COLUMN (SqlOracleEnum.COMMENT_COLUMN,
Arrays.asList(
"{table}",
"{column}",
"'{comment}'",
"{dataType}",
"[DEFAULT {defaultValue}]"
),
SqlMySQLEnum.COMMENT_COLUMN,
SqlSQLServerEnum.COMMENT_COLUMN
),
/* =============================== DML操作语句 ==================================== */
// Data Manipulation Language简称 DML用来操纵数据库中数据的命令。包括select、insert、update、delete。
/**
* 获取表数据SQL
*/
SELECT_TABLE (SqlMySQLEnum.SELECT_TABLE,
Arrays.asList(
"{table}"
)
),
COUNT_SIZE (SqlMySQLEnum.COUNT_SIZE,
Arrays.asList(
"{totalAlias}",
"{selectSql}"
)
),
COUNT_SIZE_TABLE(SqlMySQLEnum.COUNT_TABLE_SIZE,
Arrays.asList(
"{totalAlias}",
"{table}"
)
),
INSERT (SqlMySQLEnum.INSERT,
Arrays.asList(
"{table}",
"[【{column},】]",
"【{value},】"
)
),
DELETE_ALL (SqlMySQLEnum.DELETE_ALL,
Collections.singletonList(
"{table}"
)
),
/* =============================== 后缀 ==================================== */
/**
* beginIndex起始下标
* = (currentPage - 1) * pageSize当前页 * 页大小)
* endIndex结束下标
* = currentPage * pageSize
* 先查询还是先排序
*/
ORDER_PAGE (SqlMySQLEnum.ORDER_PAGE,
Arrays.asList(
"{selectSql}",
"{orderColumn}",
"{beginIndex}",
"{endIndex}",
"{pageSize}",
"[DESC]"
),
SqlOracleEnum.ORDER_PAGE,
SqlSQLServerEnum.ORDER_PAGE,
SqlPostgreSQLEnum.ORDER_PAGE
),
/**
* ASCascend升序 1234 放空默认
* DESCdescend降序 4321
*/
ORDER (SqlMySQLEnum.ORDER,
Arrays.asList(
"{column}",
"[DESC]"
)
),
/**
* 模糊查询
* * : 多字符, c*c代表cc,cBc,cbc,cabdfec等
* % : 多个字符, %c%代表agdcagd等
* ? : 单个字符, %c%代表agdcagd等
* # : 单数字, k#k代表k1k,k8k,k0k
* [*] : 特殊字符, a[*]a代表a*a
* [a-z] : 字符范围, [a-z]代表a到z的26个字母中任意一个 指定一个范围中任意一个
*/
LIKE (SqlMySQLEnum.LIKE,
Arrays.asList(
"{selectSql}",
"{column}",
"{condition}"
)
),
;
private String sqlFrame;
private SqlFrameBase baseSqlEnum;
private List<SqlFrameBase> frameEnums;
private List<String> frameParamList;
private final String dbEncode = "common";
/**
* 构造
* @param baseSqlEnum 基础枚举其他数据库没有独特SQL遵循这个枚举的SQL
*/
SqlComEnum(SqlFrameBase baseSqlEnum, List<String> frameParamList) {
this.baseSqlEnum = baseSqlEnum;
this.sqlFrame = baseSqlEnum.getSqlFrame();
this.frameParamList = frameParamList;
this.frameEnums = new ArrayList<>();
this.frameEnums.add(baseSqlEnum);
}
/**
* 构造
* @param frameEnums 不同库自身对应的SQL框架
*/
SqlComEnum(SqlFrameBase baseSqlEnum, List<String> frameParamList, SqlFrameBase... frameEnums) {
this.baseSqlEnum = baseSqlEnum;
this.sqlFrame = baseSqlEnum.getSqlFrame();
this.frameParamList = frameParamList;
List<SqlFrameBase> frameEnumsList = new ArrayList<>(Arrays.asList(frameEnums));
frameEnumsList.add(baseSqlEnum);
this.frameEnums = frameEnumsList;
}
SqlComEnum(SqlFrameBase... frameEnums) {
this.frameEnums = Arrays.asList(frameEnums);
}
/**
* 获取子类的枚举
* @return 返回子类枚举
*/
public SqlFrameBase getSqlFrameEnum(String dbEncode){
if(this.getFrameEnums() != null){
for (SqlFrameBase sqlEnum : this.getFrameEnums()) {
if(sqlEnum.getDbEncode().equals(dbEncode)){
return sqlEnum;
}
}
}
return null;
}
public SqlFrameBase getSqlFrameEnum(SqlFrameBase sqlFrameBase){
if(this.getFrameEnums() != null){
for (SqlFrameBase sqlEnum : this.getFrameEnums()) {
if(sqlEnum.equals(sqlFrameBase)){
return sqlEnum;
}
}
}
return null;
}
public PrepSqlDTO getPrepSqlDto(DbSourceOrDbLink dataSourceMod, String table){
SqlFrameBase sysTemSqlEnum = getSqlFrameEnum(dataSourceMod.init().getDbType());
return sysTemSqlEnum.getPrepSqlDto(dataSourceMod, table);
}
}

View File

@@ -0,0 +1,146 @@
package com.yunzhupaas.database.sql.enums.base;
import com.yunzhupaas.database.model.dto.PrepSqlDTO;
import com.yunzhupaas.database.model.entity.DbLinkEntity;
import com.yunzhupaas.database.model.interfaces.DbSourceOrDbLink;
import com.yunzhupaas.database.source.DbBase;
import com.yunzhupaas.database.sql.model.DbStruct;
import com.yunzhupaas.database.sql.util.SqlFrameUtil;
import com.yunzhupaas.database.util.DbTypeUtil;
import com.yunzhupaas.database.util.TenantDataSourceUtil;
import com.yunzhupaas.exception.DataException;
import com.yunzhupaas.util.StringUtil;
import java.util.*;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.2.0
* @copyright 深圳市乐程软件有限公司
* @date 2024/3/16
*/
public interface SqlFrameBase {
/**
* 获取SQL框架
* @return ignore
*/
String getSqlFrame();
/**
* 获取数据库编码
* @return ignore
*/
String getDbEncode();
/**
* 获取枚举名
* @return ignore
*/
String name();
/**
* 设置结构性参数
* @param table 表
* @param dbStruct 结构模型
* @param list 参数
*/
default void setStructParams(String table, DbStruct dbStruct, List<String> list){}
/**
* 获取数据库结构性参数
* @param table 表
* @return 结构参数
*/
default PrepSqlDTO getPrepSqlDto(DbSourceOrDbLink dataSourceMod, String table){
List<String> list = new ArrayList<>();
TenantDataSourceUtil.initDataSourceTenantDbName(dataSourceMod);
setStructParams(table, dataSourceMod.getDbStruct(), list);
return new PrepSqlDTO(getSqlFrame(), list).withConn((DbLinkEntity) dataSourceMod);
}
/**
* 自动获取数据库SQL框架处理
* 下标在SQL框架枚举里面找对应关系
* @param params 参数集
* @return ignore
*/
default String getOutSql(String... params) throws DataException {
return getOutSqlByDb(null, params);
}
/**
* 指定数据库SQL框架处理
* @param params SQL参数
* @return SQL语句
* @throws DataException 枚举使用限制
*/
default String getOutSqlByDb(String dbEncode, String... params) throws DataException {
SqlComEnum sqlComEnum = null;
SqlFrameBase sqlFrameBase = null;
/* 确定SQL框架枚举 */
// 第一种:未明确引用枚举,提供数据库类型
DbBase dbBase;
try{
dbBase = DbTypeUtil.getEncodeDb(dbEncode);
}catch (Exception e){
dbBase = null;
}
if(this instanceof SqlComEnum){
sqlComEnum = ((SqlComEnum)this);
if(dbBase != null){
sqlFrameBase = sqlComEnum.getSqlFrameEnum(dbEncode);
}
if(sqlFrameBase == null){
sqlFrameBase = sqlComEnum.getBaseSqlEnum();
}
// 第二种:明确引用枚举
}else if(dbBase == null){
for (SqlComEnum conEnum : SqlComEnum.values()) {
sqlFrameBase = conEnum.getSqlFrameEnum(this);
if(sqlFrameBase != null){
sqlComEnum = conEnum;
break;
}
}
// 当引用枚举明确指出时,不允许引用其他枚举
if(sqlFrameBase == null){throw new DataException("此枚举SQL框架未被引用");}
// 第三种:明确引用枚举,提供数据库类型(冲突)
}else {
throw new DataException("请使用SqlComEnum来做引用");
}
return SqlFrameUtil.outSqlCommon(sqlFrameBase, sqlComEnum.getFrameParamList(), params);
}
/**
* SQL框架的一些各自的特殊处理
* @param sqlFrame SQL框架
* @param paramsMap 对应提供参数集合
* @return SQL语句
*/
default String createIncrement(String sqlFrame, Map<String, String> paramsMap){
if (StringUtil.isNotEmpty(paramsMap.get("[AUTO_INCREMENT]"))){
// 当自增时,字段非空且不需要默认值
sqlFrame = sqlFrame
.replace("[[NOT] [NULL]]", "")
.replace("[<DEFAULT> {defaultValue}]", "");
}
return sqlFrame;
}
default String createPrimaryKeys(String sqlFrame, Map<String, String> paramsMap){
String primaryStr = "";
if (StringUtil.isNotEmpty(paramsMap.get("{primarykeys}"))){
primaryStr = "\n, PRIMARY KEY (" + paramsMap.get("{primarykeys}") + ")";
}
return sqlFrame.replace("{primarykeys}", primaryStr);
}
default String createIndex(){
return "";
}
}

View File

@@ -0,0 +1,92 @@
package com.yunzhupaas.database.sql.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 类功能
*
* @author 云筑产品开发平台组
* @version V3.3
* @copyright 深圳市乐程软件有限公司
* @date 2024-06-10
*/
@Data
public class DbStruct {
/* ============= 通用 ============= */
/**
* 用户名
*/
private String userName;
/**
* 表空间
*/
private String dbTableSpace;
/* ============= Mysql ============= */
/**
* 库名
* Mysql目前没有使用到模式
*/
private String mysqlDbName;
/* ============= Oracle ============= */
/**
* 模式
* Oracle目前没有使用库名
* 与用户同名
*/
private String oracleDbSchema;
/**
* Oracle 额外参数
*/
private String oracleParam;
/* ============= SqlServer ============= */
/**
* 库名
*/
private String sqlServerDbName;
/**
* 模式(暂时不使用)
* 默认dbo
* 可选guest
*/
private String sqlServerDbSchema = "dbo";
/* ============= Dm ============= */
/**
* 模式
* Dm目前没有使用库名
* 与用户同名
*/
private String dmDbSchema;
/* ============= KingBase ============= */
/**
* 库名
*/
private String kingBaseDbName;
/**
* 模式
* 默认public
*/
private String kingBaseDbSchema = "public";
/* ============= PostGre ============= */
/**
* 库名
*/
private String postGreDbName;
/**
* 模式(暂时不使用)
* 默认public
*/
private String postGreDbSchema = "public";
}

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