From 1303d55c36c20f3450ecc47c5a8c5868cf08129a Mon Sep 17 00:00:00 2001 From: terrymanu Date: Mon, 30 May 2016 17:26:40 +0800 Subject: [PATCH] for #85 use datasource to manage master slave --- README.md | 16 ++-- .../META-INF/rdb/withoutNamespace.xml | 25 ++--- .../rdb/withoutNamespaceStrategyOutside.xml | 17 +--- .../api/MasterSlaveDataSourceFactory.java | 47 ++++++++++ .../api/ShardingDataSourceFactory.java | 2 + .../rdb/sharding/api/rule/ShardingRule.java | 41 +-------- .../rdb/sharding/api/rule/TableRule.java | 92 ++++++------------- .../RoundRobinSlaveLoadBalanceStrategy.java | 7 +- .../slave/SlaveLoadBalanceStrategy.java | 3 +- .../MasterSlaveDataSource.java} | 37 ++++---- .../rdb/sharding/jdbc/ShardingConnection.java | 19 ++-- .../rdb/sharding/jdbc/ShardingDataSource.java | 14 +-- .../adapter/AbstractDataSourceAdapter.java | 6 ++ ...AbstractShardingMasterSlaveDBUnitTest.java | 49 ++++++---- ...ngMasterSlaveForPStatementWithDMLTest.java | 2 +- ...asterSlaveForPStatementWithSelectTest.java | 3 +- ...ingMasterSlaveForStatementWithDMLTest.java | 2 +- .../AbstractShardingNullableDBUnitTest.java | 4 +- .../ddframe/rdb/sharding/api/AllApiTests.java | 3 +- .../api/MasterSlaveDataSourceFactoryTest.java | 39 ++++++++ .../sharding/api/rule/DataSourceRuleTest.java | 2 +- .../api/rule/MasterSlaveRuleTest.java | 76 --------------- .../sharding/api/rule/ShardingRuleTest.java | 14 --- ...oundRobinSlaveLoadBalanceStrategyTest.java | 10 +- .../rule => }/fixture/TestDataSource.java | 7 +- .../rdb/sharding/jdbc/AllJDBCTests.java | 3 +- .../jdbc/MasterSlaveDataSourceTest.java | 64 +++++++++++++ .../sharding/jdbc/ShardingDataSourceTest.java | 8 -- .../jdbc/adapter/DataSourceAdapterTest.java | 7 ++ .../merger/fixture/MockResultSet.java | 2 +- sharding-jdbc-doc/content/index/index.md | 69 ++++++++++++-- .../content/post/master_slave.md | 24 ++--- 32 files changed, 374 insertions(+), 340 deletions(-) create mode 100644 sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/MasterSlaveDataSourceFactory.java rename sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/{api/rule/MasterSlaveRule.java => jdbc/MasterSlaveDataSource.java} (67%) create mode 100644 sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/MasterSlaveDataSourceFactoryTest.java delete mode 100644 sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/MasterSlaveRuleTest.java rename sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/{api/rule => }/fixture/TestDataSource.java (83%) create mode 100644 sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSourceTest.java diff --git a/README.md b/README.md index 9b39a8cd6d04c..2f3d0b3a7661a 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ * 分片策略灵活,可支持`=`,`BETWEEN`,`IN`等多维度分片,也可支持多分片键共用。 * `SQL`解析功能完善,支持聚合,分组,排序,`Limit`,`OR`等查询,并且支持`Binding Table`以及笛卡尔积的表查询。 +* 支持柔性事务(目前仅最大努力送达型)。 +* 支持读写分离。 `Sharding-JDBC`配置多样: @@ -123,14 +125,16 @@ ## 规则配置 `Sharding-JDBC`的分库分表通过规则配置描述,请简单浏览配置全貌: + ```java - ShardingRule shardingRule = ShardingRule.builder() +ShardingRule shardingRule = ShardingRule.builder() .dataSourceRule(dataSourceRule) - .tableRules(tableRules) - .databaseShardingStrategy(new DatabaseShardingStrategy("sharding_column_1", new XXXShardingAlgorithm())) - .tableShardingStrategy(new TableShardingStrategy("sharding_column_2", new XXXShardingAlgorithm()))) + .tableRules(tableRuleList) + .databaseShardingStrategy(new DatabaseShardingStrategy("sharding_column", new XXXShardingAlgorithm())) + .tableShardingStrategy(new TableShardingStrategy("sharding_column", new XXXShardingAlgorithm()))) .build(); ``` + 规则配置包括数据源配置、表规则配置、分库策略和分表策略组成。这只是最简单的配置方式,实际使用可更加灵活,如:多分片键,分片策略直接和`tableRule`绑定等。 >详细的规则配置请参考[用户指南](http://dangdangdotcom.github.io/sharding-jdbc/post/user_guide/) @@ -138,6 +142,7 @@ ## 使用原生JDBC接口 通过`ShardingDataSourceFactory`工厂和规则配置对象获取`ShardingDataSource`,`ShardingDataSource`实现自`JDBC`的标准接口`DataSource`。然后可通过`DataSource`选择使用原生`JDBC`开发,或者使用`JPA`, `MyBatis`等`ORM`工具。 以`JDBC`原生实现为例: + ```java DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule); String sql = "SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?"; @@ -150,15 +155,14 @@ try ( while(rs.next()) { System.out.println(rs.getInt(1)); System.out.println(rs.getInt(2)); - System.out.println(rs.getInt(3)); } } } ``` ## 使用Spring命名空间配置 -```xml +```xml t_order_3 - - - - - + + - - + + @@ -50,15 +47,12 @@ t_order_item_3 - - - - - + + - - + + @@ -92,9 +86,6 @@ - - - diff --git a/sharding-jdbc-config-parent/sharding-jdbc-config-spring/src/test/resources/META-INF/rdb/withoutNamespaceStrategyOutside.xml b/sharding-jdbc-config-parent/sharding-jdbc-config-spring/src/test/resources/META-INF/rdb/withoutNamespaceStrategyOutside.xml index 26b45f8665d68..a14309468e920 100644 --- a/sharding-jdbc-config-parent/sharding-jdbc-config-spring/src/test/resources/META-INF/rdb/withoutNamespaceStrategyOutside.xml +++ b/sharding-jdbc-config-parent/sharding-jdbc-config-spring/src/test/resources/META-INF/rdb/withoutNamespaceStrategyOutside.xml @@ -27,19 +27,16 @@ t_order_3 - + + - - - - @@ -53,19 +50,16 @@ t_order_item_3 - + + - - - - @@ -95,9 +89,6 @@ - - - diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/MasterSlaveDataSourceFactory.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/MasterSlaveDataSourceFactory.java new file mode 100644 index 0000000000000..f926afffdd101 --- /dev/null +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/MasterSlaveDataSourceFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright 1999-2015 dangdang.com. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *

+ */ + +package com.dangdang.ddframe.rdb.sharding.api; + +import com.dangdang.ddframe.rdb.sharding.jdbc.MasterSlaveDataSource; +import com.google.common.collect.Lists; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import javax.sql.DataSource; + +/** + * 读写分离数据源工厂. + * + * @author zhangliang + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class MasterSlaveDataSourceFactory { + + /** + * 创建读写分离数据源. + * + * @param logicDataSourceName 逻辑数据源名称 + * @param masterDataSource 主节点数据源 + * @param slaveDataSource 从节点数据源 + * @param otherSlaveDataSources 其他从节点数据源 + * @return 读写分离数据源 + */ + public static DataSource createDataSource(final String logicDataSourceName, final DataSource masterDataSource, final DataSource slaveDataSource, final DataSource... otherSlaveDataSources) { + return new MasterSlaveDataSource(logicDataSourceName, masterDataSource, Lists.asList(slaveDataSource, otherSlaveDataSources)); + } +} diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/ShardingDataSourceFactory.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/ShardingDataSourceFactory.java index 27d3ab4720c65..066ebbac4887f 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/ShardingDataSourceFactory.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/ShardingDataSourceFactory.java @@ -27,6 +27,8 @@ /** * 分片数据源工厂. + * + * @author zhangliang */ @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class ShardingDataSourceFactory { diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/ShardingRule.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/ShardingRule.java index cd783c3ea701a..4289609373933 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/ShardingRule.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/ShardingRule.java @@ -21,11 +21,8 @@ import com.dangdang.ddframe.rdb.sharding.api.strategy.database.NoneDatabaseShardingAlgorithm; import com.dangdang.ddframe.rdb.sharding.api.strategy.table.NoneTableShardingAlgorithm; import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy; -import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import lombok.AccessLevel; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -33,7 +30,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.Map; import java.util.Set; /** @@ -54,9 +50,6 @@ public final class ShardingRule { private final TableShardingStrategy tableShardingStrategy; - @Getter(AccessLevel.NONE) - private final Map masterSlaveRuleMap; - /** * 全属性构造器. * @@ -69,7 +62,7 @@ public final class ShardingRule { @Deprecated public ShardingRule( final DataSourceRule dataSourceRule, final Collection tableRules, final Collection bindingTableRules, - final DatabaseShardingStrategy databaseShardingStrategy, final TableShardingStrategy tableShardingStrategy, final Collection masterSlaveRules) { + final DatabaseShardingStrategy databaseShardingStrategy, final TableShardingStrategy tableShardingStrategy) { Preconditions.checkNotNull(dataSourceRule); Preconditions.checkNotNull(tableRules); this.dataSourceRule = dataSourceRule; @@ -79,13 +72,6 @@ public ShardingRule( Collections.emptyList(), new NoneDatabaseShardingAlgorithm()) : databaseShardingStrategy; this.tableShardingStrategy = null == tableShardingStrategy ? new TableShardingStrategy( Collections.emptyList(), new NoneTableShardingAlgorithm()) : tableShardingStrategy; - masterSlaveRuleMap = Maps.uniqueIndex(null == masterSlaveRules ? Collections.emptyList() : masterSlaveRules, new Function() { - - @Override - public String apply(final MasterSlaveRule input) { - return input.getLogicDataSource(); - } - }); } /** @@ -226,16 +212,6 @@ public Collection getAllShardingColumns() { return result; } - /** - * 根据逻辑数据源名称获取读写分离配置. - * - * @param logicDataSource 逻辑数据源名称 - * @return 读写分离配置 - */ - public Optional findMasterSlaveRule(final String logicDataSource) { - return Optional.fromNullable(masterSlaveRuleMap.get(logicDataSource)); - } - /** * 分片规则配置对象构建器. */ @@ -252,8 +228,6 @@ public static class ShardingRuleBuilder { private TableShardingStrategy tableShardingStrategy; - private Collection masterSlaveRules; - /** * 构建数据源配置规则. * @@ -309,24 +283,13 @@ public ShardingRuleBuilder tableShardingStrategy(final TableShardingStrategy tab return this; } - /** - * 构建数据源分片规则. - * - * @param masterSlaveRules 读写分离策略集合 - * @return 分片规则配置对象构建器 - */ - public ShardingRuleBuilder masterSlaveRules(final Collection masterSlaveRules) { - this.masterSlaveRules = masterSlaveRules; - return this; - } - /** * 构建分片规则配置对象. * * @return 分片规则配置对象 */ public ShardingRule build() { - return new ShardingRule(dataSourceRule, tableRules, bindingTableRules, databaseShardingStrategy, tableShardingStrategy, masterSlaveRules); + return new ShardingRule(dataSourceRule, tableRules, bindingTableRules, databaseShardingStrategy, tableShardingStrategy); } } } diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/TableRule.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/TableRule.java index 99da1a7505431..e7d9de460adac 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/TableRule.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/TableRule.java @@ -19,9 +19,7 @@ import com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy; import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy; -import com.google.common.base.Function; import com.google.common.base.Preconditions; -import com.google.common.collect.Collections2; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.ToString; @@ -61,8 +59,8 @@ public final class TableRule { * @deprecated 未来将改为private权限, 不在对外公开, 不建议使用非Spring命名空间的配置. */ @Deprecated - public TableRule(final String logicTable, final boolean dynamic, final List actualTables, final Collection masterSlaveRules, final DataSourceRule dataSourceRule, - final Collection dataSourceNames, final DatabaseShardingStrategy databaseShardingStrategy, final TableShardingStrategy tableShardingStrategy) { + public TableRule(final String logicTable, final boolean dynamic, final List actualTables, final DataSourceRule dataSourceRule, final Collection dataSourceNames, + final DatabaseShardingStrategy databaseShardingStrategy, final TableShardingStrategy tableShardingStrategy) { Preconditions.checkNotNull(logicTable); this.logicTable = logicTable; this.dynamic = dynamic; @@ -70,27 +68,27 @@ public TableRule(final String logicTable, final boolean dynamic, final List generateDataNodes(final Collection masterSlaveRules, final DataSourceRule dataSourceRule) { - Collection dataSourceNames = getLogicDataSourceNames(masterSlaveRules, dataSourceRule.getDataSourceNames()); + private List generateDataNodes(final DataSourceRule dataSourceRule) { + Collection dataSourceNames = dataSourceRule.getDataSourceNames(); List result = new ArrayList<>(dataSourceNames.size()); for (String each : dataSourceNames) { result.add(new DynamicDataNode(each)); @@ -98,9 +96,8 @@ private List generateDataNodes(final Collection maste return result; } - private List generateDataNodes(final List actualTables, final Collection masterSlaveRules, - final DataSourceRule dataSourceRule, final Collection actualDataSourceNames) { - Collection dataSourceNames = getLogicDataSourceNames(masterSlaveRules, getDataSourceNames(masterSlaveRules, dataSourceRule, actualDataSourceNames)); + private List generateDataNodes(final List actualTables, final DataSourceRule dataSourceRule, final Collection actualDataSourceNames) { + Collection dataSourceNames = getDataSourceNames(dataSourceRule, actualDataSourceNames); List result = new ArrayList<>(actualTables.size() * (dataSourceNames.isEmpty() ? 1 : dataSourceNames.size())); for (String actualTable : actualTables) { if (DataNode.isValidDataNode(actualTable)) { @@ -114,41 +111,19 @@ private List generateDataNodes(final List actualTables, final return result; } - private Collection getDataSourceNames(final Collection masterSlaveRules, final DataSourceRule dataSourceRule, final Collection actualDataSourceNames) { + private Collection getDataSourceNames(final DataSourceRule dataSourceRule, final Collection actualDataSourceNames) { if (null == dataSourceRule) { return Collections.emptyList(); } if (null == actualDataSourceNames || actualDataSourceNames.isEmpty()) { return dataSourceRule.getDataSourceNames(); } - return getLogicDataSourceNames(masterSlaveRules, actualDataSourceNames); - } - - private Collection getLogicDataSourceNames(final Collection masterSlaveRules, final Collection dataSourceNames) { - if (null == masterSlaveRules) { - return dataSourceNames; - } - return Collections2.transform(dataSourceNames, new Function() { - - @Override - public String apply(final String input) { - return getLogicDataSourceName(masterSlaveRules, input); - } - }); - } - - private String getLogicDataSourceName(final Collection masterSlaveRules, final String dataSourceName) { - for (MasterSlaveRule each : masterSlaveRules) { - if (each.within(dataSourceName)) { - return each.getLogicDataSource(); - } - } - return dataSourceName; + return actualDataSourceNames; } /** * 根据数据源名称过滤获取真实数据单元. - * + * * @param targetDataSources 数据源名称集合 * @param targetTables 真实表名称集合 * @return 真实数据单元 @@ -193,7 +168,7 @@ public Collection getActualDatasourceNames() { /** * 根据数据源名称过滤获取真实表名称. - * + * * @param targetDataSources 数据源名称 * @return 真实表名称 */ @@ -229,11 +204,9 @@ public static class TableRuleBuilder { private boolean dynamic; private List actualTables; - - private Collection masterSlaveRules; - + private DataSourceRule dataSourceRule; - + private Collection dataSourceNames; private DatabaseShardingStrategy databaseShardingStrategy; @@ -242,9 +215,9 @@ public static class TableRuleBuilder { /** * 构建是否为动态表. - * + * * @param dynamic 是否为动态表 - * @return 规则配置对象构建器 + * @return 真实表集合 */ public TableRuleBuilder dynamic(final boolean dynamic) { this.dynamic = dynamic; @@ -253,29 +226,18 @@ public TableRuleBuilder dynamic(final boolean dynamic) { /** * 构建真实表集合. - * + * * @param actualTables 真实表集合 - * @return 规则配置对象构建器 + * @return 真实表集合 */ public TableRuleBuilder actualTables(final List actualTables) { this.actualTables = actualTables; return this; } - - /** - * 构建读写分离规则. - * - * @param masterSlaveRules 读写分离规则 - * @return 规则配置对象构建器 - */ - public TableRuleBuilder masterSlaveRules(final Collection masterSlaveRules) { - this.masterSlaveRules = masterSlaveRules; - return this; - } /** * 构建数据源分片规则. - * + * * @param dataSourceRule 数据源分片规则 * @return 规则配置对象构建器 */ @@ -283,7 +245,7 @@ public TableRuleBuilder dataSourceRule(final DataSourceRule dataSourceRule) { this.dataSourceRule = dataSourceRule; return this; } - + /** * 构建数据源分片规则. * @@ -297,7 +259,7 @@ public TableRuleBuilder dataSourceNames(final Collection dataSourceNames /** * 构建数据库分片策略. - * + * * @param databaseShardingStrategy 数据库分片策略 * @return 规则配置对象构建器 */ @@ -308,7 +270,7 @@ public TableRuleBuilder databaseShardingStrategy(final DatabaseShardingStrategy /** * 构建表分片策略. - * + * * @param tableShardingStrategy 表分片策略 * @return 规则配置对象构建器 */ @@ -319,11 +281,11 @@ public TableRuleBuilder tableShardingStrategy(final TableShardingStrategy tableS /** * 构建表规则配置对象. - * + * * @return 表规则配置对象 */ public TableRule build() { - return new TableRule(logicTable, dynamic, actualTables, masterSlaveRules, dataSourceRule, dataSourceNames, databaseShardingStrategy, tableShardingStrategy); + return new TableRule(logicTable, dynamic, actualTables, dataSourceRule, dataSourceNames, databaseShardingStrategy, tableShardingStrategy); } } } diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/RoundRobinSlaveLoadBalanceStrategy.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/RoundRobinSlaveLoadBalanceStrategy.java index 283940761fd42..a601cd8a0e2b7 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/RoundRobinSlaveLoadBalanceStrategy.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/RoundRobinSlaveLoadBalanceStrategy.java @@ -17,6 +17,7 @@ package com.dangdang.ddframe.rdb.sharding.api.strategy.slave; +import javax.sql.DataSource; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; @@ -31,12 +32,10 @@ public final class RoundRobinSlaveLoadBalanceStrategy implements SlaveLoadBalanc private static final ConcurrentHashMap COUNT_MAP = new ConcurrentHashMap<>(); @Override - public String getDataSource(final String logicDataSource, final List slaveDataSources) { + public DataSource getDataSource(final String logicDataSource, final List slaveDataSources) { AtomicInteger count = COUNT_MAP.containsKey(logicDataSource) ? COUNT_MAP.get(logicDataSource) : new AtomicInteger(0); COUNT_MAP.putIfAbsent(logicDataSource, count); - if (count.get() >= slaveDataSources.size()) { - count.set(0); - } + count.compareAndSet(slaveDataSources.size(), 0); return slaveDataSources.get(count.getAndIncrement() % slaveDataSources.size()); } } diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/SlaveLoadBalanceStrategy.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/SlaveLoadBalanceStrategy.java index 7bd4fe4b8bb75..88a1076164b27 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/SlaveLoadBalanceStrategy.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/SlaveLoadBalanceStrategy.java @@ -17,6 +17,7 @@ package com.dangdang.ddframe.rdb.sharding.api.strategy.slave; +import javax.sql.DataSource; import java.util.List; /** @@ -33,5 +34,5 @@ public interface SlaveLoadBalanceStrategy { * @param slaveDataSources 从库数据源列表 * @return 选中的从库数据源 */ - String getDataSource(final String logicDataSource, final List slaveDataSources); + DataSource getDataSource(final String logicDataSource, final List slaveDataSources); } diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/MasterSlaveRule.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSource.java similarity index 67% rename from sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/MasterSlaveRule.java rename to sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSource.java index 35fc3ba7a5064..409df3af7a490 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/rule/MasterSlaveRule.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSource.java @@ -15,24 +15,26 @@ *

*/ -package com.dangdang.ddframe.rdb.sharding.api.rule; +package com.dangdang.ddframe.rdb.sharding.jdbc; import com.dangdang.ddframe.rdb.sharding.api.strategy.slave.RoundRobinSlaveLoadBalanceStrategy; import com.dangdang.ddframe.rdb.sharding.api.strategy.slave.SlaveLoadBalanceStrategy; +import com.dangdang.ddframe.rdb.sharding.jdbc.adapter.AbstractDataSourceAdapter; import com.dangdang.ddframe.rdb.sharding.parser.result.router.SQLStatementType; -import lombok.Getter; import lombok.RequiredArgsConstructor; +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; import java.util.List; /** - * 读写分离配置规则. + * 支持读写分离的数据源. * * @author zhangliang */ @RequiredArgsConstructor -@Getter -public final class MasterSlaveRule { +public final class MasterSlaveDataSource extends AbstractDataSourceAdapter { private static final ThreadLocal WAS_UPDATED = new ThreadLocal() { @@ -42,35 +44,30 @@ protected Boolean initialValue() { } }; - private final String logicDataSource; + private final String logicDataSourceName; - private final String masterDataSource; + private final DataSource masterDataSource; - private final List slaveDataSources; + private final List slaveDataSources; private final SlaveLoadBalanceStrategy slaveLoadBalanceStrategy = new RoundRobinSlaveLoadBalanceStrategy(); /** * 获取主或从节点的数据源名称. - * + * * @param sqlStatementType SQL类型 - * @return 主或从节点的数据源名称 + * @return 主或从节点的数据源 */ - public String getMasterOrSlaveDataSource(final SQLStatementType sqlStatementType) { + public DataSource getDataSource(final SQLStatementType sqlStatementType) { if (SQLStatementType.SELECT != sqlStatementType || WAS_UPDATED.get()) { WAS_UPDATED.set(true); return masterDataSource; } - return slaveLoadBalanceStrategy.getDataSource(logicDataSource, slaveDataSources); + return slaveLoadBalanceStrategy.getDataSource(logicDataSourceName, slaveDataSources); } - /** - * 判断该真实数据源是否属于本读写分离规则配置. - * - * @param actualDataSource 真实数据源名称 - * @return 是否属于本读写分离规则配置 - */ - public boolean within(final String actualDataSource) { - return actualDataSource.equals(masterDataSource) || slaveDataSources.contains(actualDataSource); + @Override + public Connection getConnection() throws SQLException { + throw new UnsupportedOperationException("Master slave data source cannot support get connection directly."); } } diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingConnection.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingConnection.java index 4da06ca3af496..17bbe32236b5d 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingConnection.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingConnection.java @@ -18,16 +18,15 @@ package com.dangdang.ddframe.rdb.sharding.jdbc; import com.codahale.metrics.Timer.Context; -import com.dangdang.ddframe.rdb.sharding.api.rule.MasterSlaveRule; import com.dangdang.ddframe.rdb.sharding.jdbc.adapter.AbstractConnectionAdapter; import com.dangdang.ddframe.rdb.sharding.metrics.MetricsContext; import com.dangdang.ddframe.rdb.sharding.parser.result.router.SQLStatementType; import com.google.common.base.Joiner; -import com.google.common.base.Optional; import lombok.AccessLevel; import lombok.Getter; import lombok.RequiredArgsConstructor; +import javax.sql.DataSource; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; @@ -70,15 +69,17 @@ public DatabaseMetaData getMetaData() throws SQLException { } private Connection getConnectionInternal(final String dataSourceName, final SQLStatementType sqlStatementType) throws SQLException { - Optional masterSlaveRule = shardingContext.getShardingRule().findMasterSlaveRule(dataSourceName); - String actualDataSourceName = masterSlaveRule.isPresent() ? masterSlaveRule.get().getMasterOrSlaveDataSource(sqlStatementType) : dataSourceName; - if (connectionMap.containsKey(actualDataSourceName)) { - return connectionMap.get(actualDataSourceName); + if (connectionMap.containsKey(dataSourceName)) { + return connectionMap.get(dataSourceName); } - Context metricsContext = MetricsContext.start(Joiner.on("-").join("ShardingConnection-getConnection", actualDataSourceName)); - Connection result = shardingContext.getShardingRule().getDataSourceRule().getDataSource(actualDataSourceName).getConnection(); + Context metricsContext = MetricsContext.start(Joiner.on("-").join("ShardingConnection-getConnection", dataSourceName)); + DataSource dataSource = shardingContext.getShardingRule().getDataSourceRule().getDataSource(dataSourceName); + if (dataSource instanceof MasterSlaveDataSource) { + dataSource = ((MasterSlaveDataSource) dataSource).getDataSource(sqlStatementType); + } + Connection result = dataSource.getConnection(); MetricsContext.stop(metricsContext); - connectionMap.put(actualDataSourceName, result); + connectionMap.put(dataSourceName, result); return result; } diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingDataSource.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingDataSource.java index e004f2c46942a..9c7b262f7c3a0 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingDataSource.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingDataSource.java @@ -24,6 +24,7 @@ import com.dangdang.ddframe.rdb.sharding.executor.ExecutorEngine; import com.dangdang.ddframe.rdb.sharding.jdbc.adapter.AbstractDataSourceAdapter; import com.dangdang.ddframe.rdb.sharding.metrics.MetricsContext; +import com.dangdang.ddframe.rdb.sharding.parser.result.router.SQLStatementType; import com.dangdang.ddframe.rdb.sharding.router.SQLRouteEngine; import com.google.common.base.Preconditions; @@ -64,7 +65,13 @@ private String getDatabaseProductName(final ShardingRule shardingRule) throws SQ String result = null; Collection connections = new ArrayList<>(shardingRule.getDataSourceRule().getDataSources().size()); for (DataSource each : shardingRule.getDataSourceRule().getDataSources()) { - Connection connection = each.getConnection(); + DataSource dataSource; + if (each instanceof MasterSlaveDataSource) { + dataSource = ((MasterSlaveDataSource) each).getDataSource(SQLStatementType.SELECT); + } else { + dataSource = each; + } + Connection connection = dataSource.getConnection(); connections.add(connection); String databaseProductName = connection.getMetaData().getDatabaseProductName(); Preconditions.checkState(null == result || result.equals(databaseProductName), String.format("Database type inconsistent with '%s' and '%s'", result, databaseProductName)); @@ -81,9 +88,4 @@ public ShardingConnection getConnection() throws SQLException { MetricsContext.init(shardingProperties); return new ShardingConnection(shardingContext); } - - @Override - public final ShardingConnection getConnection(final String username, final String password) throws SQLException { - return getConnection(); - } } diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/adapter/AbstractDataSourceAdapter.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/adapter/AbstractDataSourceAdapter.java index b32e76a515d25..540a25e0c20a8 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/adapter/AbstractDataSourceAdapter.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/adapter/AbstractDataSourceAdapter.java @@ -21,6 +21,7 @@ import lombok.RequiredArgsConstructor; import java.io.PrintWriter; +import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.logging.Logger; @@ -49,4 +50,9 @@ public final void setLogWriter(final PrintWriter out) throws SQLException { public final Logger getParentLogger() throws SQLFeatureNotSupportedException { return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); } + + @Override + public final Connection getConnection(final String username, final String password) throws SQLException { + return getConnection(); + } } diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/AbstractShardingMasterSlaveDBUnitTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/AbstractShardingMasterSlaveDBUnitTest.java index 2da4a8e028463..70523b19fbce7 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/AbstractShardingMasterSlaveDBUnitTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/AbstractShardingMasterSlaveDBUnitTest.java @@ -22,11 +22,11 @@ import com.dangdang.ddframe.rdb.integrate.fixture.SingleKeyModuloTableShardingAlgorithm; import com.dangdang.ddframe.rdb.sharding.api.rule.BindingTableRule; import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule; -import com.dangdang.ddframe.rdb.sharding.api.rule.MasterSlaveRule; import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule; import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule; import com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy; import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy; +import com.dangdang.ddframe.rdb.sharding.jdbc.MasterSlaveDataSource; import com.dangdang.ddframe.rdb.sharding.jdbc.ShardingDataSource; import org.junit.After; import org.junit.Before; @@ -34,8 +34,8 @@ import javax.sql.DataSource; import java.lang.reflect.Field; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -46,9 +46,9 @@ public abstract class AbstractShardingMasterSlaveDBUnitTest extends AbstractDBUn @Before @After public void reset() throws NoSuchFieldException, IllegalAccessException { - Field field = MasterSlaveRule.class.getDeclaredField("WAS_UPDATED"); + Field field = MasterSlaveDataSource.class.getDeclaredField("WAS_UPDATED"); field.setAccessible(true); - ((ThreadLocal) field.get(MasterSlaveRule.class)).remove(); + ((ThreadLocal) field.get(MasterSlaveDataSource.class)).remove(); } @Override @@ -102,19 +102,29 @@ protected List getDataSetFiles() { } protected final ShardingDataSource getShardingDataSource() { - Map dataSourceMap = createDataSourceMap(dataSourceName); + Map masterSlaveDataSourceMap = createDataSourceMap(dataSourceName); + MasterSlaveDataSource masterSlaveDs0 = new MasterSlaveDataSource("ms_0", masterSlaveDataSourceMap.get("dataSource_master_0"), Collections.singletonList(masterSlaveDataSourceMap.get("dataSource_slave_0"))); + MasterSlaveDataSource masterSlaveDs1 = new MasterSlaveDataSource("ms_1", masterSlaveDataSourceMap.get("dataSource_master_1"), Collections.singletonList(masterSlaveDataSourceMap.get("dataSource_slave_1"))); + MasterSlaveDataSource masterSlaveDs2 = new MasterSlaveDataSource("ms_2", masterSlaveDataSourceMap.get("dataSource_master_2"), Collections.singletonList(masterSlaveDataSourceMap.get("dataSource_slave_2"))); + MasterSlaveDataSource masterSlaveDs3 = new MasterSlaveDataSource("ms_3", masterSlaveDataSourceMap.get("dataSource_master_3"), Collections.singletonList(masterSlaveDataSourceMap.get("dataSource_slave_3"))); + MasterSlaveDataSource masterSlaveDs4 = new MasterSlaveDataSource("ms_4", masterSlaveDataSourceMap.get("dataSource_master_4"), Collections.singletonList(masterSlaveDataSourceMap.get("dataSource_slave_4"))); + MasterSlaveDataSource masterSlaveDs5 = new MasterSlaveDataSource("ms_5", masterSlaveDataSourceMap.get("dataSource_master_5"), Collections.singletonList(masterSlaveDataSourceMap.get("dataSource_slave_5"))); + MasterSlaveDataSource masterSlaveDs6 = new MasterSlaveDataSource("ms_6", masterSlaveDataSourceMap.get("dataSource_master_6"), Collections.singletonList(masterSlaveDataSourceMap.get("dataSource_slave_6"))); + MasterSlaveDataSource masterSlaveDs7 = new MasterSlaveDataSource("ms_7", masterSlaveDataSourceMap.get("dataSource_master_7"), Collections.singletonList(masterSlaveDataSourceMap.get("dataSource_slave_7"))); + MasterSlaveDataSource masterSlaveDs8 = new MasterSlaveDataSource("ms_8", masterSlaveDataSourceMap.get("dataSource_master_8"), Collections.singletonList(masterSlaveDataSourceMap.get("dataSource_slave_8"))); + MasterSlaveDataSource masterSlaveDs9 = new MasterSlaveDataSource("ms_9", masterSlaveDataSourceMap.get("dataSource_master_9"), Collections.singletonList(masterSlaveDataSourceMap.get("dataSource_slave_9"))); + Map dataSourceMap = new HashMap<>(10); + dataSourceMap.put("ms_0", masterSlaveDs0); + dataSourceMap.put("ms_1", masterSlaveDs1); + dataSourceMap.put("ms_2", masterSlaveDs2); + dataSourceMap.put("ms_3", masterSlaveDs3); + dataSourceMap.put("ms_4", masterSlaveDs4); + dataSourceMap.put("ms_5", masterSlaveDs5); + dataSourceMap.put("ms_6", masterSlaveDs6); + dataSourceMap.put("ms_7", masterSlaveDs7); + dataSourceMap.put("ms_8", masterSlaveDs8); + dataSourceMap.put("ms_9", masterSlaveDs9); DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap); - Collection masterSlaveRules = Arrays.asList( - new MasterSlaveRule("ms_0", "dataSource_master_0", Collections.singletonList("dataSource_slave_0")), - new MasterSlaveRule("ms_1", "dataSource_master_1", Collections.singletonList("dataSource_slave_1")), - new MasterSlaveRule("ms_2", "dataSource_master_2", Collections.singletonList("dataSource_slave_2")), - new MasterSlaveRule("ms_3", "dataSource_master_3", Collections.singletonList("dataSource_slave_3")), - new MasterSlaveRule("ms_4", "dataSource_master_4", Collections.singletonList("dataSource_slave_4")), - new MasterSlaveRule("ms_5", "dataSource_master_5", Collections.singletonList("dataSource_slave_5")), - new MasterSlaveRule("ms_6", "dataSource_master_6", Collections.singletonList("dataSource_slave_6")), - new MasterSlaveRule("ms_7", "dataSource_master_7", Collections.singletonList("dataSource_slave_7")), - new MasterSlaveRule("ms_8", "dataSource_master_8", Collections.singletonList("dataSource_slave_8")), - new MasterSlaveRule("ms_9", "dataSource_master_9", Collections.singletonList("dataSource_slave_9"))); TableRule orderTableRule = TableRule.builder("t_order").actualTables(Arrays.asList( "t_order_0", "t_order_1", @@ -125,7 +135,7 @@ protected final ShardingDataSource getShardingDataSource() { "t_order_6", "t_order_7", "t_order_8", - "t_order_9")).masterSlaveRules(masterSlaveRules).dataSourceRule(dataSourceRule).build(); + "t_order_9")).dataSourceRule(dataSourceRule).build(); TableRule orderItemTableRule = TableRule.builder("t_order_item").actualTables(Arrays.asList( "t_order_item_0", "t_order_item_1", @@ -136,13 +146,12 @@ protected final ShardingDataSource getShardingDataSource() { "t_order_item_6", "t_order_item_7", "t_order_item_8", - "t_order_item_9")).masterSlaveRules(masterSlaveRules).dataSourceRule(dataSourceRule).build(); + "t_order_item_9")).dataSourceRule(dataSourceRule).build(); TableRule configRule = TableRule.builder("t_config").dataSourceRule(dataSourceRule).build(); ShardingRule shardingRule = ShardingRule.builder().dataSourceRule(dataSourceRule).tableRules(Arrays.asList(orderTableRule, orderItemTableRule, configRule)) .bindingTableRules(Collections.singletonList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule)))) .databaseShardingStrategy(new DatabaseShardingStrategy("user_id", new SingleKeyModuloDatabaseShardingAlgorithm())) - .tableShardingStrategy(new TableShardingStrategy("order_id", new SingleKeyModuloTableShardingAlgorithm())) - .masterSlaveRules(masterSlaveRules).build(); + .tableShardingStrategy(new TableShardingStrategy("order_id", new SingleKeyModuloTableShardingAlgorithm())).build(); return new ShardingDataSource(shardingRule); } } diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/pstatement/ShardingMasterSlaveForPStatementWithDMLTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/pstatement/ShardingMasterSlaveForPStatementWithDMLTest.java index c8762abfdd57c..3a16bc0d07003 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/pstatement/ShardingMasterSlaveForPStatementWithDMLTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/pstatement/ShardingMasterSlaveForPStatementWithDMLTest.java @@ -155,7 +155,7 @@ protected void assertDataSet(final String expectedDataSetPattern, final String s for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { assertDataSet(String.format("integrate/dataset/masterslave/expect/%s/master_%s.xml", expectedDataSetPattern, i), - shardingDataSource.getConnection().getConnection(String.format("dataSource_master_%s", i), SQLStatementType.SELECT), + shardingDataSource.getConnection().getConnection(String.format("ms_%s", i), SQLStatementType.SELECT), String.format("t_order_%s", j), String.format("SELECT * FROM `t_order_%s` WHERE `status`=?", j), status); } } diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/pstatement/ShardingMasterSlaveForPStatementWithSelectTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/pstatement/ShardingMasterSlaveForPStatementWithSelectTest.java index 0abdcf4acca94..65520d4023c93 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/pstatement/ShardingMasterSlaveForPStatementWithSelectTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/pstatement/ShardingMasterSlaveForPStatementWithSelectTest.java @@ -30,8 +30,9 @@ public class ShardingMasterSlaveForPStatementWithSelectTest extends AbstractShar private ShardingDataSource shardingDataSource; @Before - public void init() throws SQLException { + public void init() throws SQLException, NoSuchFieldException, IllegalAccessException { shardingDataSource = getShardingDataSource(); + reset(); } @Test diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/statement/ShardingMasterSlaveForStatementWithDMLTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/statement/ShardingMasterSlaveForStatementWithDMLTest.java index e85b0a95015a8..a06e9354cf0ad 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/statement/ShardingMasterSlaveForStatementWithDMLTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/masterslave/statement/ShardingMasterSlaveForStatementWithDMLTest.java @@ -84,7 +84,7 @@ protected void assertDataSet(final String expectedDataSetPattern, final String s for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { assertDataSet(String.format("integrate/dataset/masterslave/expect/%s/master_%s.xml", expectedDataSetPattern, i), - shardingDataSource.getConnection().getConnection(String.format("dataSource_master_%s", i), SQLStatementType.SELECT), + shardingDataSource.getConnection().getConnection(String.format("ms_%s", i), SQLStatementType.SELECT), String.format("t_order_%s", j), String.format("SELECT * FROM `t_order_%s` WHERE `status`=?", j), status); } } diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/nullable/AbstractShardingNullableDBUnitTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/nullable/AbstractShardingNullableDBUnitTest.java index b75c3ad2259c8..4fd5cf3dc1713 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/nullable/AbstractShardingNullableDBUnitTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/integrate/nullable/AbstractShardingNullableDBUnitTest.java @@ -70,8 +70,8 @@ protected final ShardingDataSource getShardingDataSource() { DataSourceRule dataSourceRule = new DataSourceRule(createDataSourceMap(dataSourceName)); TableRule orderTableRule = TableRule.builder("t_order").dataSourceRule(dataSourceRule).build(); - ShardingRule shardingRule = ShardingRule.builder().dataSourceRule(dataSourceRule).tableRules(Arrays.asList(orderTableRule)) - .bindingTableRules(Collections.singletonList(new BindingTableRule(Arrays.asList(orderTableRule)))) + ShardingRule shardingRule = ShardingRule.builder().dataSourceRule(dataSourceRule).tableRules(Collections.singletonList(orderTableRule)) + .bindingTableRules(Collections.singletonList(new BindingTableRule(Collections.singletonList(orderTableRule)))) .databaseShardingStrategy(new DatabaseShardingStrategy(Collections.singletonList("user_id"), new MultipleKeysModuloDatabaseShardingAlgorithm())) .tableShardingStrategy(new TableShardingStrategy(Collections.singletonList("order_id"), new NoneTableShardingAlgorithm())).build(); return new ShardingDataSource(shardingRule); diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/AllApiTests.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/AllApiTests.java index f9b7058a8c48c..8cb242fb5e1a3 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/AllApiTests.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/AllApiTests.java @@ -21,7 +21,6 @@ import com.dangdang.ddframe.rdb.sharding.api.rule.DataNodeTest; import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRuleTest; import com.dangdang.ddframe.rdb.sharding.api.rule.DynamicDataNodeTest; -import com.dangdang.ddframe.rdb.sharding.api.rule.MasterSlaveRuleTest; import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRuleTest; import com.dangdang.ddframe.rdb.sharding.api.rule.TableRuleTest; import com.dangdang.ddframe.rdb.sharding.api.strategy.common.ShardingStrategyTest; @@ -53,7 +52,7 @@ TableShardingStrategyTest.class, NoneTableShardingAlgorithmTest.class, HintManagerTest.class, - MasterSlaveRuleTest.class, + MasterSlaveDataSourceFactoryTest.class, RoundRobinSlaveLoadBalanceStrategyTest.class }) public class AllApiTests { diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/MasterSlaveDataSourceFactoryTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/MasterSlaveDataSourceFactoryTest.java new file mode 100644 index 0000000000000..90918ee756afa --- /dev/null +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/MasterSlaveDataSourceFactoryTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 1999-2015 dangdang.com. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *

+ */ + +package com.dangdang.ddframe.rdb.sharding.api; + +import com.dangdang.ddframe.rdb.sharding.fixture.TestDataSource; +import com.dangdang.ddframe.rdb.sharding.jdbc.MasterSlaveDataSource; +import org.junit.Test; + +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.junit.Assert.assertThat; + +public final class MasterSlaveDataSourceFactoryTest { + + @Test + public void assertCreateDataSourceForSingleSlave() { + assertThat(MasterSlaveDataSourceFactory.createDataSource("logic_ds", new TestDataSource("master_ds"), new TestDataSource("slave_ds")), instanceOf(MasterSlaveDataSource.class)); + } + + @Test + public void assertCreateDataSourceForMultipleSlaves() { + assertThat(MasterSlaveDataSourceFactory.createDataSource("logic_ds", new TestDataSource("master_ds"), new TestDataSource("slave_ds_0"), new TestDataSource("slave_ds_1")), + instanceOf(MasterSlaveDataSource.class)); + } +} diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/DataSourceRuleTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/DataSourceRuleTest.java index 4469e728d2702..8d40f8e0c1e08 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/DataSourceRuleTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/DataSourceRuleTest.java @@ -17,7 +17,7 @@ package com.dangdang.ddframe.rdb.sharding.api.rule; -import com.dangdang.ddframe.rdb.sharding.api.rule.fixture.TestDataSource; +import com.dangdang.ddframe.rdb.sharding.fixture.TestDataSource; import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/MasterSlaveRuleTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/MasterSlaveRuleTest.java deleted file mode 100644 index b56c4a7c45a4a..0000000000000 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/MasterSlaveRuleTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 1999-2015 dangdang.com. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *

- */ - -package com.dangdang.ddframe.rdb.sharding.api.rule; - -import com.dangdang.ddframe.rdb.sharding.parser.result.router.SQLStatementType; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Collections; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - -public final class MasterSlaveRuleTest { - - private MasterSlaveRule masterSlaveRule = new MasterSlaveRule("test_ds", "test_ds_master", Collections.singletonList("test_ds_slave")); - - @Before - @After - public void reset() throws NoSuchFieldException, IllegalAccessException { - Field field = MasterSlaveRule.class.getDeclaredField("WAS_UPDATED"); - field.setAccessible(true); - ((ThreadLocal) field.get(MasterSlaveRule.class)).remove(); - } - - @Test - public void assertGetMasterOrSlaveDataSourceForDML() { - assertThat(masterSlaveRule.getMasterOrSlaveDataSource(SQLStatementType.INSERT), is("test_ds_master")); - } - - @Test - public void assertGetMasterOrSlaveDataSourceForDQL() { - assertThat(masterSlaveRule.getMasterOrSlaveDataSource(SQLStatementType.SELECT), is("test_ds_slave")); - } - - @Test - public void assertGetMasterOrSlaveDataSourceForDMLAndDQL() { - assertThat(masterSlaveRule.getMasterOrSlaveDataSource(SQLStatementType.INSERT), is("test_ds_master")); - assertThat(masterSlaveRule.getMasterOrSlaveDataSource(SQLStatementType.SELECT), is("test_ds_master")); - } - - @Test - public void assertWithinForMaster() { - assertTrue(masterSlaveRule.within("test_ds_master")); - } - - @Test - public void assertWithinForSlave() { - assertTrue(masterSlaveRule.within("test_ds_slave")); - } - - @Test - public void assertNotWithin() { - assertFalse(masterSlaveRule.within("test_ds")); - } -} diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/ShardingRuleTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/ShardingRuleTest.java index 987e4ff70c82b..4a5c36312f040 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/ShardingRuleTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/ShardingRuleTest.java @@ -202,26 +202,12 @@ public void assertGetAllShardingColumnsWithStrategy() { assertThat(createShardingRuleWithStrategy().getAllShardingColumns(), is((Collection) Sets.newHashSet("column"))); } - @Test - public void assertFindMasterSlaveRule() { - ShardingRule shardingRule = createShardingRule( - Arrays.asList(new MasterSlaveRule("ds0", "ds0_master", Collections.singletonList("ds0_slave")), new MasterSlaveRule("ds1", "ds1_master", Arrays.asList("ds1_slave_1", "ds1_slave_2")))); - assertThat(shardingRule.findMasterSlaveRule("ds0").get().getMasterDataSource(), is("ds0_master")); - assertThat(shardingRule.findMasterSlaveRule("ds1").get().getMasterDataSource(), is("ds1_master")); - assertFalse(shardingRule.findMasterSlaveRule("ds2").isPresent()); - } private ShardingRule createShardingRule() { return ShardingRule.builder().dataSourceRule(createDataSourceRule()) .tableRules(Collections.singletonList(createTableRule())).bindingTableRules(Collections.singletonList(createBindingTableRule())).build(); } - private ShardingRule createShardingRule(final Collection masterSlaveRules) { - return ShardingRule.builder().dataSourceRule(createDataSourceRule()) - .tableRules(Collections.singletonList(createTableRule())).bindingTableRules(Collections.singletonList(createBindingTableRule())) - .masterSlaveRules(masterSlaveRules).build(); - } - private DataSourceRule createDataSourceRule() { Map result = new HashMap<>(2); result.put("ds0", null); diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/RoundRobinSlaveLoadBalanceStrategyTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/RoundRobinSlaveLoadBalanceStrategyTest.java index 4586d1456f87b..d51503fcc1f4e 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/RoundRobinSlaveLoadBalanceStrategyTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/strategy/slave/RoundRobinSlaveLoadBalanceStrategyTest.java @@ -17,8 +17,10 @@ package com.dangdang.ddframe.rdb.sharding.api.strategy.slave; +import com.dangdang.ddframe.rdb.sharding.fixture.TestDataSource; import org.junit.Test; +import javax.sql.DataSource; import java.util.Arrays; import static org.hamcrest.core.Is.is; @@ -30,8 +32,10 @@ public final class RoundRobinSlaveLoadBalanceStrategyTest { @Test public void assertGetDataSource() { - assertThat(roundRobinSlaveLoadBalanceStrategy.getDataSource("ds", Arrays.asList("ds_0", "ds_1")), is("ds_0")); - assertThat(roundRobinSlaveLoadBalanceStrategy.getDataSource("ds", Arrays.asList("ds_0", "ds_1")), is("ds_1")); - assertThat(roundRobinSlaveLoadBalanceStrategy.getDataSource("ds", Arrays.asList("ds_0", "ds_1")), is("ds_0")); + DataSource slaveDataSource1 = new TestDataSource("test_ds_slave_1"); + DataSource slaveDataSource2 = new TestDataSource("test_ds_slave_2"); + assertThat(roundRobinSlaveLoadBalanceStrategy.getDataSource("ds", Arrays.asList(slaveDataSource1, slaveDataSource2)), is(slaveDataSource1)); + assertThat(roundRobinSlaveLoadBalanceStrategy.getDataSource("ds", Arrays.asList(slaveDataSource1, slaveDataSource2)), is(slaveDataSource2)); + assertThat(roundRobinSlaveLoadBalanceStrategy.getDataSource("ds", Arrays.asList(slaveDataSource1, slaveDataSource2)), is(slaveDataSource1)); } } diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/fixture/TestDataSource.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/fixture/TestDataSource.java similarity index 83% rename from sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/fixture/TestDataSource.java rename to sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/fixture/TestDataSource.java index e80dcd784e2d8..1de5c1af22d91 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/api/rule/fixture/TestDataSource.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/fixture/TestDataSource.java @@ -15,7 +15,7 @@ *

*/ -package com.dangdang.ddframe.rdb.sharding.api.rule.fixture; +package com.dangdang.ddframe.rdb.sharding.fixture; import com.dangdang.ddframe.rdb.sharding.jdbc.adapter.AbstractDataSourceAdapter; import lombok.EqualsAndHashCode; @@ -34,9 +34,4 @@ public final class TestDataSource extends AbstractDataSourceAdapter { public Connection getConnection() throws SQLException { return null; } - - @Override - public Connection getConnection(final String username, final String password) throws SQLException { - return getConnection(); - } } diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/AllJDBCTests.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/AllJDBCTests.java index 2ab1151fbdcab..0568e30fd6afe 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/AllJDBCTests.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/AllJDBCTests.java @@ -54,7 +54,8 @@ ResultSetGetterAdapterTest.class, ResultSetAdapterTest.class, JdbcMethodInvocationTest.class, - RowSetResultSetAdapterTest.class + RowSetResultSetAdapterTest.class, + MasterSlaveDataSourceTest.class }) public class AllJDBCTests { } diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSourceTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSourceTest.java new file mode 100644 index 0000000000000..7395ebeb9057a --- /dev/null +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSourceTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 1999-2015 dangdang.com. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *

+ */ + +package com.dangdang.ddframe.rdb.sharding.jdbc; + +import com.dangdang.ddframe.rdb.sharding.fixture.TestDataSource; +import com.dangdang.ddframe.rdb.sharding.parser.result.router.SQLStatementType; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import javax.sql.DataSource; +import java.lang.reflect.Field; +import java.util.Collections; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public final class MasterSlaveDataSourceTest { + + private DataSource masterDataSource = new TestDataSource("test_ds_master"); + + private DataSource slaveDataSource = new TestDataSource("test_ds_slave"); + + private MasterSlaveDataSource masterSlaveDataSource = new MasterSlaveDataSource("test_ds", masterDataSource, Collections.singletonList(slaveDataSource)); + + @Before + @After + public void reset() throws NoSuchFieldException, IllegalAccessException { + Field field = MasterSlaveDataSource.class.getDeclaredField("WAS_UPDATED"); + field.setAccessible(true); + ((ThreadLocal) field.get(MasterSlaveDataSource.class)).remove(); + } + + @Test + public void assertGetDataSourceForDML() { + assertThat(masterSlaveDataSource.getDataSource(SQLStatementType.INSERT), is(masterDataSource)); + } + + @Test + public void assertGetDataSourceForDQL() { + assertThat(masterSlaveDataSource.getDataSource(SQLStatementType.SELECT), is(slaveDataSource)); + } + + @Test + public void assertGetDataSourceForDMLAndDQL() { + assertThat(masterSlaveDataSource.getDataSource(SQLStatementType.INSERT), is(masterDataSource)); + assertThat(masterSlaveDataSource.getDataSource(SQLStatementType.SELECT), is(masterDataSource)); + } +} diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingDataSourceTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingDataSourceTest.java index ce04145505936..b614ea0b8768c 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingDataSourceTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/ShardingDataSourceTest.java @@ -47,14 +47,6 @@ public void assertGetConnection() throws SQLException { assertThat(createShardingDataSource(dataSource).getConnection().getConnection("ds", SQLStatementType.SELECT), is(connection)); } - @Test - public void assertGetConnectionWithUsername() throws SQLException { - Connection connection = mockConnection(); - DataSource dataSource = mock(DataSource.class); - when(dataSource.getConnection()).thenReturn(connection); - assertThat(createShardingDataSource(dataSource).getConnection("username", "password").getConnection("ds", SQLStatementType.SELECT), is(connection)); - } - private Connection mockConnection() throws SQLException { Connection result = mock(Connection.class); DatabaseMetaData databaseMetaData = mock(DatabaseMetaData.class); diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/adapter/DataSourceAdapterTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/adapter/DataSourceAdapterTest.java index 872da7b525715..8d4eca7138e1e 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/adapter/DataSourceAdapterTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/jdbc/adapter/DataSourceAdapterTest.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.logging.Logger; +import com.dangdang.ddframe.rdb.sharding.jdbc.ShardingConnection; import org.junit.Before; import org.junit.Test; @@ -93,4 +94,10 @@ public void assertSetLogWriter() throws SQLException { public void assertGetParentLogger() throws SQLException { assertThat(shardingDataSource.getParentLogger().getName(), is(Logger.GLOBAL_LOGGER_NAME)); } + + + @Test + public void assertGetConnectionWithUsername() throws SQLException { + assertThat(shardingDataSource.getConnection("username", "password"), instanceOf(ShardingConnection.class)); + } } diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/merger/fixture/MockResultSet.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/merger/fixture/MockResultSet.java index 9bc24356f530e..31b4dd7172c05 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/merger/fixture/MockResultSet.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/merger/fixture/MockResultSet.java @@ -264,7 +264,7 @@ public String getColumnClassName(final int column) throws SQLException { } @Override - public T unwrap(final Class iface) throws SQLException { + public I unwrap(final Class iface) throws SQLException { throw new SQLFeatureNotSupportedException(); } diff --git a/sharding-jdbc-doc/content/index/index.md b/sharding-jdbc-doc/content/index/index.md index 708ff6c0a3c8e..d26a2edde356a 100644 --- a/sharding-jdbc-doc/content/index/index.md +++ b/sharding-jdbc-doc/content/index/index.md @@ -5,11 +5,9 @@ * 曹昊    [当当](http://www.dangdang.com/) caohao@dangdang.com * 岳令    [当当](http://www.dangdang.com/) yueling@dangdang.com -**讨论QQ群:**532576663(不限于Sharding-JDBC,包括分布式,数据库相关以及其他互联网技术交流) +**讨论QQ群:**532576663(不限于Sharding-JDBC,包括分布式,数据库相关以及其他互联网技术交流。由于QQ群已接近饱和,我们希望您在申请加群之前仔细阅读文档,并在加群申请中正确回答问题,以及在申请时写上您的姓名和公司名称。并且在入群后及时修改群名片。否则我们将有权拒绝您的入群申请。谢谢合作。) # 简介 -`Sharding-JDBC`是当当应用框架`ddframe`中,关系型数据库模块`dd-rdb`中分离出来的数据库水平扩展框架,即透明化数据库分库分表访问。 - `Sharding-JDBC`直接封装`JDBC API`,可以理解为增强版的`JDBC`驱动,旧代码迁移成本几乎为零: * 可适用于任何基于`java`的`ORM`框架,如:`JPA`, `Hibernate`, `Mybatis`, `Spring JDBC Template`或直接使用`JDBC`。 @@ -22,6 +20,13 @@ * 分片策略灵活,可支持`=`,`BETWEEN`,`IN`等多维度分片,也可支持多分片键共用。 * `SQL`解析功能完善,支持聚合,分组,排序,`Limit`,`OR`等查询,并且支持`Binding Table`以及笛卡尔积的表查询。 +* 支持柔性事务(目前仅最大努力送达型)。 +* 支持读写分离。 + +`Sharding-JDBC`配置多样: + +* 可支持YAML和Spring命名空间配置 +* 灵活多样的`inline`方式 *** @@ -57,13 +62,16 @@ ## 规则配置 `Sharding-JDBC`的分库分表通过规则配置描述,请简单浏览配置全貌: + ```java - ShardingRule shardingRule = new ShardingRule( - dataSourceRule, - Arrays.asList(tableRule), - new DatabaseShardingStrategy("sharding_column_1", new XXXShardingAlgorithm()), - new TableShardingStrategy("sharding_column_2", new XXXShardingAlgorithm())); +ShardingRule shardingRule = ShardingRule.builder() + .dataSourceRule(dataSourceRule) + .tableRules(tableRuleList) + .databaseShardingStrategy(new DatabaseShardingStrategy("sharding_column", new XXXShardingAlgorithm())) + .tableShardingStrategy(new TableShardingStrategy("sharding_column", new XXXShardingAlgorithm()))) + .build(); ``` + 规则配置包括数据源配置、表规则配置、分库策略和分表策略组成。这只是最简单的配置方式,实际使用可更加灵活,如:多分片键,分片策略直接和`tableRule`绑定等。 >详细的规则配置请参考[用户指南](post/user_guide) @@ -71,6 +79,7 @@ ## 使用基于ShardingDataSource的JDBC接口 通过`ShardingDataSourceFactory`工厂和规则配置对象获取`ShardingDataSource`,`ShardingDataSource`实现自`JDBC`的标准接口`DataSource`。然后可通过`DataSource`选择使用原生`JDBC`开发,或者使用`JPA`, `MyBatis`等`ORM`工具。 以`JDBC`原生实现为例: + ```java DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule); String sql = "SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?"; @@ -83,9 +92,51 @@ try ( while(rs.next()) { System.out.println(rs.getInt(1)); System.out.println(rs.getInt(2)); - System.out.println(rs.getInt(3)); } } } ``` +## 使用Spring命名空间配置 + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` diff --git a/sharding-jdbc-doc/content/post/master_slave.md b/sharding-jdbc-doc/content/post/master_slave.md index 34ad806ef69be..ad7023e906604 100644 --- a/sharding-jdbc-doc/content/post/master_slave.md +++ b/sharding-jdbc-doc/content/post/master_slave.md @@ -24,18 +24,14 @@ weight = 6 ## 开发示例 ```java - // 构建读写分离规则 - Collection masterSlaveRules = new ArrayList<>(2); - // ds_0, ds_1是读写分离逻辑数据源, ds_0_master, ds_0_slave_1等数据源是真实数据源 - masterSlaveRules.add(new MasterSlaveRule("ds_0", "ds_0_master", Arrays.asList("ds_0_slave_1", "ds_0_slave_2")); - masterSlaveRules.add(new MasterSlaveRule("ds_1", "ds_1_master", Arrays.asList("ds_1_slave_1", "ds_1_slave_2")); - - ShardingRule shardingRule = ShardingRule.builder() - .dataSourceRule(dataSourceRule) - // 请注意, TableRule也需要通过builder传入Collection - .tableRules(Arrays.asList(orderTableRule, orderItemTableRule)) - .databaseShardingStrategy(new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm())) - .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm())) - .masterSlaveRules(masterSlaveRules) - .build(); +// 构建读写分离数据源 +MasterSlaveDataSource masterSlaveDs0 = new MasterSlaveDataSourceFactory.createDataSource("ms_0", masterDataSource0, slaveDataSource00, slaveDataSource01); +MasterSlaveDataSource masterSlaveDs1 = new MasterSlaveDataSourceFactory.createDataSource("ms_1", masterDataSource1, slaveDataSource11, slaveDataSource11); + +// 构建分库分表数据源 +Map dataSourceMap = new HashMap<>(2); +dataSourceMap.put("ms_0", masterSlaveDs0); +dataSourceMap.put("ms_1", masterSlaveDs1); + +// 通过ShardingDataSourceFactory继续创建ShardingDataSource ```