org.sagacity.sqltoy.SqlToyContext Maven / Gradle / Ivy
package org.sagacity.sqltoy;
import java.sql.Connection;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
import javax.sql.DataSource;
import org.sagacity.sqltoy.config.EntityManager;
import org.sagacity.sqltoy.config.SqlConfigParseUtils;
import org.sagacity.sqltoy.config.SqlScriptLoader;
import org.sagacity.sqltoy.config.model.ElasticEndpoint;
import org.sagacity.sqltoy.config.model.EntityMeta;
import org.sagacity.sqltoy.config.model.SqlToyConfig;
import org.sagacity.sqltoy.config.model.SqlType;
import org.sagacity.sqltoy.integration.AppContext;
import org.sagacity.sqltoy.integration.ConnectionFactory;
import org.sagacity.sqltoy.integration.impl.SimpleConnectionFactory;
import org.sagacity.sqltoy.model.IgnoreKeyCaseMap;
import org.sagacity.sqltoy.model.OverTimeSql;
import org.sagacity.sqltoy.model.QueryExecutor;
import org.sagacity.sqltoy.plugins.FilterHandler;
import org.sagacity.sqltoy.plugins.FirstBizCodeTrace;
import org.sagacity.sqltoy.plugins.IUnifyFieldsHandler;
import org.sagacity.sqltoy.plugins.OverTimeSqlHandler;
import org.sagacity.sqltoy.plugins.SqlInterceptor;
import org.sagacity.sqltoy.plugins.TypeHandler;
import org.sagacity.sqltoy.plugins.datasource.DataSourceSelector;
import org.sagacity.sqltoy.plugins.datasource.impl.DefaultDataSourceSelector;
import org.sagacity.sqltoy.plugins.ddl.DDLFactory;
import org.sagacity.sqltoy.plugins.ddl.DialectDDLGenerator;
import org.sagacity.sqltoy.plugins.formater.SqlFormater;
import org.sagacity.sqltoy.plugins.function.FunctionUtils;
import org.sagacity.sqltoy.plugins.overtime.DefaultOverTimeHandler;
import org.sagacity.sqltoy.plugins.secure.DesensitizeProvider;
import org.sagacity.sqltoy.plugins.secure.FieldsSecureProvider;
import org.sagacity.sqltoy.plugins.secure.impl.DesensitizeDefaultProvider;
import org.sagacity.sqltoy.plugins.secure.impl.FieldsRSASecureProvider;
import org.sagacity.sqltoy.plugins.sharding.ShardingStrategy;
import org.sagacity.sqltoy.translate.TranslateManager;
import org.sagacity.sqltoy.translate.cache.TranslateCacheManager;
import org.sagacity.sqltoy.utils.BeanUtil;
import org.sagacity.sqltoy.utils.DataSourceUtils;
import org.sagacity.sqltoy.utils.DataSourceUtils.Dialect;
import org.sagacity.sqltoy.utils.QueryExecutorBuilder;
import org.sagacity.sqltoy.utils.ReservedWordsUtil;
import org.sagacity.sqltoy.utils.SqlUtil;
import org.sagacity.sqltoy.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.ttl.threadpool.TtlExecutors;
//------------------了解 sqltoy的关键优势: ----------------------------------------------------------------------------------------*/
//1、最简最直观的sql编写方式(不仅仅是查询语句),采用条件参数前置处理规整法,让sql语句部分跟客户端保持高度一致
//2、sql中支持注释(规避了对hint特性的影响,知道hint吗?搜oracle hint),和动态更新加载,便于开发和后期维护整个过程的管理
//3、支持缓存翻译和反向缓存条件检索(通过缓存将名称匹配成精确的key),实现sql简化和性能大幅提升
//4、支持快速分页和分页优化功能,实现分页最高级别的优化,同时还考虑到了cte多个with as情况下的优化支持
//5、支持并行查询
//6、根本杜绝sql注入问题
//7、支持行列转换、分组汇总求平均、同比环比计算,在于用算法解决复杂sql,同时也解决了sql跨数据库问题
//8、支持保留字自动适配
//9、支持跨数据库函数自适配,从而非常有利于一套代码适应多种数据库便于产品化,比如oracle的nvl,当sql在mysql环境执行时自动替换为ifnull
//10、支持分库分表
//11、提供了在新增和修改操作过程中公共字段插入和修改,如:租户、创建人、创建时间、修改时间等
//12、提供了统一数据权限传参和数据越权校验
//13、提供了取top、取random记录、树形表结构构造和递归查询支持、updateSaveFetch/updateFetch单次交互完成修改和查询等实用的功能
//14、sqltoy的update、save、saveAll、load 等对象crud操作并规避了jpa的缺陷,参见update(entity,String...forceUpdateProps)和updateFetch、updateSaveFetch
//15、提供了极为人性化的条件处理:排它性条件、日期条件加减和提取月末月初处理等
//16、提供了查询结果日期、数字格式化、安全脱敏处理,让复杂的事情变得简单,大幅简化sql和结果的二次处理工作
//17、提供了SqlInterceptor,可自行定义sql拦截器,用于类似租户过滤、sql注入的校验等
//--------------------------------------------------------------------------------------------------------------------------------*/
/**
* @project sagacity-sqltoy
* @description sqltoy 工具的上下文容器,提供对应的sql获取以及相关参数设置
* @author zhongxuchen
* @version v1.0,Date:2009-12-11
* @modify {Date:2018-1-5,增加对redis缓存翻译的支持}
* @modify {Date:2019-09-15,将跨数据库函数FunctionConverts统一提取到FunctionUtils中,实现不同数据库函数替换后的语句放入缓存,避免每次执行函数替换}
* @modify {Date:2020-05-29,调整mongo的注入方式,剔除之前MongoDbFactory模式,直接使用MongoTemplate}
* @modify {Date:2022-06-11,支持多个缓存翻译定义文件}
* @modify {Date:2022-10-14,增加humpMapResultTypeLabel设置结果为Map时是否驼峰化处理属性}
*/
public class SqlToyContext {
/**
* 定义日志
*/
protected final Logger logger = LoggerFactory.getLogger(SqlToyContext.class);
/**
* sqlToy 配置解析插件
*/
private SqlScriptLoader scriptLoader = new SqlScriptLoader();
/**
* 实体对象管理器,加载实体bean
*/
private EntityManager entityManager = new EntityManager();
/**
* sqltoy的翻译器插件(可以通过其完成对缓存的管理扩展)
*/
private TranslateManager translateManager = new TranslateManager();
/**
* 延时检测时长(避免应用一启动即进行检测,包含:缓存变更检测、sql文件变更检测)
*/
private int delayCheckSeconds = 30;
/**
* 默认查询数据库端提取记录量
*/
private int fetchSize = -1;
/**
* 统一公共字段赋值处理; 如修改时,为修改人和修改时间进行统一赋值; 创建时:为创建人、创建时间、修改人、修改时间进行统一赋值
*/
private IUnifyFieldsHandler unifyFieldsHandler;
/**
* 具体缓存实现(默认ehcache,可以根据自己喜好来自行扩展实现,sqltoy习惯将有争议的提供默认实现但用户可自行选择)
*/
private TranslateCacheManager translateCacheManager;
/**
* 自定义参数过滤处理器(防范性预留)
*/
private FilterHandler customFilterHandler;
/**
* map类型的resultType标题转驼峰模式
*/
private boolean humpMapResultTypeLabel = true;
/**
* 跳转超出数据页范围回到第一页
*/
private Boolean overPageToFirst;
/**
* 未匹配的数据库类型分页是否是limit ? offset ? 模式还是 limit ?,? 模式
*/
private boolean defaultPageOffset = true;
/**
* 执行超时sql自定义处理器
*/
private OverTimeSqlHandler overTimeSqlHandler = new DefaultOverTimeHandler();
/**
* @param unifyFieldsHandler the unifyFieldsHandler to set
*/
public void setUnifyFieldsHandler(IUnifyFieldsHandler unifyFieldsHandler) {
this.unifyFieldsHandler = unifyFieldsHandler;
}
/**
* @return the unifyFieldsHandler
*/
public IUnifyFieldsHandler getUnifyFieldsHandler() {
return unifyFieldsHandler;
}
/**
* sharding策略
*/
private HashMap shardingStrategys = new HashMap();
/**
* es的地址配置
*/
private HashMap elasticEndpoints = new HashMap();
/**
* 单记录保存采用identity、sequence主键策略,并返回主键值时,字段名称大小写处理(lower/upper)
*/
private IgnoreKeyCaseMap dialectReturnPrimaryColumnCase = new IgnoreKeyCaseMap();
/**
* 默认为default
*/
private String defaultElastic = "default";
/**
* 缓存类型,默认ehcache(可选:caffeine)
*/
private String cacheType = "ehcache";
/**
* 默认数据源名称,一般无需设置
*/
private String defaultDataSourceName;
/**
* @return the translateManager
*/
public TranslateManager getTranslateManager() {
return translateManager;
}
/**
* 批处理记录数量,默认为200
*/
private int batchSize = 200;
/**
* 分页单次提取数据长度限制(默认为10万条),防止通过pageNo=-1 进行全表数据级提取 pageFetchSizeLimit=-1 表示不做限制
*/
private int pageFetchSizeLimit = 100000;
/**
* 是否debug模式
*/
private boolean debug = false;
/**
* 超时打印sql(毫秒,默认30秒)
*/
private int printSqlTimeoutMillis = 30000;
/**
* 数据修改提示的记录数量阈值,默认2000条
*/
private int updateTipCount = 2000;
/**
* 获取MetaData的列标题处理策略:default:不做处理;upper:转大写;lower
*/
private String columnLabelUpperOrLower = "default";
/**
* 数据库类型
*/
private String dialect;
/*----------------snowflake参数,如不设置框架自动以本机IP来获取---- */
/**
* snowflake 集群节点id<31
*/
private Integer workerId;
/**
* 数据中心id<31
*/
private Integer dataCenterId;
/*----------------snowflake 参数---- ---------------------------- */
/**
* 服务器id(3位数字),用于22位和26位主键生成,不设置会自动根据本机IP生成
*/
private Integer serverId;
/**
* 默认数据库连接池
*/
private DataSource defaultDataSource;
/**
* sql脚本检测间隔时长(debug模式下默认3秒,非debug默认15秒)
*/
private Integer scriptCheckIntervalSeconds;
/**
* 提供自定义类型处理器,一般针对json等类型
*/
private TypeHandler typeHandler;
/**
* dataSource选择器,提供给开发者扩展窗口
*/
private DataSourceSelector dataSourceSelector = new DefaultDataSourceSelector();
/**
* 提供数据源获得connection的扩展(默认spring的实现)
*/
private ConnectionFactory connectionFactory;
/**
* 定义TranslateCacheManager 对应实现类
*/
private String translateCaffeineManagerClass = "org.sagacity.sqltoy.translate.cache.impl.TranslateCaffeineManager";
/**
* 定义mongo查询的实现类,默认基于spring实现,其他框架修改成对应实现类
*/
private String mongoQueryClass = "org.sagacity.sqltoy.integration.impl.SpringMongoQuery";
/**
* 分布式id产生器实现类
*/
private String distributeIdGeneratorClass = "org.sagacity.sqltoy.integration.impl.SpringRedisIdGenerator";
/**
* 获取bean的上下文容器
*/
private AppContext appContext;
/**
* 对sqltoy-default.properties 值的修改(一般情况下不会涉及)
*/
private Map dialectConfig;
/**
* 数据库保留字,用逗号分隔
*/
private String reservedWords;
// 如果是文件存储则使用classpath:开头
/**
* 安全私钥
*/
private String securePrivateKey;
/**
* 安全公钥
*/
private String securePublicKey;
/**
* 字段加解密实现类,sqltoy提供了RSA的默认实现
*/
private FieldsSecureProvider fieldsSecureProvider;
/**
* 当发现有重复sqlId时是否抛出异常,终止程序执行
*/
private boolean breakWhenSqlRepeat = true;
/**
* 编码格式
*/
private String encoding = "UTF-8";
/**
* 脱敏处理器
*/
private DesensitizeProvider desensitizeProvider;
/**
* 重新执行查询的数据库
*/
private String[] redoDataSources;
/**
* sql执行拦截器,提供对最终执行前的sql进行干预处理
*/
private List sqlInterceptors;
/**
* 方言映射
*/
private IgnoreKeyCaseMap dialectMap;
/**
* 拆分merge into 为updateAll 和 saveAllIgnoreExist 两步操作(1、seata分布式事务不支持merge)
*/
private boolean splitMergeInto = false;
/**
* sql格式化输出器(用于debug sql输出)
*/
private SqlFormater sqlFormater;
/**
* 变更操作型sql空白默认转为null
*/
private boolean executeSqlBlankToNull = true;
/**
* sql 日志输出时LocalDateTime类型的输出格式
*/
private String localDateTimeFormat = "yyyy-MM-dd HH:mm:ss";
/**
* sql 日志输出时LocalTime类型的输出格式
*/
private String localTimeFormat = "HH:mm:ss";
/**
* sqltoy的线程池名称
*/
private String taskExecutorName;
/**
* sqltoy的线程池
*/
private Executor taskExecutor = TtlExecutors.getTtlExecutor(ForkJoinPool.commonPool());
/**
* 默认一页数据记录条数
*/
private int defaultPageSize = 10;
/**
* 自动创建表
*/
private Boolean autoDDL = false;
/**
* 自定义通过pojo生成ddl实现类
*/
private DialectDDLGenerator dialectDDLGenerator;
/**
* 自定义获取业务代码调用点
*/
private FirstBizCodeTrace firstBizCodeTrace;
/**
* @todo 初始化
* @throws Exception
*/
public void initialize() throws Exception {
logger.debug("start init sqltoy ..............................");
// 加载sqltoy的各类参数,如db2是否要增加with
// ur等,详见org/sagacity/sqltoy/sqltoy-default.properties
SqlToyConstants.loadProperties(dialectConfig);
// 设置保留字
ReservedWordsUtil.put(reservedWords);
// 初始化方言对应的类别代码,避免线程安全
DataSourceUtils.initialize();
if (firstBizCodeTrace != null) {
SqlExecuteStat.firstBizCodeTrace = firstBizCodeTrace;
}
// 设置方言映射(默认OSCAR==>gaussdb)
if (dialectMap != null && !dialectMap.isEmpty()) {
DataSourceUtils.dialectMap = dialectMap;
}
if (dialectReturnPrimaryColumnCase != null) {
SqlToyConstants.dialectReturnPrimaryColumnCase = dialectReturnPrimaryColumnCase;
}
// 设置默认非spring等框架下的连接获取处理
if (appContext == null && connectionFactory == null) {
connectionFactory = new SimpleConnectionFactory();
}
// 初始化默认dataSource
initDefaultDataSource();
// 设置workerId和dataCenterId,为使用snowflake主键ID产生算法服务
SqlToyConstants.setWorkerAndDataCenterId(workerId, dataCenterId, serverId);
// 初始化脚本加载器
scriptLoader.initialize(this.debug, delayCheckSeconds, scriptCheckIntervalSeconds, breakWhenSqlRepeat);
// 初始化翻译器,update 2021-1-23 增加caffeine缓存支持
if (translateCacheManager == null && "caffeine".equalsIgnoreCase(this.cacheType)) {
translateManager.initialize(this, (TranslateCacheManager) Class.forName(translateCaffeineManagerClass)
.getDeclaredConstructor().newInstance(), delayCheckSeconds);
} else {
translateManager.initialize(this, translateCacheManager, delayCheckSeconds);
}
// 初始化实体对象管理器(此功能已经无实际意义,已经改为即用即加载而非提前加载)
entityManager.initialize(this);
// 设置默认fetchSize
SqlToyConstants.FETCH_SIZE = this.fetchSize;
SqlToyConstants.executeSqlBlankToNull = this.executeSqlBlankToNull;
SqlToyConstants.DEFAULT_PAGE_SIZE = this.defaultPageSize;
SqlToyConstants.localDateTimeFormat = this.localDateTimeFormat;
SqlToyConstants.localTimeFormat = this.localTimeFormat;
// 初始化sql执行统计的基本参数
SqlExecuteStat.setDebug(this.debug);
SqlExecuteStat.setOverTimeSqlHandler(overTimeSqlHandler);
SqlExecuteStat.setPrintSqlTimeoutMillis(this.printSqlTimeoutMillis);
// sql格式化
SqlExecuteStat.setSqlFormater(this.sqlFormater);
// 字段加解密实现类初始化
if (null != fieldsSecureProvider) {
fieldsSecureProvider.initialize(this.encoding, securePrivateKey, securePublicKey);
} else if (StringUtil.isNotBlank(securePrivateKey) && StringUtil.isNotBlank(securePublicKey)) {
if (fieldsSecureProvider == null) {
fieldsSecureProvider = new FieldsRSASecureProvider();
}
fieldsSecureProvider.initialize(this.encoding, securePrivateKey, securePublicKey);
}
// 默认的脱敏处理器
if (desensitizeProvider == null) {
desensitizeProvider = new DesensitizeDefaultProvider();
}
// 向数据库创建表结构、或更新表结构
if (this.autoDDL != null && this.autoDDL == true) {
DataSource createDDLDB = getDefaultDataSource();
if (createDDLDB == null && dataSourceSelector != null) {
createDDLDB = dataSourceSelector.getDataSource(appContext, null, null, null, null);
}
if (createDDLDB != null) {
DDLFactory.createDDL(this, entityManager.getAllEntities(), createDDLDB);
}
}
logger.debug("sqltoy init complete!");
}
/**
* @todo 获取service并调用其指定方法获取报表数据
* @param beanName
* @param method
* @param args
* @return
*/
public Object getServiceData(String beanName, String method, Object[] args) {
if (StringUtil.isBlank(beanName) || StringUtil.isBlank(method)) {
return null;
}
try {
Object beanDefine = null;
if (appContext.containsBean(beanName)) {
beanDefine = appContext.getBean(beanName);
} else if (beanName.indexOf(".") > 0) {
beanDefine = appContext.getBean(Class.forName(beanName));
} else {
return null;
}
return BeanUtil.invokeMethod(beanDefine, method, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @todo 获取bean
* @param beanName
* @return
*/
public Object getBean(Object beanName) {
try {
if (beanName instanceof String) {
return appContext.getBean(beanName.toString());
}
return appContext.getBean((Class) beanName);
} catch (Exception e) {
e.printStackTrace();
logger.error("从springContext中获取Bean:{} 错误!{}", e.getMessage());
}
return null;
}
/**
* @todo 获取数据源
* @param dataSourceName
* @return
*/
public DataSource getDataSourceBean(String dataSourceName) {
if (StringUtil.isBlank(dataSourceName)) {
return null;
}
// 优先使用扩展来实现
if (dataSourceSelector != null) {
return dataSourceSelector.getDataSourceBean(appContext, dataSourceName);
} else if (appContext.containsBean(dataSourceName)) {
return (DataSource) appContext.getBean(dataSourceName);
}
return null;
}
/**
* @TODO 保留一个获取查询的sql(针对报表平台)
* @param sqlKey
* @return
*/
public SqlToyConfig getSqlToyConfig(String sqlKey) {
return getSqlToyConfig(sqlKey, SqlType.search, (getDialect() == null) ? "" : getDialect(), null);
}
public SqlToyConfig getSqlToyConfig(String sqlKey, SqlType sqlType, String dialect) {
if (StringUtil.isBlank(sqlKey)) {
throw new IllegalArgumentException("sql or sqlId is null!");
}
return scriptLoader.getSqlConfig(sqlKey, sqlType, dialect, null,
SqlType.search.equals(sqlType) ? true : SqlToyConstants.executeSqlBlankToNull);
}
/**
* @todo 获取sql对应的配置模型(请阅读scriptLoader,硬code的sql对应模型也利用了内存来存放非每次都动态构造对象)
* @param sqlKey
* @param sqlType
* @param dialect
* @param paramValues
* @return
*/
public SqlToyConfig getSqlToyConfig(String sqlKey, SqlType sqlType, String dialect, Object paramValues) {
if (StringUtil.isBlank(sqlKey)) {
throw new IllegalArgumentException("sql or sqlId is null!");
}
return scriptLoader.getSqlConfig(sqlKey, sqlType, dialect, paramValues,
SqlType.search.equals(sqlType) ? true : SqlToyConstants.executeSqlBlankToNull);
}
public SqlToyConfig getSqlToyConfig(QueryExecutor queryExecutor, SqlType sqlType, String dialect) {
String sqlKey = queryExecutor.getInnerModel().sql;
if (StringUtil.isBlank(sqlKey)) {
throw new IllegalArgumentException("sql or sqlId is null!");
}
// 查询语句补全select * from table,避免一些sql直接从from 开始
if (SqlType.search.equals(sqlType)) {
if (queryExecutor.getInnerModel().resultType != null) {
sqlKey = SqlUtil.completionSql(this, (Class) queryExecutor.getInnerModel().resultType, sqlKey);
} // update 2021-12-7 sql 类似 from table where xxxx 形式,补全select *
else if (!SqlConfigParseUtils.isNamedQuery(sqlKey)
&& StringUtil.matches(sqlKey.toLowerCase().trim(), "^from\\W")) {
sqlKey = "select * ".concat(sqlKey);
}
}
return scriptLoader.getSqlConfig(sqlKey, sqlType, dialect, QueryExecutorBuilder.getParamValues(queryExecutor),
queryExecutor.getInnerModel().blankToNull);
}
/**
* @return the scriptLoader
*/
public SqlScriptLoader getScriptLoader() {
return scriptLoader;
}
/**
* @param workerId the workerId to set
*/
public void setWorkerId(Integer workerId) {
this.workerId = workerId;
}
/**
* @param dataCenterId the dataCenterId to set
*/
public void setDataCenterId(Integer dataCenterId) {
this.dataCenterId = dataCenterId;
}
/**
* @param serverId the serverId to set
*/
public void setServerId(Integer serverId) {
this.serverId = serverId;
}
/**
* @return the batchSize
*/
public int getBatchSize() {
return batchSize;
}
/**
* @param batchSize the batchSize to set
*/
public void setBatchSize(int batchSize) {
// 必须要大于零
if (batchSize > 0) {
this.batchSize = batchSize;
}
}
/**
* @todo 返回sharding策略实例
* @param strategyName
* @return
*/
public ShardingStrategy getShardingStrategy(String strategyName) {
// hashMap可以事先不赋值,直接定义spring的bean
if (shardingStrategys.containsKey(strategyName)) {
return shardingStrategys.get(strategyName);
}
ShardingStrategy shardingStrategy = (ShardingStrategy) appContext.getBean(strategyName);
if (shardingStrategy != null) {
shardingStrategys.put(strategyName, shardingStrategy);
}
return shardingStrategy;
}
/**
* @param shardingStrategys the shardingStrategys to set
*/
public void setShardingStrategys(HashMap shardingStrategys) {
this.shardingStrategys = shardingStrategys;
}
/**
* @return the entityManager
*/
public EntityManager getEntityManager() {
return entityManager;
}
public EntityMeta getEntityMeta(Class> entityClass) {
return entityManager.getEntityMeta(this, entityClass);
}
/**
* @TODO 根据表名获取实体对象的信息(需要配置:spring.sqltoy.packagesToScan 提前加载pojo,sqltoy
* 默认是无需配置即用即载)
* @param tableName
* @return
*/
public EntityMeta getEntityMeta(String tableName) {
return entityManager.getEntityMeta(tableName);
}
/**
* @TODO 判断是否是实体bean
* @param entityClass
* @return
*/
public boolean isEntity(Class> entityClass) {
return entityManager.isEntity(this, entityClass);
}
/**
*
*
1、第一步调用解析,注意是单个sqlId的片段
* 2、根据业务情况,调整id,sqlToyConfig.setId(),注意:这步并非必要,当报表平台时,报表里面多个sql,每个id在本报表范围内唯一,当很多个报表时会冲突,所以需要整合rptId+sqlId
* 3、putSqlToyConfig(SqlToyConfig sqlToyConfig) 放入交由sqltoy统一管理
*
*
* @todo 提供可以动态增加解析sql片段配置的接口,完成SqltoyConfig模型的构造(用于第三方平台集成,如报表平台等),
* @param sqlSegment
* @return
* @throws Exception
*/
public synchronized SqlToyConfig parseSqlSegment(Object sqlSegment) throws Exception {
return scriptLoader.parseSqlSagment(sqlSegment);
}
/**
* @todo 将构造好的SqlToyConfig放入交给sqltoy统一托管(在托管前可以对id进行重新组合确保id的唯一性,比如报表平台,将rptId+sqlId组合成一个全局唯一的id)
* @param sqlToyConfig
* @throws Exception
*/
public synchronized void putSqlToyConfig(SqlToyConfig sqlToyConfig) throws Exception {
scriptLoader.putSqlToyConfig(sqlToyConfig);
}
/**
* @TODO 开放sql文件动态交由开发者挂载
* @param sqlFile
* @throws Exception
*/
public synchronized void parseSqlFile(Object sqlFile) throws Exception {
scriptLoader.parseSqlFile(sqlFile);
}
/**
* @return the dialect
*/
public String getDialect() {
return dialect;
}
/**
* @TODO 规整方言定义,避免设置的名称跟系统定义不一致(一般无需设置)
* @param dialect the dialect to set
*/
public void setDialect(String dialect) {
if (StringUtil.isBlank(dialect)) {
return;
}
// 规范数据库方言命名(避免方言和版本一起定义)
String tmp = dialect.toLowerCase();
if (tmp.startsWith(Dialect.MYSQL)) {
this.dialect = Dialect.MYSQL;
} else if (tmp.startsWith(Dialect.ORACLE11)) {
this.dialect = Dialect.ORACLE11;
} else if (tmp.startsWith(Dialect.ORACLE)) {
this.dialect = Dialect.ORACLE;
} else if (tmp.startsWith(Dialect.POSTGRESQL)) {
this.dialect = Dialect.POSTGRESQL;
} else if (tmp.startsWith(Dialect.GREENPLUM)) {
this.dialect = Dialect.POSTGRESQL;
} else if (tmp.startsWith(Dialect.DB2)) {
this.dialect = Dialect.DB2;
} else if (tmp.startsWith(Dialect.SQLSERVER)) {
this.dialect = Dialect.SQLSERVER;
} else if (tmp.startsWith(Dialect.SQLITE)) {
this.dialect = Dialect.SQLITE;
} else if (tmp.startsWith(Dialect.GAUSSDB)) {
this.dialect = Dialect.GAUSSDB;
} else if (tmp.startsWith(Dialect.MOGDB)) {
this.dialect = Dialect.MOGDB;
} else if (tmp.startsWith(Dialect.MARIADB)) {
this.dialect = Dialect.MARIADB;
} else if (tmp.startsWith(Dialect.CLICKHOUSE)) {
this.dialect = Dialect.CLICKHOUSE;
} else if (tmp.startsWith(Dialect.OCEANBASE)) {
this.dialect = Dialect.OCEANBASE;
} else if (tmp.startsWith(Dialect.DM)) {
this.dialect = Dialect.DM;
} else if (tmp.startsWith(Dialect.TIDB)) {
this.dialect = Dialect.TIDB;
} else if (tmp.startsWith(Dialect.KINGBASE)) {
this.dialect = Dialect.KINGBASE;
} else if (tmp.startsWith(Dialect.IMPALA) || tmp.contains("kudu")) {
this.dialect = Dialect.IMPALA;
} else if (tmp.startsWith(Dialect.TDENGINE)) {
this.dialect = Dialect.TDENGINE;
} else if (tmp.startsWith(Dialect.ES)) {
this.dialect = Dialect.ES;
} else if (tmp.startsWith(Dialect.H2)) {
this.dialect = Dialect.H2;
} else if (tmp.startsWith(Dialect.OSCAR)) {
this.dialect = Dialect.OSCAR;
} else if (tmp.startsWith(Dialect.VASTBASE)) {
this.dialect = Dialect.VASTBASE;
} else if (tmp.startsWith(Dialect.OPENGAUSS)) {
this.dialect = Dialect.OPENGAUSS;
} else {
this.dialect = dialect;
}
scriptLoader.setDialect(this.dialect);
}
/**
* @return the debug
*/
public boolean isDebug() {
return debug;
}
/**
* @param debug the debug to set
*/
public void setDebug(boolean debug) {
this.debug = debug;
}
/**
* @param packagesToScan the packagesToScan to set
*/
public void setPackagesToScan(String[] packagesToScan) {
entityManager.setPackagesToScan(packagesToScan);
}
/**
* @return the pageFetchSizeLimit
*/
public int getPageFetchSizeLimit() {
return pageFetchSizeLimit;
}
/**
* @param pageFetchSizeLimit the pageFetchSizeLimit to set
*/
public void setPageFetchSizeLimit(int pageFetchSizeLimit) {
this.pageFetchSizeLimit = pageFetchSizeLimit;
}
/**
* @param recursive the recursive to set
*/
public void setRecursive(boolean recursive) {
entityManager.setRecursive(recursive);
}
/**
* @param annotatedClasses the annotatedClasses to set
*/
public void setAnnotatedClasses(String[] annotatedClasses) {
entityManager.setAnnotatedClasses(annotatedClasses);
}
public void setDialectConfig(Map dialectConfig) {
this.dialectConfig = dialectConfig;
}
public void setSqlResourcesDir(String sqlResourcesDir) {
scriptLoader.setSqlResourcesDir(sqlResourcesDir);
}
public void setSqlResources(List sqlResources) {
scriptLoader.setSqlResources(sqlResources);
}
public void setEncoding(String encoding) {
this.encoding = encoding;
scriptLoader.setEncoding(encoding);
}
/**
* functionConverts=close表示关闭
*
* @param functionConverts the functionConverts to set
*/
public void setFunctionConverts(Object functionConverts) {
if (functionConverts == null) {
return;
}
if (functionConverts instanceof List) {
FunctionUtils.setFunctionConverts((List) functionConverts);
} else if (functionConverts instanceof String[]) {
FunctionUtils.setFunctionConverts(Arrays.asList((String[]) functionConverts));
} else if (functionConverts instanceof String) {
String converts = (String) functionConverts;
if (StringUtil.isBlank(converts) || "default".equals(converts) || "defaults".equals(converts)) {
FunctionUtils.setFunctionConverts(Arrays.asList("default"));
} // close 标记已经没有必要
else if (!"close".equalsIgnoreCase(converts)) {
FunctionUtils.setFunctionConverts(Arrays.asList(converts.split("\\,")));
}
}
}
/**
* @param translateConfig the translateConfig to set
*/
public void setTranslateConfig(String translateConfig) {
translateManager.setTranslateConfig(translateConfig);
}
/**
* @param uncachedKeyResult the nocacheKeyResult to set
*/
public void setUncachedKeyResult(String uncachedKeyResult) {
SqlToyConstants.setUncachedKeyResult(uncachedKeyResult);
}
public AppContext getAppContext() {
return appContext;
}
public void setAppContext(AppContext appContext) {
this.appContext = appContext;
}
public void initDefaultDataSource() {
if (StringUtil.isNotBlank(defaultDataSourceName)) {
this.defaultDataSource = getDataSourceBean(defaultDataSourceName);
}
}
public DataSource getDefaultDataSource() {
return defaultDataSource;
}
/**
* @param elasticEndpointList the elasticConfigs to set
*/
public void setElasticEndpoints(List elasticEndpointList) {
if (elasticEndpointList == null || elasticEndpointList.isEmpty()) {
return;
}
// 第一个作为默认值
if (StringUtil.isBlank(defaultElastic)) {
defaultElastic = elasticEndpointList.get(0).getId();
}
for (ElasticEndpoint config : elasticEndpointList) {
// 初始化restClient
config.initRestClient();
elasticEndpoints.put(config.getId().toLowerCase(), config);
}
}
public ElasticEndpoint getElasticEndpoint(String id) {
ElasticEndpoint result = elasticEndpoints.get(StringUtil.isBlank(id) ? defaultElastic : id.toLowerCase());
// 取不到,则可能sql中自定义url地址,自行构建模型,按指定的url进行查询
if (result == null) {
return new ElasticEndpoint(id);
}
return result;
}
/**
* @return the printSqlTimeoutMillis
*/
public int getPrintSqlTimeoutMillis() {
return printSqlTimeoutMillis;
}
/**
* @param printSqlTimeoutMillis the printSqlTimeoutMillis to set
*/
public void setPrintSqlTimeoutMillis(int printSqlTimeoutMillis) {
this.printSqlTimeoutMillis = printSqlTimeoutMillis;
}
/**
* @param keywordSign the keywordSign to set
*/
public void setKeywordSign(String keywordSign) {
SqlToyConstants.keywordSign = keywordSign;
}
/**
* @param scriptCheckIntervalSeconds the scriptCheckIntervalSeconds to set
*/
public void setScriptCheckIntervalSeconds(int scriptCheckIntervalSeconds) {
this.scriptCheckIntervalSeconds = scriptCheckIntervalSeconds;
}
public void setDelayCheckSeconds(int delayCheckSeconds) {
this.delayCheckSeconds = delayCheckSeconds;
}
public void setTranslateCacheManager(TranslateCacheManager translateCacheManager) {
this.translateCacheManager = translateCacheManager;
}
public String getDefaultElastic() {
return defaultElastic;
}
public void setDefaultElastic(String defaultElastic) {
this.defaultElastic = defaultElastic;
}
/**
* @param reservedWords the reservedWords to set
*/
public void setReservedWords(String reservedWords) {
this.reservedWords = reservedWords;
}
/**
* @return the typeHandler
*/
public TypeHandler getTypeHandler() {
return typeHandler;
}
/**
* @param typeHandler the typeHandler to set
*/
public void setTypeHandler(TypeHandler typeHandler) {
this.typeHandler = typeHandler;
}
/**
* @param cacheType the cacheType to set
*/
public void setCacheType(String cacheType) {
this.cacheType = cacheType;
}
public void destroy() {
try {
scriptLoader.destroy();
translateManager.destroy();
} catch (Exception e) {
}
}
/**
* @return the dataSourceSelector
*/
public DataSourceSelector getDataSourceSelector() {
return dataSourceSelector;
}
/**
* @param dataSourceSelector the dataSourceSelector to set
*/
public void setDataSourceSelector(DataSourceSelector dataSourceSelector) {
this.dataSourceSelector = dataSourceSelector;
}
/**
* @return the fetchSize
*/
public int getFetchSize() {
return fetchSize;
}
/**
* @param fetchSize the fetchSize to set
*/
public void setFetchSize(int fetchSize) {
this.fetchSize = fetchSize;
}
public void setDefaultDataSource(DataSource defaultDataSource) {
this.defaultDataSource = defaultDataSource;
}
public void setDefaultDataSourceName(String defaultDataSourceName) {
this.defaultDataSourceName = defaultDataSourceName;
}
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public Connection getConnection(DataSource datasource) {
return connectionFactory.getConnection(datasource);
}
public void releaseConnection(Connection conn, DataSource dataSource) {
connectionFactory.releaseConnection(conn, dataSource);
}
public void setBreakWhenSqlRepeat(boolean breakWhenSqlRepeat) {
this.breakWhenSqlRepeat = breakWhenSqlRepeat;
}
public void setSecurePrivateKey(String securePrivateKey) {
this.securePrivateKey = securePrivateKey;
}
public void setSecurePublicKey(String securePublicKey) {
this.securePublicKey = securePublicKey;
}
public void setFieldsSecureProvider(FieldsSecureProvider fieldsSecureProvider) {
this.fieldsSecureProvider = fieldsSecureProvider;
}
public FieldsSecureProvider getFieldsSecureProvider() {
return fieldsSecureProvider;
}
public DesensitizeProvider getDesensitizeProvider() {
return desensitizeProvider;
}
public void setDesensitizeProvider(DesensitizeProvider desensitizeProvider) {
this.desensitizeProvider = desensitizeProvider;
}
public FilterHandler getCustomFilterHandler() {
return customFilterHandler;
}
public void setCustomFilterHandler(FilterHandler customFilterHandler) {
this.customFilterHandler = customFilterHandler;
}
public void setTranslateCaffeineManagerClass(String translateCaffeineManagerClass) {
this.translateCaffeineManagerClass = translateCaffeineManagerClass;
}
public String getDistributeIdGeneratorClass() {
return distributeIdGeneratorClass;
}
public void setDistributeIdGeneratorClass(String distributeIdGeneratorClass) {
this.distributeIdGeneratorClass = distributeIdGeneratorClass;
}
public String getMongoQueryClass() {
return mongoQueryClass;
}
public void setMongoQueryClass(String mongoQueryClass) {
this.mongoQueryClass = mongoQueryClass;
}
public OverTimeSqlHandler getOverTimeSqlHandler() {
return overTimeSqlHandler;
}
public void setOverTimeSqlHandler(OverTimeSqlHandler overTimeSqlHandler) {
this.overTimeSqlHandler = overTimeSqlHandler;
}
/**
* @TODO 获取执行最慢的sql
* @param size 提取记录数量
* @param hasSqlId 是否是xml中定义含id的sql(另外一种就是代码中直接写的sql)
* @return
*/
public List getSlowestSql(int size, boolean hasSqlId) {
return overTimeSqlHandler.getSlowest(size, hasSqlId);
}
public String getColumnLabelUpperOrLower() {
return columnLabelUpperOrLower;
}
public void setColumnLabelUpperOrLower(String columnLabelUpperOrLower) {
this.columnLabelUpperOrLower = columnLabelUpperOrLower;
}
public String[] getRedoDataSources() {
return redoDataSources;
}
public void setRedoDataSources(String[] redoDataSources) {
this.redoDataSources = redoDataSources;
}
public List getSqlInterceptors() {
return sqlInterceptors;
}
public boolean hasSqlInterceptors() {
if (sqlInterceptors == null || sqlInterceptors.isEmpty()) {
return false;
}
return true;
}
public void setSqlInterceptors(List sqlInterceptors) {
this.sqlInterceptors = sqlInterceptors;
}
public boolean isSplitMergeInto() {
return splitMergeInto;
}
public void setSplitMergeInto(boolean splitMergeInto) {
this.splitMergeInto = splitMergeInto;
}
public boolean isHumpMapResultTypeLabel() {
return humpMapResultTypeLabel;
}
public void setHumpMapResultTypeLabel(boolean humpMapResultTypeLabel) {
this.humpMapResultTypeLabel = humpMapResultTypeLabel;
}
public int getUpdateTipCount() {
return updateTipCount;
}
public void setUpdateTipCount(int updateTipCount) {
this.updateTipCount = updateTipCount;
}
public boolean isExecuteSqlBlankToNull() {
return executeSqlBlankToNull;
}
public void setExecuteSqlBlankToNull(boolean executeSqlBlankToNull) {
this.executeSqlBlankToNull = executeSqlBlankToNull;
}
public Boolean getOverPageToFirst() {
return overPageToFirst;
}
public void setOverPageToFirst(Boolean overPageToFirst) {
this.overPageToFirst = overPageToFirst;
}
public void setTaskExecutorName(String taskExecutorName) {
this.taskExecutorName = taskExecutorName;
}
public Executor getTaskExecutor() {
if (StringUtil.isBlank(taskExecutorName) || !appContext.containsBean(taskExecutorName)) {
return taskExecutor;
} else {
return (Executor) appContext.getBean(taskExecutorName);
}
}
public void setTaskExecutor(Executor taskExecutor) {
this.taskExecutor = taskExecutor;
}
/**
* @param sqlFormater the sqlFormater to set
*/
public void setSqlFormater(SqlFormater sqlFormater) {
this.sqlFormater = sqlFormater;
}
public void setDefaultPageSize(int defaultPageSize) {
this.defaultPageSize = defaultPageSize;
}
public boolean isDefaultPageOffset() {
return defaultPageOffset;
}
public void setDefaultPageOffset(boolean defaultPageOffset) {
this.defaultPageOffset = defaultPageOffset;
}
public Boolean getAutoDDL() {
return autoDDL;
}
public void setAutoDDL(Boolean autoDDL) {
this.autoDDL = autoDDL;
}
/**
* @param dialectMap the dialectMap to set
*/
public void setDialectMap(Map dialectMap) {
if (dialectMap != null && !dialectMap.isEmpty()) {
this.dialectMap = new IgnoreKeyCaseMap(dialectMap);
}
}
/**
* @param localDateTimeFormat the localDateTimeFormat to set
*/
public void setLocalDateTimeFormat(String localDateTimeFormat) {
this.localDateTimeFormat = localDateTimeFormat;
}
/**
* @param localTimeFormat the localTimeFormat to set
*/
public void setLocalTimeFormat(String localTimeFormat) {
this.localTimeFormat = localTimeFormat;
}
/**
* @return the dialectDDLGenerator
*/
public DialectDDLGenerator getDialectDDLGenerator() {
return dialectDDLGenerator;
}
/**
* @param dialectDDLGenerator the dialectDDLGenerator to set
*/
public void setDialectDDLGenerator(DialectDDLGenerator dialectDDLGenerator) {
this.dialectDDLGenerator = dialectDDLGenerator;
}
public void setFirstBizCodeTrace(FirstBizCodeTrace firstBizCodeTrace) {
this.firstBizCodeTrace = firstBizCodeTrace;
}
/**
* @return the dialectReturnPrimaryColumnCase
*/
public IgnoreKeyCaseMap getDialectReturnPrimaryColumnCase() {
return dialectReturnPrimaryColumnCase;
}
/**
* @param dialectReturnPrimaryColumnCase the dialectReturnPrimaryColumnCase to
* set
*/
public void setDialectReturnPrimaryColumnCase(IgnoreKeyCaseMap dialectReturnPrimaryColumnCase) {
this.dialectReturnPrimaryColumnCase = dialectReturnPrimaryColumnCase;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy