All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitee.qdbp.jdbc.plugins.DbPluginHelper Maven / Gradle / Ivy

package com.gitee.qdbp.jdbc.plugins;

import java.lang.reflect.Array;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import com.gitee.qdbp.able.convert.BeanToMapConverter;
import com.gitee.qdbp.able.convert.MapToBeanConverter;
import com.gitee.qdbp.able.convert.ObjectTypeConverter;
import com.gitee.qdbp.able.jdbc.base.OrderByCondition;
import com.gitee.qdbp.able.jdbc.base.UpdateCondition;
import com.gitee.qdbp.able.jdbc.base.WhereCondition;
import com.gitee.qdbp.able.jdbc.condition.TableJoin;
import com.gitee.qdbp.jdbc.model.AllFieldColumn;
import com.gitee.qdbp.jdbc.model.DbType;
import com.gitee.qdbp.jdbc.model.DbVersion;
import com.gitee.qdbp.jdbc.model.MainDbType;
import com.gitee.qdbp.jdbc.model.OmitStrategy;
import com.gitee.qdbp.jdbc.model.SimpleFieldColumn;
import com.gitee.qdbp.jdbc.model.TablesFieldColumn;
import com.gitee.qdbp.jdbc.model.TypedDbVariable;
import com.gitee.qdbp.jdbc.operator.DbBaseOperator;
import com.gitee.qdbp.jdbc.result.RowToBeanMapper;
import com.gitee.qdbp.jdbc.result.RowToBeanMapper.FactoryOfTable;
import com.gitee.qdbp.jdbc.result.RowToBeanMapper.FactoryOfTables;
import com.gitee.qdbp.jdbc.result.RowToMapMapper;
import com.gitee.qdbp.jdbc.utils.DbTypes;
import com.gitee.qdbp.jdbc.utils.ParseTools;
import com.gitee.qdbp.staticize.tags.base.Taglib;
import com.gitee.qdbp.tools.property.PropertyContainer;
import com.gitee.qdbp.tools.utils.ConvertTools;
import com.gitee.qdbp.tools.utils.VerifyTools;
import org.springframework.jdbc.core.SqlParameterValue;

/**
 * 插件帮助类
 *
 * @author zhaohuihua
 * @version 20210626
 */
public class DbPluginHelper {

    public interface Aware {

        void setPlugins(DbPluginHelper plugins);
    }

    private final DbPluginContainer plugins;
    private final ParseTools parseTools;

    DbPluginHelper(DbPluginContainer plugins) {
        this.plugins = plugins;
        this.parseTools = new ParseTools(this);
    }

    /** 解析工具类 **/
    public ParseTools parseTools() {
        return parseTools;
    }

    /** 获取配置项 **/
    public PropertyContainer getSqlConfig() {
        return this.plugins.getSqlConfig();
    }

    /** 通过配置项检查是否支持某选项 **/
    public boolean configSupports(String configKey, DbVersion version) {
        return configSupports(configKey, null, version);
    }

    /** 通过配置项检查是否支持某选项 **/
    public boolean configSupports(String configKey, String defaultValue, DbVersion version) {
        String value = plugins.getSqlConfig().getStringUseDefValue(configKey, defaultValue);
        return version.matchesWith(value);
    }

    protected int getRealJdbcType(int jdbcType, DbVersion dbVersion) {
        // 如果支持CLOB/NCLOB字段, 将需要调用PreparedStatement.setClob方法
        // postgresql不支持CLOB, org.postgresql.jdbc.PgPreparedStatement.setClob, 报NOT_IMPLEMENTED错误
        if (jdbcType == Types.CLOB || jdbcType == Types.NCLOB) {
            if (!this.configSupports("supports.clob", dbVersion)) {
                return Types.VARCHAR;
            }
        }
        return jdbcType;
    }

