Search in sources :

Example 6 with ShardingStrategyConfig

use of org.sagacity.sqltoy.config.model.ShardingStrategyConfig in project sagacity-sqltoy by chenrenfei.

the class EntityQuery method tableSharding.

/**
 * @TODO 设置分表策略,再复杂场景则推荐用xml的sql中定义
 * @param strategy
 * @param paramNames 分表策略依赖的参数
 * @return
 */
public EntityQuery tableSharding(String strategy, String... paramNames) {
    ShardingStrategyConfig sharding = new ShardingStrategyConfig(1);
    sharding.setStrategy(strategy);
    sharding.setFields(paramNames);
    sharding.setAliasNames(paramNames);
    innerModel.tableSharding = sharding;
    return this;
}
Also used : ShardingStrategyConfig(org.sagacity.sqltoy.config.model.ShardingStrategyConfig)

Example 7 with ShardingStrategyConfig

use of org.sagacity.sqltoy.config.model.ShardingStrategyConfig in project sagacity-sqltoy by chenrenfei.

the class EntityQuery method dbSharding.

/**
 * @TODO 设置分库策略
 * @param strategy
 * @param paramNames
 * @return
 */
public EntityQuery dbSharding(String strategy, String... paramNames) {
    ShardingStrategyConfig sharding = new ShardingStrategyConfig(0);
    sharding.setStrategy(strategy);
    sharding.setFields(paramNames);
    sharding.setAliasNames(paramNames);
    innerModel.dbSharding = sharding;
    return this;
}
Also used : ShardingStrategyConfig(org.sagacity.sqltoy.config.model.ShardingStrategyConfig)

Example 8 with ShardingStrategyConfig

use of org.sagacity.sqltoy.config.model.ShardingStrategyConfig in project sagacity-sqltoy by chenrenfei.

the class SqlToyDaoSupport method findEntityBase.

/**
 * @TODO 提供findEntity的基础实现,供对外接口包装,额外开放了resultClass的自定义功能
 * @param entityClass
 * @param page        如分页查询则需指定,非分页则传null
 * @param entityQuery
 * @param resultClass 指定返回结果类型
 * @param isCount
 * @return
 */
