Sharding-JDBC系列
- Sharding-JDBC 核心組件介紹
- Sharding-JDBC 配置分析
- Sharding-JDBC 執(zhí)行整體流程
- Sharding-JDBC 分庫(kù)配置解析過(guò)程
- Sharding-JDBC 分表配置解析過(guò)程
- Sharding-JDBC 分庫(kù)分表配置解析過(guò)程
ShardingSphere介紹
ShardingSphere是一套開源的分布式數(shù)據(jù)庫(kù)中間件解決方案組成的生態(tài)圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(計(jì)劃中)這3款相互獨(dú)立的產(chǎn)品組成。 他們均提供標(biāo)準(zhǔn)化的數(shù)據(jù)分片、分布式事務(wù)和數(shù)據(jù)庫(kù)治理功能,可適用于如Java同構(gòu)、異構(gòu)語(yǔ)言、云原生等各種多樣化的應(yīng)用場(chǎng)景。
ShardingSphere定位為關(guān)系型數(shù)據(jù)庫(kù)中間件,旨在充分合理地在分布式的場(chǎng)景下利用關(guān)系型數(shù)據(jù)庫(kù)的計(jì)算和存儲(chǔ)能力,而并非實(shí)現(xiàn)一個(gè)全新的關(guān)系型數(shù)據(jù)庫(kù)。
官方文檔參考shardingsphere官網(wǎng),文檔非常詳細(xì)推薦閱讀。

Sharding-JDBC
Rule 分片信息
- RuleConfiguration的核心配置依次為ShardingRule(分片Rule)、TableRule (表規(guī)則)、ShardingRuleConfiguration(分片規(guī)則)、TableRuleConfiguration(表規(guī)則)和MasterSlaveRuleConfiguration(主從規(guī)則)。
ShardingRule 分片規(guī)則
@Getter
public class ShardingRule implements BaseRule {
// 分片規(guī)則配置
private final ShardingRuleConfiguration ruleConfiguration;
// 分片的數(shù)據(jù)源名稱
private final ShardingDataSourceNames shardingDataSourceNames;
// 邏輯表的庫(kù)表資源
private final Collection<TableRule> tableRules;
// 相同表分片規(guī)則的組
private final Collection<BindingTableRule> bindingTableRules;
// 廣播的表名
private final Collection<String> broadcastTables;
// 默認(rèn)分庫(kù)策略
private final ShardingStrategy defaultDatabaseShardingStrategy;
// 默認(rèn)分表策略
private final ShardingStrategy defaultTableShardingStrategy;
// 默認(rèn)主鍵生成器
private final ShardingKeyGenerator defaultShardingKeyGenerator;
// 主從規(guī)則
private final Collection<MasterSlaveRule> masterSlaveRules;
// 加密規(guī)則
private final EncryptRule encryptRule;
public ShardingRule(final ShardingRuleConfiguration shardingRuleConfig, final Collection<String> dataSourceNames) {
Preconditions.checkArgument(null != shardingRuleConfig, "ShardingRuleConfig cannot be null.");
Preconditions.checkArgument(null != dataSourceNames && !dataSourceNames.isEmpty(), "Data sources cannot be empty.");
this.ruleConfiguration = shardingRuleConfig;
shardingDataSourceNames = new ShardingDataSourceNames(shardingRuleConfig, dataSourceNames);
tableRules = createTableRules(shardingRuleConfig);
broadcastTables = shardingRuleConfig.getBroadcastTables();
bindingTableRules = createBindingTableRules(shardingRuleConfig.getBindingTableGroups());
defaultDatabaseShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultDatabaseShardingStrategyConfig());
defaultTableShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultTableShardingStrategyConfig());
defaultShardingKeyGenerator = createDefaultKeyGenerator(shardingRuleConfig.getDefaultKeyGeneratorConfig());
masterSlaveRules = createMasterSlaveRules(shardingRuleConfig.getMasterSlaveRuleConfigs());
encryptRule = createEncryptRule(shardingRuleConfig.getEncryptRuleConfig());
}
}

