Sharding-Jdbc source code analysis

In sharding Jdbc, you can rewrite the four basic classes of the Jdbc base by using sharding-JDBC as an example. Take a step-by-step look at how JDBC builds a datasource.

First we chooseorg.apache.shardingsphere.example.sharding.spring.boot.jpaTo test the method, modify the local configuration file to make it work

We then put a breakpoint on createDatesource to see the parameters passed in

The createDatesource method creates a new classShardingSphereDataSourceThe first step in creating this class is initializationMetaDataContextsClass, and that class is us org.apache.shardingsphere.infraOne of the base classes in the base package let’s review the structures in the infra package here

Shardingsphere-infra % tree-L 1 ├─ ShardingSphere-Infra - Authority Proxy ├─ ShardingSphere-Infra - Binder SQL Parsing Result ├─ ShardingSphere-Infra-Common Important Basic Objects and Tools ├─ ShardingSphere-Infra-Context Set ├─ ShardingSphere-Infra-DateTime Time Services ├─ ShardingSphere-Infra - Executor Engine - Execution Engine ├─ ShardingSphere-Infra merge Engine - Merge Engine ├─ ShardingSphere-Infra - Optimize Engine - Optimization engine, New ├─ ShardingSphere Infra - Parser Engine └ ─ ShardingSphere Infra - Rewrite Engine ├─ ShardingSphere Infra - RouteCopy the code

SingletonMap first processes the incoming datasouceMap parameter and then validates XA_TRANSACTION_MANAGER_TYPE (flexible transaction type).

public ShardingSphereDataSource(final Map<String, DataSource> dataSourceMap, final Collection<RuleConfiguration> configurations, final Properties props) throws SQLException {
    metaDataContexts = new MetaDataContextsBuilder(
            Collections.singletonMap(DefaultSchema.LOGIC_NAME, dataSourceMap), Collections.singletonMap(DefaultSchema.LOGIC_NAME, configurations), props).build();
    String xaTransactionMangerType = metaDataContexts.getProps().getValue(ConfigurationPropertyKey.XA_TRANSACTION_MANAGER_TYPE);
    transactionContexts = createTransactionContexts(metaDataContexts.getDefaultMetaData().getResource().getDatabaseType(), dataSourceMap, xaTransactionMangerType);
}
Copy the code

MetaDataContextsBuilder contains a large number of initialization classes, so we will discuss build first

public StandardMetaDataContexts build() throws SQLException {
    Map<String, ShardingSphereMetaData> mataDataMap = new HashMap<>(ruleConfigs.size(), 1);
    Authentication authentication = buildAuthentication(users, mataDataMap);
    for (String each : ruleConfigs.keySet()) {
        mataDataMap.put(each, buildMetaData(each));
    }
    return new StandardMetaDataContexts(mataDataMap, executorEngine, authentication, props);
}
Copy the code

The initializer class initializes by calling the buildAuthentication method and then calling PrivilegeBuilder within the method

PrivilegeBuilderMetaDataContextsBuilder (); MetaDataContextsBuilder (); MetaDataContextsBuilder ();


private ShardingSphereMetaData buildMetaData(final String schemaName) throws SQLException {
    Map<String, DataSource> dataSourceMap = dataSources.get(schemaName);
    Collection<RuleConfiguration> ruleConfigs = this.ruleConfigs.get(schemaName);
    DatabaseType databaseType = getDatabaseType(dataSourceMap);
    Collection<ShardingSphereRule> rules = ShardingSphereRulesBuilder.build(ruleConfigs, databaseType, dataSourceMap, schemaName);
    ShardingSphereRuleMetaData ruleMetaData = new ShardingSphereRuleMetaData(ruleConfigs, rules);
    return new ShardingSphereMetaData(schemaName, buildResource(databaseType, dataSourceMap), ruleMetaData, buildSchema(schemaName, databaseType, dataSourceMap, rules));
}
Copy the code

Can see the first took a datasource and ruleconfig parameters, using ShardingSphereRulesBuilder for initialization of the rules.

Then the type of database is judged

private DatabaseType getDatabaseType(final Map<String, DataSource> dataSourceMap) { DatabaseType result = null; for (DataSource each : dataSourceMap.values()) { DatabaseType databaseType = getDatabaseType(each); Preconditions.checkState(null == result || result == databaseType, String.format("Database type inconsistent with '%s' and '%s'", result, databaseType)); result = databaseType; } return null == result ? DatabaseTypeRegistry.getDefaultDatabaseType() : result; } private DatabaseType getDatabaseType(final DataSource dataSource) { try (Connection connection = dataSource.getConnection()) { return DatabaseTypeRegistry.getDatabaseTypeByURL(connection.getMetaData().getURL()); } catch (final SQLException ex) { return null; }}Copy the code

After initial metadata context, createDataSource invokes ShardingTransactionManagerEngine initialization transaction context, need to configure the transaction will happen in the future.

private TransactionContexts createTransactionContexts(final DatabaseType databaseType, final Map<String, DataSource> dataSourceMap, final String xaTransactionMangerType) {
    ShardingTransactionManagerEngine engine = new ShardingTransactionManagerEngine();
    engine.init(databaseType, dataSourceMap, xaTransactionMangerType);
    return new StandardTransactionContexts(Collections.singletonMap(DefaultSchema.LOGIC_NAME, engine));
}
Copy the code

More on that below. How Shardingsphere integrates Atomikos’ support for XA distributed transactions If not configured, this ends the process of creating a ShardingSphereDataSource directly.