private Object findEntityBase(Class entityClass, Page page, EntityQuery entityQuery, Class resultClass, boolean isCount) {
    EntityMeta entityMeta = getEntityMeta(entityClass);
    EntityQueryExtend innerModel = entityQuery.getInnerModel();
    String translateFields = "";
    // 将缓存翻译对应的查询补充到select column 上,形成select keyColumn as viewColumn 模式
    if (!innerModel.translates.isEmpty()) {
        Iterator<Translate> iter = innerModel.translates.values().iterator();
        String keyColumn;
        TranslateExtend extend;
        while (iter.hasNext()) {
            extend = iter.next().getExtend();
            // 将java模式的字段名称转化为数据库字段名称
            keyColumn = entityMeta.getColumnName(extend.keyColumn);
            if (keyColumn == null) {
                keyColumn = extend.keyColumn;
            }
            // 保留字处理
            keyColumn = ReservedWordsUtil.convertWord(keyColumn, null);
            translateFields = translateFields.concat(",").concat(keyColumn).concat(" as ").concat(extend.column);
        }
    }
    // 将notSelect构造成select,形成统一处理机制
    String[] selectFieldAry = null;
    Set<String> notSelect = innerModel.notSelectFields;
    if (notSelect != null) {
        List<String> selectFields = new ArrayList<String>();
        for (String field : entityMeta.getFieldsArray()) {
            if (!notSelect.contains(field.toLowerCase())) {
                selectFields.add(field);
            }
        }
        if (selectFields.size() > 0) {
            selectFieldAry = new String[selectFields.size()];
            selectFields.toArray(selectFieldAry);
        }
    } else {
        selectFieldAry = innerModel.fields;
    }
    // 指定的查询字段
    String fields = "";
    if (selectFieldAry != null && selectFieldAry.length > 0) {
        int index = 0;
        String colName;
        HashSet<String> cols = new HashSet<String>();
        boolean notAllPureField = false;
        for (String field : selectFieldAry) {
            // 去除重复字段
            if (!cols.contains(field)) {
                colName = entityMeta.getColumnName(field);
                // 非表字段对应pojo的属性名称
                if (colName == null) {
                    colName = field;
                    // 非字段名称
                    if (!entityMeta.getColumnFieldMap().containsKey(colName.toLowerCase())) {
                        notAllPureField = true;
                    } else {
                        // 保留字处理
                        colName = ReservedWordsUtil.convertWord(colName, null);
                    }
                } else {
                    // 保留字处理
                    colName = ReservedWordsUtil.convertWord(colName, null);
                }
                if (index > 0) {
                    fields = fields.concat(",");
                }
                fields = fields.concat(colName);
                index++;
                cols.add(field);
            }
        }
        // select 字段中可能存在max(field)或field as xxx等非字段形式
        if (notAllPureField) {
            fields = SqlUtil.convertFieldsToColumns(entityMeta, fields);
        }
    } else {
        fields = entityMeta.getAllColumnNames();
    }
    String sql = "select ".concat((innerModel.distinct) ? " distinct " : "").concat(fields).concat(translateFields).concat(" from ").concat(entityMeta.getSchemaTable(null, null));
    // where条件
    String where = "";
    // 动态组织where 后面的条件语句,此功能并不建议使用,where 一般需要指定明确条件
    if (StringUtil.isBlank(innerModel.where)) {
        if (innerModel.values != null && innerModel.values.length > 0) {
            where = SqlUtil.wrapWhere(entityMeta);
        }
    } else {
        where = SqlUtil.convertFieldsToColumns(entityMeta, innerModel.where);
    }
    if (StringUtil.isNotBlank(where)) {
        sql = sql.concat(" where ").concat(where);
    }
    // 分组和having
    if (StringUtil.isNotBlank(innerModel.groupBy)) {
        sql = sql.concat(" group by ").concat(SqlUtil.convertFieldsToColumns(entityMeta, innerModel.groupBy));
        if (StringUtil.isNotBlank(innerModel.having)) {
            sql = sql.concat(" having ").concat(SqlUtil.convertFieldsToColumns(entityMeta, innerModel.having));
        }
    }
    // 处理order by 排序
    if (!innerModel.orderBy.isEmpty()) {
        sql = sql.concat(" order by ");
        Iterator<Entry<String, String>> iter = innerModel.orderBy.entrySet().iterator();
        Entry<String, String> entry;
        String columnName;
        int index = 0;
        while (iter.hasNext()) {
            entry = iter.next();
            columnName = entityMeta.getColumnName(entry.getKey());
            if (columnName == null) {
                columnName = entry.getKey();
            }
            // 保留字处理
            columnName = ReservedWordsUtil.convertWord(columnName, null);
            if (index > 0) {
                sql = sql.concat(",");
            }
            // entry.getValue() is order way,like: desc or " "
            sql = sql.concat(columnName).concat(entry.getValue());
            index++;
        }
    }
    QueryExecutor queryExecutor;
    Class resultType = (resultClass == null) ? entityClass : resultClass;
    // :named 模式(named模式参数值必须存在)
    if (SqlConfigParseUtils.hasNamedParam(where) && StringUtil.isBlank(innerModel.names)) {
        queryExecutor = new QueryExecutor(sql, (innerModel.values == null || innerModel.values.length == 0) ? null : (Serializable) innerModel.values[0]).resultType(resultType).dataSource(getDataSource(innerModel.dataSource)).fetchSize(innerModel.fetchSize).maxRows(innerModel.maxRows);
    } else {
        queryExecutor = new QueryExecutor(sql).names(innerModel.names).values(innerModel.values).resultType(resultType).dataSource(getDataSource(innerModel.dataSource)).fetchSize(innerModel.fetchSize).maxRows(innerModel.maxRows);
    }
    // 设置是否空白转null
    queryExecutor.getInnerModel().blankToNull = innerModel.blankToNull;
    // 设置额外的缓存翻译
    if (!innerModel.translates.isEmpty()) {
        queryExecutor.getInnerModel().translates.putAll(innerModel.translates);
    }
    // 设置额外的参数条件过滤
    if (!innerModel.paramFilters.isEmpty()) {
        queryExecutor.getInnerModel().paramFilters.addAll(innerModel.paramFilters);
    }
    // 设置安全脱敏
    if (!innerModel.secureMask.isEmpty()) {
        queryExecutor.getInnerModel().secureMask.putAll(innerModel.secureMask);
    }
    // 设置分页优化
    queryExecutor.getInnerModel().pageOptimize = innerModel.pageOptimize;
    SqlToyConfig sqlToyConfig = sqlToyContext.getSqlToyConfig(queryExecutor, SqlType.search, getDialect(queryExecutor.getInnerModel().dataSource));
    // 加密字段,查询时解密
    if (entityMeta.getSecureColumns() != null) {
        sqlToyConfig.setDecryptColumns(entityMeta.getSecureColumns());
    }
    // 分库分表策略
    setEntitySharding(queryExecutor, entityMeta);
    if (innerModel.dbSharding != null) {
        queryExecutor.getInnerModel().dbSharding = innerModel.dbSharding;
    }
    if (innerModel.tableSharding != null) {
        ShardingStrategyConfig shardingConfig = innerModel.tableSharding;
        // 补充表名称
        shardingConfig.setTables(new String[] { entityMeta.getTableName() });
        List<ShardingStrategyConfig> tableShardings = new ArrayList<ShardingStrategyConfig>();
        tableShardings.add(shardingConfig);
        queryExecutor.getInnerModel().tableShardings = tableShardings;
    }
    DataSource realDataSource = getDataSource(queryExecutor.getInnerModel().dataSource, sqlToyConfig);
    // 取count数量
    if (isCount) {
        return dialectFactory.getCountBySql(sqlToyContext, queryExecutor, sqlToyConfig, realDataSource);
    }
    // 非分页
    if (page == null) {
        // 取top
        if (innerModel.pickType == 0) {
            return dialectFactory.findTop(sqlToyContext, queryExecutor, sqlToyConfig, innerModel.pickSize, realDataSource).getRows();
        } else // 取随机记录
        if (innerModel.pickType == 1) {
            return dialectFactory.getRandomResult(sqlToyContext, queryExecutor, sqlToyConfig, innerModel.pickSize, realDataSource).getRows();
        } else {
            return dialectFactory.findByQuery(sqlToyContext, queryExecutor, sqlToyConfig, innerModel.lockMode, realDataSource).getRows();
        }
    }
    // 跳过总记录数形式的分页
    if (page.getSkipQueryCount()) {
        return dialectFactory.findSkipTotalCountPage(sqlToyContext, queryExecutor, sqlToyConfig, page.getPageNo(), page.getPageSize(), realDataSource).getPageResult();
    }
    return dialectFactory.findPage(sqlToyContext, queryExecutor, sqlToyConfig, page.getPageNo(), page.getPageSize(), realDataSource).getPageResult();
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) SqlToyConfig(org.sagacity.sqltoy.config.model.SqlToyConfig) ArrayList(java.util.ArrayList) DataSource(javax.sql.DataSource) Entry(java.util.Map.Entry) ParallQueryExecutor(org.sagacity.sqltoy.dialect.executor.ParallQueryExecutor) QueryExecutor(org.sagacity.sqltoy.model.QueryExecutor) ShardingStrategyConfig(org.sagacity.sqltoy.config.model.ShardingStrategyConfig) TranslateExtend(org.sagacity.sqltoy.model.inner.TranslateExtend) EntityQueryExtend(org.sagacity.sqltoy.model.inner.EntityQueryExtend) Translate(org.sagacity.sqltoy.config.model.Translate) HashSet(java.util.HashSet)