ShardingRule
TableRule 表規(guī)則
@Getter
@ToString(exclude = {"dataNodeIndexMap", "actualTables", "actualDatasourceNames", "datasourceToTablesMap"})
public final class TableRule {
// 邏輯表
private final String logicTable;
// 實(shí)際數(shù)據(jù)節(jié)點(diǎn)
private final List<DataNode> actualDataNodes;
@Getter(AccessLevel.NONE)
// 實(shí)際表名
private final Set<String> actualTables;
@Getter(AccessLevel.NONE)
private final Map<DataNode, Integer> dataNodeIndexMap;
private final ShardingStrategy databaseShardingStrategy;
private final ShardingStrategy tableShardingStrategy;
private final String generateKeyColumn;
private final ShardingKeyGenerator shardingKeyGenerator;
private final Collection<String> actualDatasourceNames = new LinkedHashSet<>();
private final Map<String, Collection<String>> datasourceToTablesMap = new HashMap<>();
public TableRule(final String defaultDataSourceName, final String logicTableName) {
logicTable = logicTableName.toLowerCase();
actualDataNodes = Collections.singletonList(new DataNode(defaultDataSourceName, logicTableName));
actualTables = getActualTables();
cacheActualDatasourcesAndTables();
dataNodeIndexMap = Collections.emptyMap();
databaseShardingStrategy = null;
tableShardingStrategy = null;
generateKeyColumn = null;
shardingKeyGenerator = null;
}
}

TableRule
ShardingRuleConfiguration 分片規(guī)則配置
@Getter
@Setter
public final class ShardingRuleConfiguration implements RuleConfiguration {
// 表規(guī)則配置
private Collection<TableRuleConfiguration> tableRuleConfigs = new LinkedList<>();
// 相同表分片規(guī)則的組,如果表分片規(guī)則相同,則可以放在一個(gè)組里。
private Collection<String> bindingTableGroups = new LinkedList<>();
// 廣播的表
private Collection<String> broadcastTables = new LinkedList<>();
// 默認(rèn)數(shù)據(jù)源名稱
private String defaultDataSourceName;
// 默認(rèn)數(shù)據(jù)庫(kù)的分片算法配置
private ShardingStrategyConfiguration defaultDatabaseShardingStrategyConfig;
// 默認(rèn)表的分片算法配置
private ShardingStrategyConfiguration defaultTableShardingStrategyConfig;
// 自動(dòng)生成鍵的配置
private KeyGeneratorConfiguration defaultKeyGeneratorConfig;
// 主備配置信息
private Collection<MasterSlaveRuleConfiguration> masterSlaveRuleConfigs = new LinkedList<>();
// 加密配置規(guī)則
private EncryptRuleConfiguration encryptRuleConfig;
}

ShardingRuleConfiguration
TableRuleConfiguration 表配置
@Getter
@Setter
public final class TableRuleConfiguration {
// 邏輯表名
private final String logicTable;
// 實(shí)際物理的表,按照dataBase+table的維度
private final String actualDataNodes;
// database的分片策略
private ShardingStrategyConfiguration databaseShardingStrategyConfig;
// table的分片的策略
private ShardingStrategyConfiguration tableShardingStrategyConfig;
// 自動(dòng)生成鍵的配置
private KeyGeneratorConfiguration keyGeneratorConfig;
public TableRuleConfiguration(final String logicTable) {
this(logicTable, null);
}
public TableRuleConfiguration(final String logicTable, final String actualDataNodes) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(logicTable), "LogicTable is required.");
this.logicTable = logicTable;
this.actualDataNodes = actualDataNodes;
}
}