    /**
     * 将变量转换为数据库字段值
* 基本对象不做转换, 直接返回, 其他对象转换为基本对象后返回
* 基本对象是指Boolean/Character/Date/Number/String * * @param variable 变量 * @param dialect 数据库方言 * @return 转换后的字段值对象 */ public Object variableToDbValue(Object variable, SqlDialect dialect) { if (variable instanceof Collection) { Collection list = (Collection) variable; List result = new ArrayList<>(); for (Object item : list) { result.add(variableToDbValue(item, dialect)); } return result; } else if (variable != null && variable.getClass().isArray()) { Object[] array = (Object[]) variable; Object[] result = (Object[]) Array.newInstance(variable.getClass().getComponentType(), array.length); for (int i = 0; i < array.length; i++) { result[i] = variableToDbValue(array[i], dialect); } return result; } else { if (variable instanceof SqlParameterValue) { return variable; } VariableToDbValueConverter converter = plugins.getToDbValueConverter(); Object result = converter.convert(variable); if (result instanceof TypedDbVariable) { // 转换结果指定了类型 TypedDbVariable temp = (TypedDbVariable) result; int jdbcType = getRealJdbcType(temp.getJdbcType(), dialect.dbVersion()); return new SqlParameterValue(jdbcType, temp.getValue()); } else if (variable instanceof TypedDbVariable) { // 入参指定了类型 TypedDbVariable typed = (TypedDbVariable) variable; int jdbcType = getRealJdbcType(typed.getJdbcType(), dialect.dbVersion()); return new SqlParameterValue(jdbcType, result); } else if (result instanceof Character) { // Character类型不能自动识别 // @see org.springframework.jdbc.core.StatementCreatorUtils.setValue // 调用的是PreparedStatement.setObject(int index, Object x) // 而不是PreparedStatement.setObject(int index, Object x, int Types.xxx) return new SqlParameterValue(Types.VARCHAR, variable); } else { return result; } } } /** * 将变量转换为字符串, 用于拼接SQL
* 如字符串会返回单引号括起来的'stringValue', Boolean会返回1或0
* 日期: MYSQL: '2019-06-01 12:34:56.789'
* ORACLE: TO_TIMESTAMP('2019-06-01 12:34:56.789', 'YYYY-MM-DD HH24:MI:SS.FF') * * @param variable 变量 * @param dialect 数据库方言 * @return 转换后的字符串 */ public String variableToString(Object variable, SqlDialect dialect) { if (variable instanceof Collection) { Collection list = (Collection) variable; List result = new ArrayList<>(); for (Object item : list) { result.add(variableToString(item, dialect)); } return ConvertTools.joinToString(result, ',', false); } else if (variable != null && variable.getClass().isArray()) { Object[] array = (Object[]) variable; String[] result = new String[array.length]; for (int i = 0; i < array.length; i++) { result[i] = variableToString(array[i], dialect); } return ConvertTools.joinToString(result, ',', false); } else { VariableToDbValueConverter converter = plugins.getToDbValueConverter(); Object result = converter.convert(variable); if (result instanceof TypedDbVariable) { TypedDbVariable temp = (TypedDbVariable) result; result = temp.getValue(); } else if (result instanceof SqlParameterValue) { SqlParameterValue temp = (SqlParameterValue) result; result = temp.getValue(); } if (result == null) { return "NULL"; } else if (result instanceof Number) { return result.toString(); } else if (result instanceof CharSequence) { return dialect.variableToString(result.toString()); } else if (result instanceof Boolean) { return dialect.variableToString((Boolean) result); } else if (result instanceof Date) { return dialect.variableToString((Date) result); } else if (result instanceof Character) { return dialect.variableToString(result.toString()); } else { return dialect.variableToString(result.toString()); } } } /** * 将代码中写的数据类型转换为java.sql.Types中的数据类型 * * @param dataType 代码中的数据类型
* 1.来自SQL模板中, 如#{createTime,jdbcType=TIMESTAMP}
* 2.来自实体类上的注解, 如@Column(columnDefinition="TIMESTAMP NOT NULL") * @return java.sql.Types中的数据类型 * @see java.sql.Types * @see JdbcDataTypeResolver */ public Integer parseJdbcDataType(String dataType) { JdbcDataTypeResolver resolver = plugins.getJdbcDataTypeResolver(); return resolver.parseDataType(dataType); } /** * 获取Jdbc数据类型转换类 * * @return JdbcDataTypeResolver */ public JdbcDataTypeResolver getJdbcDataTypeResolver() { return plugins.getJdbcDataTypeResolver(); } /** * 可用的数据库类型
* 除MainDbType以外, 可通过plugins.addDbType()注册其他数据库类型 * * @return 数据库类型列表 */ public List getAvailableDbTypes() { return plugins.getAvailableDbTypes(); } /** * 判断数据库类型是否有效 * * @param dbType 数据库类型字符串 * @return 是否有效 */ public boolean isAvailableDbType(String dbType) { if (dbType == null || dbType.length() == 0) { return false; } List dbTypes = getAvailableDbTypes(); for (DbType item : dbTypes) { if (DbTypes.equals(item, MainDbType.Unknown)) { continue; } if (item.name().equalsIgnoreCase(dbType)) { return true; } } return false; } /** * 解析数据库类型 * * @param dbType 数据库类型字符串 * @return 数据库类型对象 */ public DbType parseDbType(String dbType) { if (dbType == null || dbType.length() == 0) { return null; } List dbTypes = getAvailableDbTypes(); for (DbType item : dbTypes) { if (DbTypes.equals(item, MainDbType.Unknown)) { continue; } if (item.name().equalsIgnoreCase(dbType)) { return item; } } return MainDbType.Unknown; } /** * 新建一个SQL标签库
* 默认的标签库为classpath:settings/qdbc/qdbc.taglib.txt
* 可通过plugins.setSqlTaglibPath()修改 * * @return SQL标签库 */ public Taglib newSqlTaglib() { return plugins.getSqlTaglibCreator().create(); } /** * 转换原始关键字, 如sysdate/CURRENT_TIMESTAMP之前的互转 * * @param rawValue 原生值, 如sysdate * @param dialect 数据库方言 * @return 转换后的值, 如mysql的CURRENT_TIMESTAMP, SqlServer的GETDATE() * @see RawValueConverter */ public String resolveRawValue(String rawValue, SqlDialect dialect) { RawValueConverter converter = plugins.getRawValueConverter(); return converter.convert(rawValue, dialect); } /** 获取对象类型转换处理类 **/ public ObjectTypeConverter getObjectTypeConverter() { return plugins.getObjectTypeConverter(); } /** 获取Row到Map的转换处理类 **/ public RowToMapMapper getRowToMapConverter() { return plugins.getRowToMapConverter(); } /** 获取Row到Bean的转换处理类 (单表) **/ public RowToBeanMapper getRowToBeanMapper(Class clazz) { FactoryOfTable factory = plugins.getTableRowToBeanFactory(); return factory.getRowToBeanMapper(clazz); } /** 获取Row到Bean的转换处理类 (多表关联) **/ public RowToBeanMapper getRowToBeanMapper(TableJoin tables, Class clazz) { FactoryOfTables factory = plugins.getTablesRowToBeanFactory(); return factory.getRowToBeanMapper(tables, clazz); } /** 获取Map到JavaBean的转换处理类 **/ public MapToBeanConverter getMapToBeanConverter() { return plugins.getMapToBeanConverter(); } /** JavaBean到Map的转换处理类 **/ public BeanToMapConverter getBeanToMapConverter() { return plugins.getBeanToMapConverter(); } /** 获取JavaBean到数据库条件的转换处理类 **/ public DbConditionConverter getDbConditionConverter() { return plugins.getDbConditionConverter(); } /** 实体类逻辑删除数据状态填充策略 **/ public EntityFieldFillStrategy getEntityFieldFillStrategy() { return plugins.getEntityFieldFillStrategy(); } /** 实体类逻辑删除数据状态填充策略 **/ public EntityDataStateFillStrategy getEntityDataStateFillStrategy() { return plugins.getEntityDataStateFillStrategy(); } /** 根据DbType生成SqlDialect **/ public SqlDialect buildSqlDialect(DbType dbType) { return buildSqlDialect(new DbVersion(dbType)); } /** 根据DbVersion生成SqlDialect **/ public SqlDialect buildSqlDialect(DbVersion version) { SqlDialect.Creator creator = plugins.getSqlDialectCreator(); return creator.create(version); } /** 获取自定义WhereSqlBuilder **/ public > B getWhereSqlBuilder(Class type) { return plugins.getWhereSqlBuilder(type); } /** 获取自定义WhereSqlBuilder **/ public > B getWhereSqlBuilder(T condition) { @SuppressWarnings("unchecked") Class type = (Class) condition.getClass(); return plugins.getWhereSqlBuilder(type); } /** 获取自定义UpdateSqlBuilder **/ public > B getUpdateSqlBuilder(Class type) { return plugins.getUpdateSqlBuilder(type); } /** 获取自定义UpdateSqlBuilder **/ public > B getUpdateSqlBuilder(T condition) { @SuppressWarnings("unchecked") Class type = (Class) condition.getClass(); return plugins.getUpdateSqlBuilder(type); } /** 获取自定义UpdateSqlBuilder **/ public > B getOrderBySqlBuilder(Class type) { return plugins.getOrderBySqlBuilder(type); } /** 获取自定义UpdateSqlBuilder **/ public > B getOrderBySqlBuilder(T condition) { @SuppressWarnings("unchecked") Class type = (Class) condition.getClass(); return plugins.getOrderBySqlBuilder(type); } /** * 根据运算符获取WhereOperator处理类 * * @param operatorType 运算符 * @return WhereOperator处理类 */ public DbBaseOperator getWhereOperator(String operatorType) { DbOperatorContainer container = plugins.getOperatorContainer(); return container == null ? null : container.getWhereOperator(operatorType); } /** * 根据运算符获取UpdateOperator处理类 * * @param operatorType 运算符 * @return UpdateOperator处理类 */ public DbBaseOperator getUpdateOperator(String operatorType) { DbOperatorContainer container = plugins.getOperatorContainer(); return container == null ? null : container.getUpdateOperator(operatorType); } /** * 格式化SQL语句 * * @param sql 待格式化的SQL语句 * @param indent 缩进层数 * @param version 数据库版本 * @return 已格式化的SQL语句 */ public String formatSql(String sql, int indent, DbVersion version) { SqlFormatter formatter = plugins.getSqlFormatter(); return formatter.format(sql, indent, version); } /** * 替换SQL语句 * * @param sql 源SQL语句 * @param version 数据库版本 * @return 替换后的SQL语句 */ public String replaceSql(String sql, DbVersion version) { SqlReplacer replacer = plugins.getSqlReplacer(); return replacer.replace(sql, version); } /** * 查找数据库版本信息 * * @param datasource 数据源 * @return 数据库版本信息 */ public DbVersion findDbVersion(DataSource datasource) { DbVersionFinder finder = plugins.getDbVersionFinder(); return finder.findDbVersion(datasource); } /** 获取SQL模板扫描处理类 **/ public SqlFileScanner getSqlFileScanner() { return plugins.getSqlFileScanner(); } /** 获取SQL片断的选项配置类 **/ public SqlFragmentOptions getSqlFragmentOptions() { return plugins.getSqlFragmentOptions(); } /** 获取字段值校验处理类 **/ public ColumnValueValidator getColumnValueValidator() { return plugins.getColumnValueValidator(); } /** 获取命名转换接口 **/ public JdbcNamingConverter getNamingConverter() { return plugins.getNamingConverter(); } /** 获取批量操作的省略策略配置 **/ public OmitStrategy getOmitStrategyOfBatchExecutor() { return plugins.getOmitStrategyOfBatchSql(); } /** 获取IN语句的省略策略配置 **/ public OmitStrategy getOmitStrategyOfInSql() { return plugins.getOmitStrategyOfInSql(); } /** 多表关联列信息的解析器 **/ public TablesFieldColumnParser getTablesFieldColumnParser() { return plugins.getTablesFieldColumnParser(); } /** 根据数据库类型获取批量新增处理类 **/ public BatchInsertExecutor getBatchInsertExecutor(DbVersion version) { return plugins.getBatchInsertExecutor(version); } /** 根据数据库类型获取批量更新处理类 **/ public BatchUpdateExecutor getBatchUpdateExecutor(DbVersion version) { return plugins.getBatchUpdateExecutor(version); } /** Entity的表名缓存 **/ private final Map, String> entityTableNameCache = new HashMap<>(); /** * 扫描表名信息(有缓存) * * @param clazz 类名 * @return 表名 */ public String parseTableName(Class clazz) { VerifyTools.requireNonNull(clazz, "class"); if (entityTableNameCache.containsKey(clazz)) { return entityTableNameCache.get(clazz); } TableInfoScans scans = plugins.getTableInfoScans(); String tableName = scans.scanTableName(clazz); entityTableNameCache.put(clazz, tableName); return tableName; } /** Entity的主键缓存 **/ private final Map, SimpleFieldColumn> entityPrimaryKeyCache = new HashMap<>(); /** * 扫描获取主键(有缓存) * * @param clazz 类名 * @return 主键 */ public SimpleFieldColumn parsePrimaryKey(Class clazz) { VerifyTools.requireNonNull(clazz, "class"); if (entityPrimaryKeyCache.containsKey(clazz)) { return entityPrimaryKeyCache.get(clazz); } AllFieldColumn all = parseAllFieldColumns(clazz); SimpleFieldColumn pk = all.findPrimaryKey(); entityPrimaryKeyCache.put(clazz, pk); return pk; } /** TableJoin的列名缓存 **/ private final Map> joinColumnsCache = new HashMap<>(); /** * 扫描获取字段名和数据库列名的映射表(有缓存) * * @param tables 表关联对象 * @return AllFieldColumn: fieldName - columnName */ public AllFieldColumn parseAllFieldColumns(TableJoin tables) { VerifyTools.requireNonNull(tables, "tables"); String cacheKey = tables.getTableFeatures(true); if (joinColumnsCache.containsKey(cacheKey)) { return joinColumnsCache.get(cacheKey); } TablesFieldColumnParser parser = plugins.getTablesFieldColumnParser(); List all = parser.parseFieldColumns(tables); AllFieldColumn fieldColumns = new AllFieldColumn<>(all); joinColumnsCache.put(cacheKey, fieldColumns); return fieldColumns; } /** Entity的列名缓存 **/ private final Map, AllFieldColumn> entityColumnsCache = new HashMap<>(); /** * 扫描获取字段名和数据库列名的映射表(有缓存) * * @param clazz 类型 * @return AllFieldColumn: fieldName - columnName */ public AllFieldColumn parseAllFieldColumns(Class clazz) { VerifyTools.requireNonNull(clazz, "class"); if (entityColumnsCache.containsKey(clazz)) { return entityColumnsCache.get(clazz); } else { TableInfoScans scans = plugins.getTableInfoScans(); List fields = scans.scanColumnList(clazz); if (fields.isEmpty()) { String m = "Fields not found, please check config of TableInfoScans, class=" + clazz.getName(); throw new IllegalArgumentException(m); } AllFieldColumn all = new AllFieldColumn<>(fields); entityColumnsCache.put(clazz, all); return all; } } }