Example 9 with ShardingStrategyConfig

use of org.sagacity.sqltoy.config.model.ShardingStrategyConfig in project sagacity-sqltoy by chenrenfei.

the class ShardingUtils method getShardingDataSource.

/**
 * @todo 根据条件决定获得对应的数据库
 * @param sqlToyContext
 * @param sqlToyConfig
 * @param queryExecutor
 * @param dataSource
 * @return
 * @throws Exception
 */
public static DataSource getShardingDataSource(SqlToyContext sqlToyContext, SqlToyConfig sqlToyConfig, QueryExecutor queryExecutor, DataSource dataSource) throws Exception {
    // 获取sharding DataSource
    // 优先以直接指定的dataSource为基准
    DataSource shardingDataSource = dataSource;
    QueryExecutorExtend extend = queryExecutor.getInnerModel();
    ShardingStrategyConfig shardingConfig = null;
    if (null != sqlToyConfig.getDataSourceSharding()) {
        shardingConfig = sqlToyConfig.getDataSourceSharding();
    }
    if (null != extend.dbSharding) {
        shardingConfig = extend.dbSharding;
    }
    // 如果没有sharding策略,则返回dataSource,否则以sharding的结果dataSource为基准
    if (null == shardingConfig) {
        return shardingDataSource;
    }
    String[] paramNames = extend.getDataSourceShardingParamsName(sqlToyConfig);
    Object[] paramValues = extend.getDataSourceShardingParamsValue(sqlToyConfig);
    IgnoreCaseLinkedMap<String, Object> valueMap = hashParams(paramNames, paramValues);
    DataSource result = getShardingDataSource(sqlToyContext, sqlToyConfig, shardingConfig, valueMap);
    if (result != null) {
        return result;
    }
    return shardingDataSource;
}
Also used : ShardingStrategyConfig(org.sagacity.sqltoy.config.model.ShardingStrategyConfig) QueryExecutorExtend(org.sagacity.sqltoy.model.inner.QueryExecutorExtend) DataSource(javax.sql.DataSource)

Example 10 with ShardingStrategyConfig

use of org.sagacity.sqltoy.config.model.ShardingStrategyConfig in project sagacity-sqltoy by chenrenfei.

the class EntityManager method parseSharding.

/**
 * @todo 解析分库分表策略
 * @param entityMeta
 * @param entityClass
 */