TableRuleConfiguration
MasterSlaveRuleConfiguration 主從配置
@Getter
public class MasterSlaveRuleConfiguration implements RuleConfiguration {
// 名稱
private final String name;
// 主數(shù)據(jù)源
private final String masterDataSourceName;
// 從數(shù)據(jù)源
private final List<String> slaveDataSourceNames;
// 負(fù)載均衡算法
private final LoadBalanceStrategyConfiguration loadBalanceStrategyConfiguration;
public MasterSlaveRuleConfiguration(final String name, final String masterDataSourceName, final List<String> slaveDataSourceNames) {
this(name, masterDataSourceName, slaveDataSourceNames, null);
}
public MasterSlaveRuleConfiguration(final String name,
final String masterDataSourceName, final List<String> slaveDataSourceNames, final LoadBalanceStrategyConfiguration loadBalanceStrategyConfiguration) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(name), "Name is required.");
Preconditions.checkArgument(!Strings.isNullOrEmpty(masterDataSourceName), "MasterDataSourceName is required.");
Preconditions.checkArgument(null != slaveDataSourceNames && !slaveDataSourceNames.isEmpty(), "SlaveDataSourceNames is required.");
this.name = name;
this.masterDataSourceName = masterDataSourceName;
this.slaveDataSourceNames = slaveDataSourceNames;
this.loadBalanceStrategyConfiguration = loadBalanceStrategyConfiguration;
}
}

MasterSlaveRuleConfiguration
配置關(guān)系圖

