From 5980c97bdf0186f49c77ba80b8a0e9656b5994cf Mon Sep 17 00:00:00 2001 From: terrymanu Date: Tue, 31 May 2016 15:14:36 +0800 Subject: [PATCH] for #85 use hint set force route from master --- .../ddframe/rdb/sharding/api/HintManager.java | 11 +++++++++++ .../rdb/sharding/hint/HintManagerHolder.java | 9 +++++++++ .../rdb/sharding/jdbc/MasterSlaveDataSource.java | 5 +++-- .../rdb/sharding/hint/HintManagerHolderTest.java | 12 ++++++++++++ .../sharding/jdbc/MasterSlaveDataSourceTest.java | 9 +++++++++ sharding-jdbc-doc/content/post/master_slave.md | 13 ++++++++++--- 6 files changed, 54 insertions(+), 5 deletions(-) diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/HintManager.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/HintManager.java index 2c2ea76632a31..84f2c1343f6f0 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/HintManager.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/api/HintManager.java @@ -24,6 +24,7 @@ import com.google.common.collect.BoundType; import com.google.common.collect.Range; import lombok.AccessLevel; +import lombok.Getter; import lombok.NoArgsConstructor; import java.util.Arrays; @@ -43,6 +44,9 @@ public final class HintManager implements AutoCloseable { private final Map> tableShardingValues = new HashMap<>(); + @Getter + private boolean masterRouteOnly; + /** * 获取线索分片管理器实例. * @@ -139,6 +143,13 @@ public ShardingValue getTableShardingValue(final ShardingKey shardingKey) { return tableShardingValues.get(shardingKey); } + /** + * 设置数据库操作只路由至主库. + */ + public void setMasterRouteOnly() { + masterRouteOnly = true; + } + @Override public void close() { HintManagerHolder.clear(); diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/hint/HintManagerHolder.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/hint/HintManagerHolder.java index 65db1b4eeeceb..0d70b90bb0d2d 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/hint/HintManagerHolder.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/hint/HintManagerHolder.java @@ -72,6 +72,15 @@ public static Optional> getTableShardingValue(final ShardingKey return isUseHint() ? Optional.>fromNullable(HINT_MANAGER_HOLDER.get().getTableShardingValue(shardingKey)) : Optional.>absent(); } + /** + * 判断是否数据库操作只路由至主库. + * + * @return 是否数据库操作只路由至主库 + */ + public static boolean isMasterRouteOnly() { + return isUseHint() ? HINT_MANAGER_HOLDER.get().isMasterRouteOnly() : false; + } + /** * 清理线索分片管理器的本地线程持有者. */ diff --git a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSource.java b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSource.java index d949c0612cd0f..2f0dfa564be94 100644 --- a/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSource.java +++ b/sharding-jdbc-core/src/main/java/com/dangdang/ddframe/rdb/sharding/jdbc/MasterSlaveDataSource.java @@ -19,6 +19,7 @@ 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.hint.HintManagerHolder; import com.dangdang.ddframe.rdb.sharding.jdbc.adapter.AbstractDataSourceAdapter; import com.dangdang.ddframe.rdb.sharding.parser.result.router.SQLStatementType; import com.google.common.base.Preconditions; @@ -60,7 +61,7 @@ protected Boolean initialValue() { * @return 主或从节点的数据源 */ public DataSource getDataSource(final SQLStatementType sqlStatementType) { - if (SQLStatementType.SELECT != sqlStatementType || WAS_UPDATED.get()) { + if (SQLStatementType.SELECT != sqlStatementType || WAS_UPDATED.get() || HintManagerHolder.isMasterRouteOnly()) { WAS_UPDATED.set(true); return masterDataSource; } @@ -70,7 +71,7 @@ public DataSource getDataSource(final SQLStatementType sqlStatementType) { String getDatabaseProductName() throws SQLException { String result; try (Connection masterConnection = masterDataSource.getConnection()) { - result = masterConnection.getMetaData().getDatabaseProductName(); + result = masterConnection.getMetaData().getDatabaseProductName(); } for (DataSource each : slaveDataSources) { String slaveDatabaseProductName; diff --git a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/hint/HintManagerHolderTest.java b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/hint/HintManagerHolderTest.java index 1d0f70114e32b..60bac8550f068 100644 --- a/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/hint/HintManagerHolderTest.java +++ b/sharding-jdbc-core/src/test/java/com/dangdang/ddframe/rdb/sharding/hint/HintManagerHolderTest.java @@ -50,6 +50,18 @@ public void assertGetTableShardingValue() { assertTrue(HintManagerHolder.getTableShardingValue(new ShardingKey("logicTable", "shardingColumn")).isPresent()); } + @Test + public void assertIsMasterRouteOnlyWithoutSet() { + hintManager.close(); + assertFalse(HintManagerHolder.isMasterRouteOnly()); + } + + @Test + public void assertIsMasterRouteOnly() { + hintManager.setMasterRouteOnly(); + assertTrue(HintManagerHolder.isMasterRouteOnly()); + } + @Test public void assertClear() { hintManager.addDatabaseShardingValue("logicTable", "shardingColumn", 1); 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 index fca432ecab03a..9036fc29fe2ec 100644 --- 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 @@ -17,6 +17,7 @@ package com.dangdang.ddframe.rdb.sharding.jdbc; +import com.dangdang.ddframe.rdb.sharding.api.HintManager; import com.dangdang.ddframe.rdb.sharding.api.MasterSlaveDataSourceFactory; import com.dangdang.ddframe.rdb.sharding.fixture.TestDataSource; import com.dangdang.ddframe.rdb.sharding.parser.result.router.SQLStatementType; @@ -69,6 +70,14 @@ public void assertGetDataSourceForDMLAndDQL() { assertThat(masterSlaveDataSource.getDataSource(SQLStatementType.SELECT), is(masterDataSource)); } + @Test + public void assertGetDataSourceForHintToMasterOnly() { + HintManager hintManager = HintManager.getInstance(); + hintManager.setMasterRouteOnly(); + assertThat(masterSlaveDataSource.getDataSource(SQLStatementType.SELECT), is(masterDataSource)); + hintManager.close(); + } + @Test(expected = IllegalStateException.class) public void assertGetDatabaseProductNameWhenDataBaseProductNameDifferent() throws SQLException { DataSource masterDataSource = mock(DataSource.class); diff --git a/sharding-jdbc-doc/content/post/master_slave.md b/sharding-jdbc-doc/content/post/master_slave.md index d2cd6360bb0b1..8e5d5e8181414 100644 --- a/sharding-jdbc-doc/content/post/master_slave.md +++ b/sharding-jdbc-doc/content/post/master_slave.md @@ -11,10 +11,9 @@ weight = 6 ## 支持项 1. 提供了一主多从的读写分离配置,可配合分库分表使用。 1. 同一线程如果有写入操作,以后的读操作均从主库读取,用于保证同一线程中的数据一致性。 +1. Spring命名空间。 +1. 基于Hint的强制主库路由。 -## 待支持项 -1. Spring命名空间 -1. 基于Hint的强制主库读取配置 ## 不支持范围 1. 主库和从库的数据同步。 @@ -111,3 +110,11 @@ dataSourceMap.put("ms_1", masterSlaveDs1); ``` + +## 使用Hint强制路由主库示例 + +```java +HintManager hintManager = HintManager.getInstance(); +hintManager.setMasterRouteOnly(); +// 继续JDBC操作 +```