private void parseSharding(EntityMeta entityMeta, Class entityClass) {
    Class classType = entityClass;
    Sharding sharding = null;
    // 增加递归对父类检测
    while (classType != null && !classType.equals(Object.class)) {
        sharding = (Sharding) classType.getAnnotation(Sharding.class);
        if (sharding != null) {
            break;
        }
        classType = classType.getSuperclass();
    }
    // 不存在分库策略
    if (sharding == null) {
        return;
    }
    // 分库策略
    ShardingConfig shardingConfig = new ShardingConfig();
    // 最大并行数量
    shardingConfig.setMaxConcurrents(sharding.maxConcurrents());
    // 最大执行时长(秒)
    shardingConfig.setMaxWaitSeconds(sharding.maxWaitSeconds());
    // 异常处理策略(是否全局回滚)
    shardingConfig.setGlobalRollback(sharding.is_global_rollback());
    Strategy shardingDB = sharding.db();
    String strategy = shardingDB.name();
    // 分库策略
    if (StringUtil.isNotBlank(strategy)) {
        ShardingStrategyConfig config = new ShardingStrategyConfig(0);
        config.setFields(shardingDB.fields());
        // 别名,如果没有设置则将fields作为默认别名,别名的目的在于共用sharding策略中的参数名称
        String[] aliasNames = new String[shardingDB.fields().length];
        System.arraycopy(shardingDB.fields(), 0, aliasNames, 0, aliasNames.length);
        if (shardingDB.aliasNames() != null) {
            System.arraycopy(shardingDB.aliasNames(), 0, aliasNames, 0, shardingDB.aliasNames().length);
        }
        config.setAliasNames(aliasNames);
        config.setDecisionType(shardingDB.decisionType());
        config.setStrategy(strategy);
        shardingConfig.setShardingDBStrategy(config);
    }
    // 分表策略
    Strategy shardingTable = sharding.table();
    strategy = shardingTable.name();
    if (StringUtil.isNotBlank(strategy)) {
        ShardingStrategyConfig config = new ShardingStrategyConfig(1);
        config.setFields(shardingTable.fields());
        // 别名,如果没有设置则将fields作为默认别名,别名的目的在于共用sharding策略中的参数名称
        String[] aliasNames = new String[shardingTable.fields().length];
        System.arraycopy(shardingTable.fields(), 0, aliasNames, 0, aliasNames.length);
        if (shardingTable.aliasNames() != null) {
            System.arraycopy(shardingTable.aliasNames(), 0, aliasNames, 0, shardingTable.aliasNames().length);
        }
        config.setTables(new String[] { entityMeta.getTableName() });
        config.setAliasNames(aliasNames);
        config.setDecisionType(shardingDB.decisionType());
        config.setStrategy(strategy);
        shardingConfig.setShardingTableStrategy(config);
    }
    // 必须有一个策略是存在的
    if (shardingConfig.getShardingDBStrategy() != null || shardingConfig.getShardingTableStrategy() != null) {
        entityMeta.setShardingConfig(shardingConfig);
    }
}
Also used : Sharding(org.sagacity.sqltoy.config.annotation.Sharding) ShardingConfig(org.sagacity.sqltoy.config.model.ShardingConfig) ShardingStrategyConfig(org.sagacity.sqltoy.config.model.ShardingStrategyConfig) Strategy(org.sagacity.sqltoy.config.annotation.Strategy) PKStrategy(org.sagacity.sqltoy.config.model.PKStrategy)

Aggregations

ShardingStrategyConfig (org.sagacity.sqltoy.config.model.ShardingStrategyConfig)18 ArrayList (java.util.ArrayList)8 ShardingConfig (org.sagacity.sqltoy.config.model.ShardingConfig)5 HashSet (java.util.HashSet)4 HashMap (java.util.HashMap)3 EntityMeta (org.sagacity.sqltoy.config.model.EntityMeta)3 List (java.util.List)2 DataSource (javax.sql.DataSource)2 QueryShardingModel (org.sagacity.sqltoy.config.model.QueryShardingModel)2 ShardingDBModel (org.sagacity.sqltoy.config.model.ShardingDBModel)2 ShardingModel (org.sagacity.sqltoy.config.model.ShardingModel)2 SqlToyConfig (org.sagacity.sqltoy.config.model.SqlToyConfig)2 ShardingDBModel (org.sagacity.sqltoy.model.ShardingDBModel)2 ShardingModel (org.sagacity.sqltoy.model.ShardingModel)2 QueryExecutorExtend (org.sagacity.sqltoy.model.inner.QueryExecutorExtend)2 ShardingStrategy (org.sagacity.sqltoy.plugin.ShardingStrategy)2 Element (org.w3c.dom.Element)2 Entry (java.util.Map.Entry)1 Sharding (org.sagacity.sqltoy.config.annotation.Sharding)1 Strategy (org.sagacity.sqltoy.config.annotation.Strategy)1