配置關(guān)系圖
- 圖片來(lái)自于Sharding-JDBC源碼解析
JDBC核心組件
- JDBC的核心模塊包括DataSource、Connection、PreparedStatement和Statement、ResultSet。
- Sharding-JDBC針對(duì)上述的核心進(jìn)行封裝,實(shí)現(xiàn)分庫(kù)分表的目的。
DataSource
ShardingDataSource
DataSource getShardingDataSource() throws SQLException {
// 創(chuàng)建數(shù)據(jù)分配規(guī)則
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
// 綁定order表的表配置
shardingRuleConfig.getTableRuleConfigs().add(getOrderTableRuleConfiguration());
//綁定order_item表的配置
shardingRuleConfig.getTableRuleConfigs().add(getOrderItemTableRuleConfiguration());
// 綁定相同分片規(guī)則的表
shardingRuleConfig.getBindingTableGroups().add("t_order, t_order_item");
// 綁定廣播的表
shardingRuleConfig.getBroadcastTables().add("t_config");
// 綁定庫(kù)表的分片策略
shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "ds${user_id % 2}"));
shardingRuleConfig.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new ModuloShardingTableAlgorithm()));
// 創(chuàng)建ShardingDataSource對(duì)象
return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig, new Properties());
}
private static KeyGeneratorConfiguration getKeyGeneratorConfiguration() {
KeyGeneratorConfiguration result = new KeyGeneratorConfiguration("SNOWFLAKE", "order_id");
return result;
}
TableRuleConfiguration getOrderTableRuleConfiguration() {
TableRuleConfiguration result = new TableRuleConfiguration("t_order", "ds${0..1}.t_order${0..1}");
result.setKeyGeneratorConfig(getKeyGeneratorConfiguration());
return result;
}
TableRuleConfiguration getOrderItemTableRuleConfiguration() {
TableRuleConfiguration result = new TableRuleConfiguration("t_order_item", "ds${0..1}.t_order_item${0..1}");
return result;
}
Map<String, DataSource> createDataSourceMap() {
Map<String, DataSource> result = new HashMap<>();
result.put("ds0", DataSourceUtil.createDataSource("ds0"));
result.put("ds1", DataSourceUtil.createDataSource("ds1"));
return result;
}
public final class DataSourceUtil {
private static final String HOST = "localhost";
private static final int PORT = 3306;
private static final String USER_NAME = "root";
private static final String PASSWORD = "123456";
public static DataSource createDataSource(final String dataSourceName) {
HikariDataSource result = new HikariDataSource();
result.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
result.setJdbcUrl(String.format("jdbc:mysql://%s:%s/%s?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8", HOST, PORT, dataSourceName));
result.setUsername(USER_NAME);
result.setPassword(PASSWORD);
return result;
}
}
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ShardingDataSourceFactory {
public static DataSource createDataSource(
final Map<String, DataSource> dataSourceMap, final ShardingRuleConfiguration shardingRuleConfig, final Properties props) throws SQLException {
return new ShardingDataSource(dataSourceMap, new ShardingRule(shardingRuleConfig, dataSourceMap.keySet()), props);
}
}
@Getter
public abstract class AbstractDataSourceAdapter extends AbstractUnsupportedOperationDataSource implements AutoCloseable {
private final Map<String, DataSource> dataSourceMap;
private final DatabaseType databaseType;
public AbstractDataSourceAdapter(final Map<String, DataSource> dataSourceMap) throws SQLException {
this.dataSourceMap = dataSourceMap;
databaseType = createDatabaseType();
}
}
@Getter
public class ShardingDataSource extends AbstractDataSourceAdapter {
private final ShardingRuntimeContext runtimeContext;
public ShardingDataSource(final Map<String, DataSource> dataSourceMap, final ShardingRule shardingRule, final Properties props) throws SQLException {
super(dataSourceMap);
checkDataSourceType(dataSourceMap);
runtimeContext = new ShardingRuntimeContext(dataSourceMap, shardingRule, props, getDatabaseType());
}
@Override
public final ShardingConnection getConnection() {
return new ShardingConnection(getDataSourceMap(), runtimeContext, TransactionTypeHolder.get());
}
}
MasterSlaveDataSource
DataSource getMasterSlaveDataSource() throws SQLException {
MasterSlaveRuleConfiguration masterSlaveRuleConfig = new MasterSlaveRuleConfiguration("ds_master_slave", "ds_master", Arrays.asList("ds_slave0", "ds_slave1"));
return MasterSlaveDataSourceFactory.createDataSource(createDataSourceMap(), masterSlaveRuleConfig, new Properties());
}
Map<String, DataSource> createDataSourceMap() {
Map<String, DataSource> result = new HashMap<>();
result.put("ds_master", DataSourceUtil.createDataSource("ds_master"));
result.put("ds_slave0", DataSourceUtil.createDataSource("ds_slave0"));
result.put("ds_slave1", DataSourceUtil.createDataSource("ds_slave1"));
return result;
}
public final class DataSourceUtil {
private static final String HOST = "localhost";
private static final int PORT = 3306;
private static final String USER_NAME = "root";
private static final String PASSWORD = "123456";
public static DataSource createDataSource(final String dataSourceName) {
HikariDataSource result = new HikariDataSource();
result.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
result.setJdbcUrl(String.format("jdbc:mysql://%s:%s/%s?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8", HOST, PORT, dataSourceName));
result.setUsername(USER_NAME);
result.setPassword(PASSWORD);
return result;
}
}
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class MasterSlaveDataSourceFactory {
public static DataSource createDataSource(final Map<String, DataSource> dataSourceMap, final MasterSlaveRuleConfiguration masterSlaveRuleConfig, final Properties props) throws SQLException {
return new MasterSlaveDataSource(dataSourceMap, new MasterSlaveRule(masterSlaveRuleConfig), props);
}
}
@Getter
public abstract class AbstractDataSourceAdapter extends AbstractUnsupportedOperationDataSource implements AutoCloseable {
private final Map<String, DataSource> dataSourceMap;
private final DatabaseType databaseType;
public AbstractDataSourceAdapter(final Map<String, DataSource> dataSourceMap) throws SQLException {
this.dataSourceMap = dataSourceMap;
databaseType = createDatabaseType();
}
}
@Getter
public class MasterSlaveDataSource extends AbstractDataSourceAdapter {
private final MasterSlaveRuntimeContext runtimeContext;
public MasterSlaveDataSource(final Map<String, DataSource> dataSourceMap, final MasterSlaveRule masterSlaveRule, final Properties props) throws SQLException {
super(dataSourceMap);
runtimeContext = new MasterSlaveRuntimeContext(dataSourceMap, masterSlaveRule, props, getDatabaseType());
}
@Override
public final MasterSlaveConnection getConnection() {
return new MasterSlaveConnection(getDataSourceMap(), runtimeContext);
}
}
DataSource類圖

