preface

This chapter continues to examine the core step of ShardingJDBC: routing.

  • ShardingRouteEngineFactoryRouting engine factory.
  • ShardingStrategySharding policy.

A, ShardingRouteEngineFactory routing engine factory

1. Review shardin Group decorator

public final class ShardingRouteDecorator implements RouteDecorator<ShardingRule> { @Override public RouteContext decorate(final RouteContext routeContext, final ShardingSphereMetaData metaData, final ShardingRule shardingRule, Final ConfigurationProperties properties) {// SQL context SQLParserEngine parses SQL DataNodeRouter to create SQLStatementContext sqlStatementContext = routeContext.getSqlStatementContext(); / / parameter List < Object > parameters. = routeContext getParameters (); / / for SQL do check ShardingStatementValidatorFactory. NewInstance (sqlStatementContext. GetSqlStatement ()), ifPresent (validator - >  validator.validate(shardingRule, sqlStatementContext.getSqlStatement(), parameters)); ShardingConditions = getShardingConditions(parameters,  sqlStatementContext, metaData.getSchema(), shardingRule); / / merge shardingConditions Boolean needMergeShardingValues = isNeedMergeShardingValues (sqlStatementContext shardingRule); if (sqlStatementContext.getSqlStatement() instanceof DMLStatement && needMergeShardingValues) { checkSubqueryShardingValues(sqlStatementContext, shardingRule, shardingConditions); mergeShardingConditions(shardingConditions); } / / routing ShardingRouteEngine ShardingRouteEngine = ShardingRouteEngineFactory. NewInstance (shardingRule, metaData, sqlStatementContext, shardingConditions, properties); RouteResult routeResult = shardingRouteEngine.route(shardingRule); if (needMergeShardingValues) { Preconditions.checkState(1 == routeResult.getRouteUnits().size(), "Must have one sharding with subquery."); Return RouteContext(sqlStatementContext, parameters, routeResult); }}Copy the code

The ShardingRouteDecorator’s Decorate method is the core flow of routing.