DataSource
Connection
ShardingConnection
@Getter
public final class ShardingConnection extends AbstractConnectionAdapter {
// 綁定的dataSourceMap
private final Map<String, DataSource> dataSourceMap;
private final ShardingRuntimeContext runtimeContext;
private final TransactionType transactionType;
private final ShardingTransactionManager shardingTransactionManager;
public ShardingConnection(final Map<String, DataSource> dataSourceMap, final ShardingRuntimeContext runtimeContext, final TransactionType transactionType) {
this.dataSourceMap = dataSourceMap;
this.runtimeContext = runtimeContext;
this.transactionType = transactionType;
shardingTransactionManager = runtimeContext.getShardingTransactionManagerEngine().getTransactionManager(transactionType);
}
@Override
public PreparedStatement prepareStatement(final String sql) throws SQLException {
return new ShardingPreparedStatement(this, sql);
}
@Override
public Statement createStatement() {
return new ShardingStatement(this);
}
}
MasterSlaveConnection
@RequiredArgsConstructor
@Getter
public final class MasterSlaveConnection extends AbstractConnectionAdapter {
// 綁定的dataSourceMap
private final Map<String, DataSource> dataSourceMap;
private final MasterSlaveRuntimeContext runtimeContext;
@Override
public Statement createStatement() {
return new MasterSlaveStatement(this);
}
@Override
public PreparedStatement prepareStatement(final String sql) throws SQLException {
return new MasterSlavePreparedStatement(this, sql);
}
}
Connection類圖

Connection類圖
PreparedStatement
ShardingPreparedStatement
public final class ShardingPreparedStatement extends AbstractShardingPreparedStatementAdapter {
@Getter
private final ShardingConnection connection;
private final String sql;
private final PreparedQueryShardingEngine shardingEngine;
private final PreparedStatementExecutor preparedStatementExecutor;
private final BatchPreparedStatementExecutor batchPreparedStatementExecutor;
private SQLRouteResult sqlRouteResult;
private ResultSet currentResultSet;
private ShardingPreparedStatement(
final ShardingConnection connection, final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final boolean returnGeneratedKeys)
throws SQLException {
if (Strings.isNullOrEmpty(sql)) {
throw new SQLException(SQLExceptionConstant.SQL_STRING_NULL_OR_EMPTY);
}
this.connection = connection;
this.sql = sql;
ShardingRuntimeContext runtimeContext = connection.getRuntimeContext();
shardingEngine = new PreparedQueryShardingEngine(sql, runtimeContext.getRule(), runtimeContext.getProps(), runtimeContext.getMetaData(), runtimeContext.getParseEngine());
preparedStatementExecutor = new PreparedStatementExecutor(resultSetType, resultSetConcurrency, resultSetHoldability, returnGeneratedKeys, connection);
batchPreparedStatementExecutor = new BatchPreparedStatementExecutor(resultSetType, resultSetConcurrency, resultSetHoldability, returnGeneratedKeys, connection);
}
@Override
public ResultSet executeQuery() throws SQLException {
ResultSet result;
try {
clearPrevious();
shard();
initPreparedStatementExecutor();
MergeEngine mergeEngine = MergeEngineFactory.newInstance(connection.getRuntimeContext().getDatabaseType(),
connection.getRuntimeContext().getRule(), sqlRouteResult, connection.getRuntimeContext().getMetaData().getRelationMetas(), preparedStatementExecutor.executeQuery());
result = getResultSet(mergeEngine);
} finally {
clearBatch();
}
currentResultSet = result;
return result;
}
@Override
public int executeUpdate() throws SQLException {
try {
clearPrevious();
shard();
initPreparedStatementExecutor();
return preparedStatementExecutor.executeUpdate();
} finally {
clearBatch();
}
}
@Override
public boolean execute() throws SQLException {
try {
clearPrevious();
shard();
initPreparedStatementExecutor();
return preparedStatementExecutor.execute();
} finally {
clearBatch();
}
}
}
MasterSlavePreparedStatement
@Getter
public final class MasterSlavePreparedStatement extends AbstractMasterSlavePreparedStatementAdapter {
private final MasterSlaveConnection connection;
@Getter(AccessLevel.NONE)
private final MasterSlaveRouter masterSlaveRouter;
public MasterSlavePreparedStatement(
final MasterSlaveConnection connection, final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException {
if (Strings.isNullOrEmpty(sql)) {
throw new SQLException(SQLExceptionConstant.SQL_STRING_NULL_OR_EMPTY);
}
this.connection = connection;
masterSlaveRouter = new MasterSlaveRouter(connection.getRuntimeContext().getRule(), connection.getRuntimeContext().getParseEngine(),
connection.getRuntimeContext().getProps().<Boolean>getValue(ShardingPropertiesConstant.SQL_SHOW));
for (String each : masterSlaveRouter.route(sql, true)) {
PreparedStatement preparedStatement = connection.getConnection(each).prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
routedStatements.add(preparedStatement);
}
}
@Override
public ResultSet executeQuery() throws SQLException {
Preconditions.checkArgument(1 == routedStatements.size(), "Cannot support executeQuery for DDL");
return routedStatements.iterator().next().executeQuery();
}
@Override
public int executeUpdate() throws SQLException {
int result = 0;
for (PreparedStatement each : routedStatements) {
result += each.executeUpdate();
}
return result;
}
@Override
public boolean execute() throws SQLException {
boolean result = false;
for (PreparedStatement each : routedStatements) {
result = each.execute();
}
return result;
}
}
PreparedStatement類圖

PreparedStatement類圖
Statement
ShardingStatement
public final class ShardingStatement extends AbstractStatementAdapter {
@Getter
private final ShardingConnection connection;
private final StatementExecutor statementExecutor;
private boolean returnGeneratedKeys;
private SQLRouteResult sqlRouteResult;
private ResultSet currentResultSet;
public ShardingStatement(final ShardingConnection connection, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) {
super(Statement.class);
this.connection = connection;
statementExecutor = new StatementExecutor(resultSetType, resultSetConcurrency, resultSetHoldability, connection);
}
@Override
public ResultSet executeQuery(final String sql) throws SQLException {
if (Strings.isNullOrEmpty(sql)) {
throw new SQLException(SQLExceptionConstant.SQL_STRING_NULL_OR_EMPTY);
}
ResultSet result;
try {
clearPrevious();
shard(sql);
initStatementExecutor();
MergeEngine mergeEngine = MergeEngineFactory.newInstance(connection.getRuntimeContext().getDatabaseType(),
connection.getRuntimeContext().getRule(), sqlRouteResult, connection.getRuntimeContext().getMetaData().getRelationMetas(), statementExecutor.executeQuery());
result = getResultSet(mergeEngine);
} finally {
currentResultSet = null;
}
currentResultSet = result;
return result;
}
@Override
public int executeUpdate(final String sql) throws SQLException {
try {
clearPrevious();
shard(sql);
initStatementExecutor();
return statementExecutor.executeUpdate();
} finally {
currentResultSet = null;
}
}
@Override
public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
if (RETURN_GENERATED_KEYS == autoGeneratedKeys) {
returnGeneratedKeys = true;
}
try {
clearPrevious();
shard(sql);
initStatementExecutor();
return statementExecutor.executeUpdate(autoGeneratedKeys);
} finally {
currentResultSet = null;
}
}
}
MasterSlaveStatement
@Getter
public final class MasterSlaveStatement extends AbstractStatementAdapter {
private final MasterSlaveConnection connection;
@Getter(AccessLevel.NONE)
private final MasterSlaveRouter masterSlaveRouter;
private final int resultSetType;
private final int resultSetConcurrency;
private final int resultSetHoldability;
private final Collection<Statement> routedStatements = new LinkedList<>();
public MasterSlaveStatement(final MasterSlaveConnection connection, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) {
super(Statement.class);
this.connection = connection;
masterSlaveRouter = new MasterSlaveRouter(connection.getRuntimeContext().getRule(), connection.getRuntimeContext().getParseEngine(),
connection.getRuntimeContext().getProps().<Boolean>getValue(ShardingPropertiesConstant.SQL_SHOW));
this.resultSetType = resultSetType;
this.resultSetConcurrency = resultSetConcurrency;
this.resultSetHoldability = resultSetHoldability;
}
@Override
public ResultSet executeQuery(final String sql) throws SQLException {
if (Strings.isNullOrEmpty(sql)) {
throw new SQLException(SQLExceptionConstant.SQL_STRING_NULL_OR_EMPTY);
}
clearPrevious();
Collection<String> dataSourceNames = masterSlaveRouter.route(sql, false);
Preconditions.checkState(1 == dataSourceNames.size(), "Cannot support executeQuery for DML or DDL");
Statement statement = connection.getConnection(dataSourceNames.iterator().next()).createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
routedStatements.add(statement);
return statement.executeQuery(sql);
}
@Override
public int executeUpdate(final String sql) throws SQLException {
clearPrevious();
int result = 0;
for (String each : masterSlaveRouter.route(sql, false)) {
Statement statement = connection.getConnection(each).createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
routedStatements.add(statement);
result += statement.executeUpdate(sql);
}
return result;
}
}
Statement類圖