  • Obtain from SQLShardingConditions
  • ShardingRouteEngineFactoryGetting the Routing Engine
  • ShardingRouteEngineThe routing engine executes and getsRouteResult

ShardingRouteEngine already know about the various implementations in the last chapter, the current is unknown, which SQL is what kind of engine, this is ShardingRouteEngineFactory according to a variety of factors.

2, ShardingRouteEngineFactory

ShardingRouteEngineFactory as ShardingRouteEngine factory, according to the structure of different refs ShardingRouteEngine returned to the client. Focus on his only public method, newInstance.

public static ShardingRouteEngine newInstance(final ShardingRule shardingRule, final ShardingSphereMetaData metaData, final SQLStatementContext sqlStatementContext, final ShardingConditions shardingConditions, final ConfigurationProperties properties) { SQLStatement sqlStatement = sqlStatementContext.getSqlStatement(); Collection<String> tableNames = sqlStatementContext.getTablesContext().getTableNames(); if (sqlStatement instanceof TCLStatement) { return new ShardingDatabaseBroadcastRoutingEngine(); } if (sqlStatement instanceof DDLStatement) { return new ShardingTableBroadcastRoutingEngine(metaData.getSchema(), sqlStatementContext); } if (sqlStatement instanceof DALStatement) { return getDALRoutingEngine(shardingRule, sqlStatement, tableNames); } if (sqlStatement instanceof DCLStatement) { return getDCLRoutingEngine(sqlStatementContext, metaData); } if (shardingRule.isAllInDefaultDataSource(tableNames)) { return new ShardingDefaultDatabaseRoutingEngine(tableNames); } if (shardingRule.isAllBroadcastTables(tableNames)) { return sqlStatement instanceof SelectStatement ? new ShardingUnicastRoutingEngine(tableNames) : new ShardingDatabaseBroadcastRoutingEngine(); } if (sqlStatementContext.getSqlStatement() instanceof DMLStatement && tableNames.isEmpty() && shardingRule.hasDefaultDataSourceName()) { return new ShardingDefaultDatabaseRoutingEngine(tableNames); } if (sqlStatementContext.getSqlStatement() instanceof DMLStatement && shardingConditions.isAlwaysFalse() || tableNames.isEmpty() || ! shardingRule.tableRuleExists(tableNames)) { return new ShardingUnicastRoutingEngine(tableNames); } return getShardingRoutingEngine(shardingRule, sqlStatementContext, shardingConditions, tableNames, properties); }Copy the code

TCLStatement

Transaction SQL, such as set the autocommit = 0, commit and roolback, ShardingDatabaseBroadcastRoutingEngine data broadcasting.

if (sqlStatement instanceof TCLStatement) {
    return new ShardingDatabaseBroadcastRoutingEngine();
}
Copy the code

SetAutoCommit (false) set non-commit to connection.setautoCommit (false) and commit to connection.mit.

Normal when using JDBC connection. SetAutoCommit (false) and set the autocommit = 0 is no different, because for the com. Mysql. JDBC. ConnectionImpl# setAutoCommit, Qlset AutoCOMMIT = 0.

However, when using Sharing-JDBC, connection.setautoCommit (false) can avoid redundant data source execution (more on transactions later, Note that the INVOCATION of WRapper transformer # replaymethod is used) and sqlSET Autocommit = 0 will cause the datasource to broadcast execution.

DDLStatement

DDL, such as the alter table t_order modify the column status varchar (255) the DEFAULT NULL, executes ShardingTableBroadcastRoutingEngine broadcast table.

if (sqlStatement instanceof DDLStatement) {
    return new ShardingTableBroadcastRoutingEngine(metaData.getSchema(), sqlStatementContext);
}
Copy the code

DALStatement

DAL, such as set @xxx =? , Show tables, describe t_order.

private static ShardingRouteEngine getDALRoutingEngine(final ShardingRule shardingRule, final SQLStatement sqlStatement, final Collection<String> tableNames) { if (sqlStatement instanceof UseStatement) { return new ShardingIgnoreRoutingEngine(); } // set @xxx =? ; show databases; if (sqlStatement instanceof SetStatement || sqlStatement instanceof ResetParameterStatement || sqlStatement instanceof ShowDatabasesStatement) { return new ShardingDatabaseBroadcastRoutingEngine(); } // tableRule does not exist and has default data source default data source if (! tableNames.isEmpty() && ! shardingRule.tableRuleExists(tableNames) && shardingRule.hasDefaultDataSourceName()) { return new ShardingDefaultDatabaseRoutingEngine(tableNames); } // describe t_order if (! tableNames.isEmpty()) { return new ShardingUnicastRoutingEngine(tableNames); } / / tableNames empty data source multicast / / show tables return new ShardingDataSourceGroupBroadcastRoutingEngine (); }Copy the code
  • set @xxx=?orshow databasesGo,ShardingDatabaseBroadcastRoutingEngineData source broadcast.
  • TableNames is not empty and does not have a tableRule and has a default data source. GoShardingDefaultDatabaseRoutingEngineDefault data source.
  • Other tableNames are not empty for scenes such asdescribe t_orderGo,ShardingUnicastRoutingEngineUnicast.
  • TableNames is empty, as inshow tablesGo,ShardingDataSourceGroupBroadcastRoutingEngineMulticast, supported through the default data source.

ShardingDataSourceGroupBroadcastRoutingEngine is DDLStatement finally a scheme. Early versions, to show tables this command is not support the default data source, lead to set the default data source name, still go random data to perform the corresponding SQL (out of the original scheme is ShardingUnicastRoutingEngine unicast, so is random data sources).

While using database,it will select a random database!!!

DCLStatement

DCLStatement, SQL related to user permissions, such as Grant permissions.

private static ShardingRouteEngine getDCLRoutingEngine(final SQLStatementContext sqlStatementContext, GRANT ALL ON T_order TO 'user2'@'%' if GRANT ALL ON t_order TO 'user2'@'%' if (isDCLForSingleTable(sqlStatementContext)) { return new ShardingTableBroadcastRoutingEngine(metaData.getSchema(), sqlStatementContext); GRANT ALL ON *.* TO 'user2'@'%' else {return new ShardingMasterInstanceBroadcastRoutingEngine(metaData.getDataSources()); }}Copy the code

For single table DCL and not a single table DCL ShardingRouteEngine, the former use ShardingTableBroadcastRoutingEngine table broadcasting; The latter using radio ShardingMasterInstanceBroadcastRoutingEngine instance.

DMLStatement

Full default data source

When all the tables have no configuration TableRule, nor a broadcast table, will take ShardingDefaultDatabaseRoutingEngine default data source routing engine.

 if (shardingRule.isAllInDefaultDataSource(tableNames)) {
    return new ShardingDefaultDatabaseRoutingEngine(tableNames);
}
Copy the code

ShardingRule#isAllInDefaultDataSource checks whether all logical tables are in the default data source.

public boolean isAllInDefaultDataSource(final Collection<String> logicTableNames) { if (! hasDefaultDataSourceName()) { return false; } for (String each : LogicTableNames) {/ / logical table If there is a table rules or is broadcast table Is not the default data source if (findTableRule (each). IsPresent () | | isBroadcastTable (each)) {return  false; } } return ! logicTableNames.isEmpty(); }Copy the code

All radio table

When all logical tables are broadcast tables, there are two cases.

  • Select statement, executeShardingUnicastRoutingEngineUnicast.
  • Non-select statement, executeShardingDatabaseBroadcastRoutingEngineData source broadcast.
if (shardingRule.isAllBroadcastTables(tableNames)) {
  return sqlStatement instanceof SelectStatement 
           ? new ShardingUnicastRoutingEngine(tableNames) 
           : new ShardingDatabaseBroadcastRoutingEngine();
}
Copy the code

Other situations

If the table list is empty (such as select now (), etc.) and is configured with the default data source, then walk ShardingDefaultDatabaseRoutingEngine default data source.

if (sqlStatementContext.getSqlStatement() instanceof DMLStatement 
      && tableNames.isEmpty() 
      && shardingRule.hasDefaultDataSourceName()) {
    return new ShardingDefaultDatabaseRoutingEngine(tableNames);
}
Copy the code

If shardingConditions isAlwaysFalse, or tableNames empty, or tableNames no corresponding TableRule, walk ShardingUnicastRoutingEngine unicast.

if (sqlStatementContext.getSqlStatement() instanceof DMLStatement && shardingConditions.isAlwaysFalse() || tableNames.isEmpty() || ! shardingRule.tableRuleExists(tableNames)) { return new ShardingUnicastRoutingEngine(tableNames); }Copy the code

So when is shardingConditions isAlwaysFalse?

Shardingrouteconditions #getShardingConditions (RouteValue, RouteValue, RouteValue) Returns the AlwaysFalseRouteValue, corresponding will convert AlwaysFalseShardingCondition. Select * from t_order where order_id = 5 and order_id = 6 or select * from t_order where order_id > 5 and order_id < 5.

WhereClauseShardingConditionEngine#mergeRouteValues

private RouteValue mergeRouteValues(final Column column, final Collection<RouteValue> routeValues) { Collection<Comparable<? >> listValue = null; Range<Comparable<? >> rangeValue = null; for (RouteValue each : RouteValues) {if (each instanceof ListRouteValue) { AlwaysFalseRouteValue listValue = mergeListRouteValues(((ListRouteValue) each).getValues(), listValue); if (listValue.isEmpty()) { return new AlwaysFalseRouteValue(); }} else if (each instanceof RangeRouteValue) {try { Return AlwaysFalseRouteValue rangeValue = mergeRangeRouteValues(((RangeRouteValue) each).getValuerange (), rangeValue); } catch (final IllegalArgumentException ex) { return new AlwaysFalseRouteValue(); } } } if (null == listValue) { return new RangeRouteValue<>(column.getName(), column.getTableName(), rangeValue); } if (null == rangeValue) { return new ListRouteValue<>(column.getName(), column.getTableName(), listValue); } listValue = mergeListAndRangeRouteValues(listValue, rangeValue); return listValue.isEmpty() ? new AlwaysFalseRouteValue() : new ListRouteValue<>(column.getName(), column.getTableName(), listValue); }Copy the code

Back to ShardingRouteEngineFactory getShardingRoutingEngine method is DML last judgment logic, the general business SQL are going this way.

private static ShardingRouteEngine getShardingRoutingEngine(final ShardingRule shardingRule, final SQLStatementContext sqlStatementContext, final ShardingConditions shardingConditions, final Collection<String> tableNames, Final ConfigurationProperties properties) {// tableName Collection<String> shardingTableNames = shardingRule.getShardingLogicTableNames(tableNames); / / if the filter out only one table or the table in a binding rule all go ShardingStandardRoutingEngine if (1 = = shardingTableNames. The size () | | shardingRule.isAllBindingTables(shardingTableNames)) { return new ShardingStandardRoutingEngine(shardingTableNames.iterator().next(), sqlStatementContext, shardingConditions, properties); } / / or else go ShardingComplexRoutingEngine / / TODO config for cartesian set return new ShardingComplexRoutingEngine(tableNames, sqlStatementContext, shardingConditions, properties); }Copy the code

See from the above code, if involves the associated query, want to consider to configure the binding table, otherwise it will enter ShardingComplexRoutingEngine. And ShardingComplexRoutingEngine logic mentioned in the previous chapter, cycle all ShardingStandardRoutingEngine table implementation, if the final RouteResult is greater than 1, Will lead to enter ShardingCartesianRoutingEngine cartesian product (see the previous chapter).

Ii. ShardingStrategy

ShardingStandardRoutingEngineThe most important sharding strategy for standard routing engines is not coveredShardingStandardRoutingEngine#route0This core method.

Private Collection<DataNode> Route0 (final ShardingRule ShardingRule, final TableRule TableRule, final List<RouteValue> databaseShardingValues, Final List<RouteValue> tableShardingValues) {// dataSource Route Collection<String> routedDataSources = routeDataSources(shardingRule, tableRule, databaseShardingValues); Collection<DataNode> result = new LinkedList<>(); for (String each : RoutedDataSources) {// table routing table+dataSource construct DataNode Collection<DataNode> dataNodes = routeTables(shardingRule, tableRule, each, tableShardingValues); result.addAll(dataNodes); } return result; } // Data source routing Private Collection<String> routeDataSources(final ShardingRule ShardingRule, final TableRule TableRule, Final List < RouteValue > databaseShardingValues) {/ / if there is no RouteValue returns all data sources if (databaseShardingValues. IsEmpty ()) { return tableRule.getActualDatasourceNames(); } / / strategy depots ShardingStrategy databaseShardingStrategy = shardingRule. GetDatabaseShardingStrategy (tableRule); // Run the sharding algorithm to obtain the data source name Collection<String> dataSources = databaseShardingStrategy.doSharding(tableRule.getActualDatasourceNames(), databaseShardingValues, this.properties); // Add LinkedHashSet Collection<String> result = new LinkedHashSet<>(dataSources); // The routing result must be non-empty preconditions. checkState(! result.isEmpty(), "no database route info"); / / routing results can not exceed the scope of the actual data collection Preconditions. The checkState (tableRule. GetActualDatasourceNames () containsAll (result), "Some routed data sources do not belong to configured data sources. routed data sources: `%s`, configured data sources: `%s`", result, tableRule.getActualDatasourceNames()); return result; } private Collection<DataNode> routeTables(final ShardingRule ShardingRule, final TableRule TableRule, final String routedDataSource, Final List<RouteValue> tableShardingValues) { availableTargetTables = tableRule.getActualTableNames(routedDataSource); Collection<String> routedTables; / / if RouteValue is empty return a list of all under the current dataSource if (tableShardingValues. IsEmpty ()) {routedTables = new LinkedHashSet<>(availableTargetTables); } / / perform subdivision algorithm for table result sets the else {ShardingStrategy tableShardingStrategy = shardingRule. GetTableShardingStrategy (tableRule); Collection<String> tables = tableShardingStrategy.doSharding(availableTargetTables, tableShardingValues, this.properties); routedTables = new LinkedHashSet<>(tables); } // The route result cannot be empty preconditions. checkState(! routedTables.isEmpty(), "no table route info"); // Assemble DataNode Collection<DataNode> result = new LinkedList<>(); for (String each : routedTables) { result.add(new DataNode(routedDataSource, each)); } return result; }Copy the code

InlineShardingStrategy

InlineShardingStrategy is a sharding strategy configured through groovy expressions, constructed as follows.

Public Final Class implements ShardingStrategy {// private Final String shardingColumn; // groovy.lang.Closure private final Closure<? > closure; public InlineShardingStrategy(final InlineShardingStrategyConfiguration inlineShardingStrategyConfig) { Preconditions.checkNotNull(inlineShardingStrategyConfig.getShardingColumn(), "Sharding column cannot be null."); Preconditions.checkNotNull(inlineShardingStrategyConfig.getAlgorithmExpression(), "Sharding algorithm expression cannot be null."); shardingColumn = inlineShardingStrategyConfig.getShardingColumn(); String algorithmExpression = InlineExpressionParser.handlePlaceHolder(inlineShardingStrategyConfig.getAlgorithmExpression().trim()); closure = new InlineExpressionParser(algorithmExpression).evaluateClosure(); }}Copy the code

DoSharding method.

@Override public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<RouteValue> shardingValues, final ConfigurationProperties properties) { RouteValue shardingValue = shardingValues.iterator().next(); // RangeRouteValue Specifies the range-sharding method if (properties.<Boolean>getValue(ConfigurationPropertyKey.ALLOW_RANGE_QUERY_WITH_INLINE_SHARDING) && shardingValue instanceof RangeRouteValue) { return availableTargetNames; } Preconditions.checkState(shardingValue instanceof ListRouteValue, "Inline strategy cannot support this type sharding:" + shardingValue.toString()); // ListRouteValue shardingResult = doSharding((ListRouteValue) shardingValue); Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); for (String each : shardingResult) { if (availableTargetNames.contains(each)) { result.add(each); } } return result; }Copy the code

First, shardingValue is RangeRouteValue interval, if allow range. Query.. With the inline. Sharding is true, it returns all availableTargetNames; Otherwise, an exception is thrown. The default is false, and an exception is thrown to prevent the user from ignoring the underlying performance problem.

For inline sharding strategy, user only can config precise algorithm via inline expression, and cannot config range algorithm. So throw exception when SQL contains range conditions(such as BETWEEN AND, <, >, <=, >=) may better than query all data nodes. If query all data nodes instead of explicit exception, user may missing the potential performance issue. When turn this parameter on, query all data nodes with inline sharding to be allowed instead of explicit exception.

The next step is to convert the ListRouteValue to the PreciseShardingValue collection, performing the sharding logic. Groovy can’t read it.

Private Collection<String> doSharding(final ListRouteValue shardingValue) {Collection<String> result = new LinkedList<>(); For (PreciseShardingValue<? > each: transferToPreciseShardingValues (shardingValue)) {/ / perform shard logic result. The add (execute (each)); } return result; } / / ListRouteValue tile into PreciseShardingValue private collection List < PreciseShardingValue > transferToPreciseShardingValues (final ListRouteValue<? > shardingValue) { List<PreciseShardingValue> result = new ArrayList<>(shardingValue.getValues().size()); PreciseShardingValue for (Comparable<? > each : shardingValue.getValues()) { result.add(new PreciseShardingValue(shardingValue.getTableName(), shardingValue.getColumnName(), each)); } return result; } private String Execute (Final PreciseShardingValue shardingValue) {Closure<? > result = closure.rehydrate(new Expando(), null, null); result.setResolveStrategy(Closure.DELEGATE_ONLY); result.setProperty(shardingColumn, shardingValue.getValue()); return result.call().toString(); }Copy the code

StandardShardingStrategy

StandardShardingStrategy is the most commonly used sharding strategy. It configates precise sharding and interval sharding algorithm for single field, and interval sharding algorithm is not necessary.

Public final class StandardShardingStrategy implements ShardingStrategy {// private Final String shardingColumn; Private final PreciseShardingAlgorithm PreciseShardingAlgorithm; Private Final RangeShardingAlgorithm RangeShardingAlgorithm; public StandardShardingStrategy(final StandardShardingStrategyConfiguration standardShardingStrategyConfig) { Preconditions.checkNotNull(standardShardingStrategyConfig.getShardingColumn(), "Sharding column cannot be null."); Preconditions.checkNotNull(standardShardingStrategyConfig.getPreciseShardingAlgorithm(), "precise sharding algorithm cannot be null."); shardingColumn = standardShardingStrategyConfig.getShardingColumn(); preciseShardingAlgorithm = standardShardingStrategyConfig.getPreciseShardingAlgorithm(); rangeShardingAlgorithm = standardShardingStrategyConfig.getRangeShardingAlgorithm(); }}Copy the code

The doSharding method uses different sharding logic for different routeValues.

@Override
public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<RouteValue> shardingValues, final ConfigurationProperties properties) {
    RouteValue shardingValue = shardingValues.iterator().next();
    Collection<String> shardingResult = shardingValue instanceof ListRouteValue
            ? doSharding(availableTargetNames, (ListRouteValue) shardingValue) 
            : doSharding(availableTargetNames, (RangeRouteValue) shardingValue);
    Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
    result.addAll(shardingResult);
    return result;
}
Copy the code

If it is ListRouteValue, as with InlineShardingStrategy, the values of tiled ListRouteValue are assembled into PreciseShardingValue, and the exact sharding algorithm is cyclic executed.

private Collection<String> doSharding(final Collection<String> availableTargetNames, final ListRouteValue<? > shardingValue) { Collection<String> result = new LinkedList<>(); for (Comparable<? > each : shardingValue.getValues()) { PreciseShardingValue preciseShardingValue = new PreciseShardingValue(shardingValue.getTableName(), shardingValue.getColumnName(), each); String target = preciseShardingAlgorithm.doSharding(availableTargetNames, preciseShardingValue); if (null ! = target) { result.add(target); } } return result; }Copy the code

If the value is RangeRouteValue, the interval sharding algorithm is empty, and an error is reported. Otherwise, the RangeRouteValue is directly converted to RangeShardingValue to perform the algorithm’s doSharding method.

private Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeRouteValue<? > shardingValue) { if (null == rangeShardingAlgorithm) { throw new UnsupportedOperationException("Cannot find range sharding strategy in sharding rule."); } return rangeShardingAlgorithm.doSharding(availableTargetNames, new RangeShardingValue(shardingValue.getTableName(), shardingValue.getColumnName(), shardingValue.getValueRange())); }Copy the code

ComplexShardingStrategy

ComplexShardingStrategy Compared to StandardShardingStrategy, it is a sharding strategy for multiple fields.

public final class ComplexShardingStrategy implements ShardingStrategy { @Getter private final Collection<String> shardingColumns; private final ComplexKeysShardingAlgorithm shardingAlgorithm; public ComplexShardingStrategy(final ComplexShardingStrategyConfiguration complexShardingStrategyConfig) { Preconditions.checkNotNull(complexShardingStrategyConfig.getShardingColumns(), "Sharding columns cannot be null."); Preconditions.checkNotNull(complexShardingStrategyConfig.getShardingAlgorithm(), "Sharding algorithm cannot be null."); shardingColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); shardingColumns.addAll(Splitter.on(",").trimResults().splitToList(complexShardingStrategyConfig.getShardingColumns())); shardingAlgorithm = complexShardingStrategyConfig.getShardingAlgorithm(); } @Override public Collection<String> doSharding(final Collection<String> availableTargetNames, Final Collection<RouteValue> shardingValues, final ConfigurationProperties properties) {// Collection<Comparable<? >>> columnShardingValues = new HashMap<>(shardingValues.size(), 1); Range Map<String, Range<Comparable<? >>> columnRangeValues = new HashMap<>(shardingValues.size(), 1); String logicTableName = ""; for (RouteValue each : shardingValues) { if (each instanceof ListRouteValue) { columnShardingValues.put(each.getColumnName(), ((ListRouteValue) each).getValues()); } else if (each instanceof RangeRouteValue) { columnRangeValues.put(each.getColumnName(), ((RangeRouteValue) each).getValueRange()); } logicTableName = each.getTableName(); } // ComplexKeysShardingValue ComplexKeysShardingValue complexKeysShardingValue = new ComplexKeysShardingValue(logicTableName, columnShardingValues, columnRangeValues); / / execution ComplexKeysShardingAlgorithm Collection < String > shardingResult = shardingAlgorithm. DoSharding (availableTargetNames,  complexKeysShardingValue); Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); result.addAll(shardingResult); return result; }}Copy the code

HintShardingStrategy

HintShardingStrategy implies sharding strategy. Instead of parsing SQL to obtain ShardingConditions to obtain sharding key values, the sharding values are set by user manipulation of HintManager (excluding sharding fields, which are irrelevant to SQL).

public final class HintShardingStrategy implements ShardingStrategy { @Getter private final Collection<String> shardingColumns; private final HintShardingAlgorithm shardingAlgorithm; public HintShardingStrategy(final HintShardingStrategyConfiguration hintShardingStrategyConfig) { Preconditions.checkNotNull(hintShardingStrategyConfig.getShardingAlgorithm(), "Sharding algorithm cannot be null."); shardingColumns = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); shardingAlgorithm = hintShardingStrategyConfig.getShardingAlgorithm(); } @Override public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<RouteValue> shardingValues, final ConfigurationProperties properties) { ListRouteValue shardingValue = (ListRouteValue) shardingValues.iterator().next(); // HintShardingValue HintShardingValue hintShardingValue = new HintShardingValue(shardingValue.getTableName(), shardingValue.getColumnName(), shardingValue.getValues()); // HintShardingAlgorithm Collection<String> shardingResult = shardingAlgorithm.doSharding(availableTargetNames, hintShardingValue); Collection<String> result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); result.addAll(shardingResult); return result; }}Copy the code

conclusion

  • ShardingRouteEngineFactory#getShardingRoutingEngineGeneral business SQL uses this method to determine which routing engine to use. If the table in SQL matches only a single TableRule or the TableRule matches all belong to the same binding relationship, it will goShardingStandardRoutingEngine; Or you will goShardingComplexRoutingEngineLoop through each SQL table, executeShardingStandardRoutingEngineThe final RouteResult result set with more than 1 element will result in an entryShardingCartesianRoutingEngineCartesian product routing engine.
  • For a standard routing engine ShardingStandardRoutingEngine, ShardingStrategy will only take effect, a total of four kinds of strategy.