Statement類圖
ResultSet
ShardingResultSet
public final class ShardingResultSet extends AbstractResultSetAdapter {
private final MergedResult mergeResultSet;
private final Map<String, Integer> columnLabelAndIndexMap;
public ShardingResultSet(final List<ResultSet> resultSets, final MergedResult mergeResultSet, final Statement statement, final SQLRouteResult sqlRouteResult) throws SQLException {
super(resultSets, statement, sqlRouteResult);
this.mergeResultSet = mergeResultSet;
columnLabelAndIndexMap = createColumnLabelAndIndexMap(resultSets.get(0).getMetaData());
}
private Map<String, Integer> createColumnLabelAndIndexMap(final ResultSetMetaData resultSetMetaData) throws SQLException {
Map<String, Integer> result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (int columnIndex = resultSetMetaData.getColumnCount(); columnIndex > 0; columnIndex--) {
result.put(resultSetMetaData.getColumnLabel(columnIndex), columnIndex);
}
return result;
}
}

ResultSet類圖
shardingjdbc目錄結(jié)構(gòu)
├── api
│ ├── EncryptDataSourceFactory.java
│ ├── MasterSlaveDataSourceFactory.java
│ ├── ShardingDataSourceFactory.java
│ └── yaml
│ ├── YamlEncryptDataSourceFactory.java
│ ├── YamlMasterSlaveDataSourceFactory.java
│ └── YamlShardingDataSourceFactory.java
├── executor
│ ├── AbstractStatementExecutor.java
│ ├── BatchPreparedStatementExecutor.java
│ ├── PreparedStatementExecutor.java
│ ├── SQLExecuteCallbackFactory.java
│ └── StatementExecutor.java
└── jdbc
├── adapter
│ ├── AbstractConnectionAdapter.java
│ ├── AbstractDataSourceAdapter.java
│ ├── AbstractMasterSlavePreparedStatementAdapter.java
│ ├── AbstractResultSetAdapter.java
│ ├── AbstractShardingPreparedStatementAdapter.java
│ ├── AbstractStatementAdapter.java
│ ├── WrapperAdapter.java
│ ├── executor
│ └── invocation
├── core
│ ├── connection
│ ├── constant
│ ├── context
│ ├── datasource
│ ├── resultset
│ └── statement
├── metadata
│ └── JDBCTableMetaDataConnectionManager.java
└── unsupported
├── AbstractUnsupportedDatabaseMetaDataResultSet.java
├── AbstractUnsupportedGeneratedKeysResultSet.java
├── AbstractUnsupportedOperationConnection.java
├── AbstractUnsupportedOperationDataSource.java
├── AbstractUnsupportedOperationPreparedStatement.java
├── AbstractUnsupportedOperationResultSet.java
├── AbstractUnsupportedOperationStatement.java
└── AbstractUnsupportedUpdateOperationResultSet.java