You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by du...@apache.org on 2022/11/14 12:10:02 UTC

[shardingsphere] branch master updated: Optimize shadow rule configuration (#22123)

This is an automated email from the ASF dual-hosted git repository.

duanzhengqiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 87a2712c02d Optimize shadow rule configuration (#22123)
87a2712c02d is described below

commit 87a2712c02da15bb437815e645b70cdf0b6a63de
Author: gin <ja...@163.com>
AuthorDate: Mon Nov 14 20:09:43 2022 +0800

    Optimize shadow rule configuration (#22123)
    
    * Optimize shadow rule configuration
    
    * Fix ut
    
    * Fix ut
    
    * Fix ci
    
    * Fix ci
    
    * Fix ci
    
    * Add properties ut
    
    * Fix properties ut
---
 .../shadow/api/config/ShadowRuleConfiguration.java |  4 +-
 .../datasource/ShadowDataSourceConfiguration.java  |  2 +
 .../AlgorithmProvidedShadowRuleConfiguration.java  |  8 ++--
 .../AbstractShadowRuleConfigurationChecker.java    |  9 +++++
 ...ithmProvidedShadowRuleConfigurationChecker.java |  2 +-
 .../checker/ShadowRuleConfigurationChecker.java    |  2 +-
 .../shardingsphere/shadow/rule/ShadowRule.java     |  4 +-
 ...wRuleAlgorithmProviderConfigurationSwapper.java | 20 +++++++---
 .../YamlShadowRuleConfigurationSwapper.java        | 26 ++++++++----
 .../YamlShadowDataSourceConfigurationSwapper.java  | 41 -------------------
 ...ProvidedShadowRuleConfigurationCheckerTest.java |  2 +-
 .../ShadowRuleConfigurationCheckerTest.java        |  6 +--
 .../HintShadowAlgorithmDeterminerTest.java         | 12 +++---
 .../ShadowDeleteStatementRoutingEngineTest.java    |  2 +-
 .../ShadowInsertStatementRoutingEngineTest.java    |  2 +-
 .../ShadowSelectStatementRoutingEngineTest.java    |  2 +-
 .../ShadowNonDMLStatementRoutingEngineTest.java    |  2 +-
 .../shardingsphere/shadow/rule/ShadowRuleTest.java |  8 ++--
 ...eAlgorithmProviderConfigurationSwapperTest.java | 29 ++++++++++----
 ...mlShadowDataSourceConfigurationSwapperTest.java | 46 ----------------------
 .../converter/ShadowRuleStatementConverter.java    |  7 +++-
 .../handler/query/ShadowRuleQueryResultSet.java    | 17 ++++----
 .../supporter/ShadowRuleStatementSupporter.java    |  9 ++++-
 .../update/AlterShadowRuleStatementUpdater.java    |  5 +--
 .../update/CreateShadowRuleStatementUpdater.java   |  2 +-
 .../update/DropShadowRuleStatementUpdater.java     | 13 ++++--
 .../ShadowRuleStatementConverterTest.java          |  6 ++-
 .../query/ShadowRuleQueryResultSetTest.java        |  2 +-
 .../AlterShadowRuleStatementUpdaterTest.java       | 12 +++---
 .../CreateShadowRuleStatementUpdaterTest.java      |  5 ++-
 .../update/DropShadowRuleStatementUpdaterTest.java |  3 +-
 .../PropertiesShadowSpringBootStarterTest.java     | 20 +++++++---
 .../YamlShadowDefaultSpringBootStarterTest.java    |  8 ++--
 .../boot/YmlShadowSpringBootStarterTest.java       | 15 ++++---
 .../parser/ShadowRuleBeanDefinitionParser.java     |  7 ++--
 .../ShadowAlgorithmSpringNamespaceTest.java        | 15 ++++---
 .../ShadowDefaultAlgorithmSpringNamespaceTest.java |  8 ++--
 .../queryable/ConvertYamlConfigurationHandler.java | 10 ++---
 .../rule/RulesUsedStorageUnitQueryResultSet.java   |  6 +--
 .../RulesUsedStorageUnitQueryResultSetTest.java    |  2 +-
 40 files changed, 203 insertions(+), 198 deletions(-)

diff --git a/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/api/config/ShadowRuleConfiguration.java b/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/api/config/ShadowRuleConfiguration.java
index 850b65493a9..da2b6c1b816 100644
--- a/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/api/config/ShadowRuleConfiguration.java
+++ b/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/api/config/ShadowRuleConfiguration.java
@@ -25,7 +25,9 @@ import org.apache.shardingsphere.infra.config.rule.scope.DatabaseRuleConfigurati
 import org.apache.shardingsphere.shadow.api.config.datasource.ShadowDataSourceConfiguration;
 import org.apache.shardingsphere.shadow.api.config.table.ShadowTableConfiguration;
 
+import java.util.Collection;
 import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.Map;
 
 /**
@@ -35,7 +37,7 @@ import java.util.Map;
 @Setter
 public final class ShadowRuleConfiguration implements DatabaseRuleConfiguration, DistributedRuleConfiguration {
     
-    private Map<String, ShadowDataSourceConfiguration> dataSources = new LinkedHashMap<>();
+    private Collection<ShadowDataSourceConfiguration> dataSources = new LinkedList<>();
     
     private Map<String, ShadowTableConfiguration> tables = new LinkedHashMap<>();
     
diff --git a/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/api/config/datasource/ShadowDataSourceConfiguration.java b/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/api/config/datasource/ShadowDataSourceConfiguration.java
index cb4db3043c1..089b37dbbcc 100644
--- a/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/api/config/datasource/ShadowDataSourceConfiguration.java
+++ b/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/api/config/datasource/ShadowDataSourceConfiguration.java
@@ -29,6 +29,8 @@ import lombok.Setter;
 @RequiredArgsConstructor
 public final class ShadowDataSourceConfiguration {
     
+    private final String name;
+    
     private final String productionDataSourceName;
     
     private final String shadowDataSourceName;
diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/algorithm/config/AlgorithmProvidedShadowRuleConfiguration.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/algorithm/config/AlgorithmProvidedShadowRuleConfiguration.java
index 04219909f38..bc49a9fc109 100644
--- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/algorithm/config/AlgorithmProvidedShadowRuleConfiguration.java
+++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/algorithm/config/AlgorithmProvidedShadowRuleConfiguration.java
@@ -25,7 +25,9 @@ import org.apache.shardingsphere.shadow.api.config.datasource.ShadowDataSourceCo
 import org.apache.shardingsphere.shadow.api.config.table.ShadowTableConfiguration;
 import org.apache.shardingsphere.shadow.spi.ShadowAlgorithm;
 
+import java.util.Collection;
 import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.Map;
 
 /**
@@ -35,11 +37,11 @@ import java.util.Map;
 @Setter
 public final class AlgorithmProvidedShadowRuleConfiguration implements DatabaseRuleConfiguration, DistributedRuleConfiguration {
     
-    private String defaultShadowAlgorithmName;
-    
-    private Map<String, ShadowDataSourceConfiguration> dataSources = new LinkedHashMap<>();
+    private Collection<ShadowDataSourceConfiguration> dataSources = new LinkedList<>();
     
     private Map<String, ShadowTableConfiguration> tables = new LinkedHashMap<>();
     
     private Map<String, ShadowAlgorithm> shadowAlgorithms = new LinkedHashMap<>();
+    
+    private String defaultShadowAlgorithmName;
 }
diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/AbstractShadowRuleConfigurationChecker.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/AbstractShadowRuleConfigurationChecker.java
index 8dca86ec7db..276afb2da3c 100644
--- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/AbstractShadowRuleConfigurationChecker.java
+++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/AbstractShadowRuleConfigurationChecker.java
@@ -29,6 +29,7 @@ import org.apache.shardingsphere.shadow.spi.ShadowAlgorithm;
 
 import javax.sql.DataSource;
 import java.util.Collection;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -100,4 +101,12 @@ public abstract class AbstractShadowRuleConfigurationChecker<T extends RuleConfi
     protected void shadowTableAlgorithmsReferencesCheck(final Map<String, ShadowTableConfiguration> shadowTables) {
         shadowTables.forEach((key, value) -> Preconditions.checkState(!value.getShadowAlgorithmNames().isEmpty(), "No available shadow Algorithm configuration in shadow table `%s`.", key));
     }
+    
+    protected Map<String, ShadowDataSourceConfiguration> initShadowDataSources(final Collection<ShadowDataSourceConfiguration> dataSourceConfigurations) {
+        Map<String, ShadowDataSourceConfiguration> result = new LinkedHashMap<>();
+        for (ShadowDataSourceConfiguration each : dataSourceConfigurations) {
+            result.put(each.getName(), each);
+        }
+        return result;
+    }
 }
diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/AlgorithmProvidedShadowRuleConfigurationChecker.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/AlgorithmProvidedShadowRuleConfigurationChecker.java
index 50f297db98c..bc53e71f1a2 100644
--- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/AlgorithmProvidedShadowRuleConfigurationChecker.java
+++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/AlgorithmProvidedShadowRuleConfigurationChecker.java
@@ -33,7 +33,7 @@ public final class AlgorithmProvidedShadowRuleConfigurationChecker extends Abstr
     
     @Override
     protected void checkShadowRuleConfiguration(final AlgorithmProvidedShadowRuleConfiguration config, final Map<String, DataSource> dataSourceMap) {
-        Map<String, ShadowDataSourceConfiguration> dataSources = config.getDataSources();
+        Map<String, ShadowDataSourceConfiguration> dataSources = initShadowDataSources(config.getDataSources());
         checkDataSources(dataSources, dataSourceMap);
         Map<String, ShadowTableConfiguration> shadowTables = config.getTables();
         shadowTableDataSourcesAutoReferences(shadowTables, dataSources);
diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/ShadowRuleConfigurationChecker.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/ShadowRuleConfigurationChecker.java
index 25a5cb6d8ab..2e99122fcbf 100644
--- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/ShadowRuleConfigurationChecker.java
+++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/checker/ShadowRuleConfigurationChecker.java
@@ -33,7 +33,7 @@ public final class ShadowRuleConfigurationChecker extends AbstractShadowRuleConf
     
     @Override
     protected void checkShadowRuleConfiguration(final ShadowRuleConfiguration config, final Map<String, DataSource> dataSourceMap) {
-        Map<String, ShadowDataSourceConfiguration> dataSources = config.getDataSources();
+        Map<String, ShadowDataSourceConfiguration> dataSources = initShadowDataSources(config.getDataSources());
         checkDataSources(dataSources, dataSourceMap);
         Map<String, ShadowTableConfiguration> shadowTables = config.getTables();
         shadowTableDataSourcesAutoReferences(shadowTables, dataSources);
diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java
index bd03f572202..7960a3c92ec 100644
--- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java
+++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java
@@ -80,8 +80,8 @@ public final class ShadowRule implements DatabaseRule, DataSourceContainedRule {
         initShadowTableRules(ruleConfig.getTables());
     }
     
-    private void initShadowDataSourceMappings(final Map<String, ShadowDataSourceConfiguration> dataSources) {
-        dataSources.forEach((key, value) -> shadowDataSourceMappings.put(key, new ShadowDataSourceRule(value.getProductionDataSourceName(), value.getShadowDataSourceName())));
+    private void initShadowDataSourceMappings(final Collection<ShadowDataSourceConfiguration> dataSources) {
+        dataSources.forEach(each -> shadowDataSourceMappings.put(each.getName(), new ShadowDataSourceRule(each.getProductionDataSourceName(), each.getShadowDataSourceName())));
     }
     
     private void initShadowAlgorithmConfigurations(final Map<String, AlgorithmConfiguration> shadowAlgorithmConfigs) {
diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleAlgorithmProviderConfigurationSwapper.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleAlgorithmProviderConfigurationSwapper.java
index a7ba21ee20d..06888bada9e 100644
--- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleAlgorithmProviderConfigurationSwapper.java
+++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleAlgorithmProviderConfigurationSwapper.java
@@ -20,9 +20,10 @@ package org.apache.shardingsphere.shadow.yaml.swapper;
 import org.apache.shardingsphere.infra.yaml.config.pojo.algorithm.YamlAlgorithmConfiguration;
 import org.apache.shardingsphere.infra.yaml.config.swapper.rule.YamlRuleConfigurationSwapper;
 import org.apache.shardingsphere.shadow.algorithm.config.AlgorithmProvidedShadowRuleConfiguration;
+import org.apache.shardingsphere.shadow.api.config.datasource.ShadowDataSourceConfiguration;
 import org.apache.shardingsphere.shadow.constant.ShadowOrder;
 import org.apache.shardingsphere.shadow.yaml.config.YamlShadowRuleConfiguration;
-import org.apache.shardingsphere.shadow.yaml.swapper.datasource.YamlShadowDataSourceConfigurationSwapper;
+import org.apache.shardingsphere.shadow.yaml.config.datasource.YamlShadowDataSourceConfiguration;
 import org.apache.shardingsphere.shadow.yaml.swapper.table.YamlShadowTableConfigurationSwapper;
 
 /**
@@ -30,8 +31,6 @@ import org.apache.shardingsphere.shadow.yaml.swapper.table.YamlShadowTableConfig
  */
 public final class YamlShadowRuleAlgorithmProviderConfigurationSwapper implements YamlRuleConfigurationSwapper<YamlShadowRuleConfiguration, AlgorithmProvidedShadowRuleConfiguration> {
     
-    private final YamlShadowDataSourceConfigurationSwapper dataSourceConfigSwapper = new YamlShadowDataSourceConfigurationSwapper();
-    
     private final YamlShadowTableConfigurationSwapper tableSwapper = new YamlShadowTableConfigurationSwapper();
     
     @Override
@@ -53,7 +52,14 @@ public final class YamlShadowRuleAlgorithmProviderConfigurationSwapper implement
     }
     
     private void parseDataSources(final AlgorithmProvidedShadowRuleConfiguration data, final YamlShadowRuleConfiguration yamlConfig) {
-        data.getDataSources().forEach((key, value) -> yamlConfig.getDataSources().put(key, dataSourceConfigSwapper.swapToYamlConfiguration(value)));
+        data.getDataSources().forEach(each -> yamlConfig.getDataSources().put(each.getName(), swapToDataSourceYamlConfiguration(each)));
+    }
+    
+    private YamlShadowDataSourceConfiguration swapToDataSourceYamlConfiguration(final ShadowDataSourceConfiguration data) {
+        YamlShadowDataSourceConfiguration result = new YamlShadowDataSourceConfiguration();
+        result.setProductionDataSourceName(data.getProductionDataSourceName());
+        result.setShadowDataSourceName(data.getShadowDataSourceName());
+        return result;
     }
     
     @Override
@@ -70,7 +76,11 @@ public final class YamlShadowRuleAlgorithmProviderConfigurationSwapper implement
     }
     
     private void parseYamlDataSources(final YamlShadowRuleConfiguration yamlConfig, final AlgorithmProvidedShadowRuleConfiguration data) {
-        yamlConfig.getDataSources().forEach((key, value) -> data.getDataSources().put(key, dataSourceConfigSwapper.swapToObject(value)));
+        yamlConfig.getDataSources().forEach((key, value) -> data.getDataSources().add(swapToDataSourceObject(key, value)));
+    }
+    
+    private ShadowDataSourceConfiguration swapToDataSourceObject(final String name, final YamlShadowDataSourceConfiguration yamlConfig) {
+        return new ShadowDataSourceConfiguration(name, yamlConfig.getProductionDataSourceName(), yamlConfig.getShadowDataSourceName());
     }
     
     @Override
diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleConfigurationSwapper.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleConfigurationSwapper.java
index 19a0bf03543..4b98621ae03 100644
--- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleConfigurationSwapper.java
+++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleConfigurationSwapper.java
@@ -20,9 +20,10 @@ package org.apache.shardingsphere.shadow.yaml.swapper;
 import org.apache.shardingsphere.infra.yaml.config.swapper.rule.YamlRuleConfigurationSwapper;
 import org.apache.shardingsphere.infra.yaml.config.swapper.algorithm.YamlAlgorithmConfigurationSwapper;
 import org.apache.shardingsphere.shadow.api.config.ShadowRuleConfiguration;
+import org.apache.shardingsphere.shadow.api.config.datasource.ShadowDataSourceConfiguration;
 import org.apache.shardingsphere.shadow.constant.ShadowOrder;
 import org.apache.shardingsphere.shadow.yaml.config.YamlShadowRuleConfiguration;
-import org.apache.shardingsphere.shadow.yaml.swapper.datasource.YamlShadowDataSourceConfigurationSwapper;
+import org.apache.shardingsphere.shadow.yaml.config.datasource.YamlShadowDataSourceConfiguration;
 import org.apache.shardingsphere.shadow.yaml.swapper.table.YamlShadowTableConfigurationSwapper;
 
 /**
@@ -30,8 +31,6 @@ import org.apache.shardingsphere.shadow.yaml.swapper.table.YamlShadowTableConfig
  */
 public final class YamlShadowRuleConfigurationSwapper implements YamlRuleConfigurationSwapper<YamlShadowRuleConfiguration, ShadowRuleConfiguration> {
     
-    private final YamlShadowDataSourceConfigurationSwapper dataSourceConfigSwapper = new YamlShadowDataSourceConfigurationSwapper();
-    
     private final YamlShadowTableConfigurationSwapper tableConfigurationSwapper = new YamlShadowTableConfigurationSwapper();
     
     private final YamlAlgorithmConfigurationSwapper algorithmSwapper = new YamlAlgorithmConfigurationSwapper();
@@ -46,16 +45,23 @@ public final class YamlShadowRuleConfigurationSwapper implements YamlRuleConfigu
         return result;
     }
     
-    private void parseShadowAlgorithms(final ShadowRuleConfiguration data, final YamlShadowRuleConfiguration yamlConfig) {
-        data.getShadowAlgorithms().forEach((key, value) -> yamlConfig.getShadowAlgorithms().put(key, algorithmSwapper.swapToYamlConfiguration(value)));
+    private void parseDataSources(final ShadowRuleConfiguration data, final YamlShadowRuleConfiguration yamlConfig) {
+        data.getDataSources().forEach(each -> yamlConfig.getDataSources().put(each.getName(), swapToDataSourceYamlConfiguration(each)));
+    }
+    
+    private YamlShadowDataSourceConfiguration swapToDataSourceYamlConfiguration(final ShadowDataSourceConfiguration data) {
+        YamlShadowDataSourceConfiguration result = new YamlShadowDataSourceConfiguration();
+        result.setProductionDataSourceName(data.getProductionDataSourceName());
+        result.setShadowDataSourceName(data.getShadowDataSourceName());
+        return result;
     }
     
     private void parseShadowTables(final ShadowRuleConfiguration data, final YamlShadowRuleConfiguration yamlConfig) {
         data.getTables().forEach((key, value) -> yamlConfig.getTables().put(key, tableConfigurationSwapper.swapToYamlConfiguration(value)));
     }
     
-    private void parseDataSources(final ShadowRuleConfiguration data, final YamlShadowRuleConfiguration yamlConfig) {
-        data.getDataSources().forEach((key, value) -> yamlConfig.getDataSources().put(key, dataSourceConfigSwapper.swapToYamlConfiguration(value)));
+    private void parseShadowAlgorithms(final ShadowRuleConfiguration data, final YamlShadowRuleConfiguration yamlConfig) {
+        data.getShadowAlgorithms().forEach((key, value) -> yamlConfig.getShadowAlgorithms().put(key, algorithmSwapper.swapToYamlConfiguration(value)));
     }
     
     @Override
@@ -77,7 +83,11 @@ public final class YamlShadowRuleConfigurationSwapper implements YamlRuleConfigu
     }
     
     private void parseYamlDataSources(final YamlShadowRuleConfiguration yamlConfig, final ShadowRuleConfiguration data) {
-        yamlConfig.getDataSources().forEach((key, value) -> data.getDataSources().put(key, dataSourceConfigSwapper.swapToObject(value)));
+        yamlConfig.getDataSources().forEach((key, value) -> data.getDataSources().add(swapToDataSourceObject(key, value)));
+    }
+    
+    private ShadowDataSourceConfiguration swapToDataSourceObject(final String name, final YamlShadowDataSourceConfiguration yamlConfig) {
+        return new ShadowDataSourceConfiguration(name, yamlConfig.getProductionDataSourceName(), yamlConfig.getShadowDataSourceName());
     }
     
     @Override
diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/datasource/YamlShadowDataSourceConfigurationSwapper.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/datasource/YamlShadowDataSourceConfigurationSwapper.java
deleted file mode 100644
index 9daac8527d9..00000000000
--- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/yaml/swapper/datasource/YamlShadowDataSourceConfigurationSwapper.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.shardingsphere.shadow.yaml.swapper.datasource;
-
-import org.apache.shardingsphere.infra.util.yaml.swapper.YamlConfigurationSwapper;
-import org.apache.shardingsphere.shadow.api.config.datasource.ShadowDataSourceConfiguration;
-import org.apache.shardingsphere.shadow.yaml.config.datasource.YamlShadowDataSourceConfiguration;
-
-/**
- * YAML shadow data source configuration swapper.
- */
-public final class YamlShadowDataSourceConfigurationSwapper implements YamlConfigurationSwapper<YamlShadowDataSourceConfiguration, ShadowDataSourceConfiguration> {
-    
-    @Override
-    public YamlShadowDataSourceConfiguration swapToYamlConfiguration(final ShadowDataSourceConfiguration data) {
-        YamlShadowDataSourceConfiguration result = new YamlShadowDataSourceConfiguration();
-        result.setProductionDataSourceName(data.getProductionDataSourceName());
-        result.setShadowDataSourceName(data.getShadowDataSourceName());
-        return result;
-    }
-    
-    @Override
-    public ShadowDataSourceConfiguration swapToObject(final YamlShadowDataSourceConfiguration yamlConfig) {
-        return new ShadowDataSourceConfiguration(yamlConfig.getProductionDataSourceName(), yamlConfig.getShadowDataSourceName());
-    }
-}
diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/checker/AlgorithmProvidedShadowRuleConfigurationCheckerTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/checker/AlgorithmProvidedShadowRuleConfigurationCheckerTest.java
index 27aa9286cc7..b28e185d01e 100644
--- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/checker/AlgorithmProvidedShadowRuleConfigurationCheckerTest.java
+++ b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/checker/AlgorithmProvidedShadowRuleConfigurationCheckerTest.java
@@ -51,7 +51,7 @@ public final class AlgorithmProvidedShadowRuleConfigurationCheckerTest {
         AlgorithmProvidedShadowRuleConfiguration result = new AlgorithmProvidedShadowRuleConfiguration();
         result.setShadowAlgorithms(Collections.singletonMap(
                 "user-id-insert-match-algorithm", ShadowAlgorithmFactory.newInstance(new AlgorithmConfiguration("REGEX_MATCH", createProperties()))));
-        result.setDataSources(Collections.singletonMap("shadow-data-source", new ShadowDataSourceConfiguration("ds", "ds_shadow")));
+        result.setDataSources(Collections.singletonList(new ShadowDataSourceConfiguration("shadow-data-source", "ds", "ds_shadow")));
         result.setTables(Collections.singletonMap("t_order", new ShadowTableConfiguration(new LinkedList<>(), new LinkedList<>(Collections.singleton("user-id-insert-match-algorithm")))));
         return result;
     }
diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/checker/ShadowRuleConfigurationCheckerTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/checker/ShadowRuleConfigurationCheckerTest.java
index 5aa9279f1ed..99d037b67de 100644
--- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/checker/ShadowRuleConfigurationCheckerTest.java
+++ b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/checker/ShadowRuleConfigurationCheckerTest.java
@@ -82,9 +82,9 @@ public final class ShadowRuleConfigurationCheckerTest {
         return result;
     }
     
-    private Map<String, ShadowDataSourceConfiguration> createDataSources() {
-        Map<String, ShadowDataSourceConfiguration> result = new LinkedHashMap<>();
-        result.put("shadow-data-source", new ShadowDataSourceConfiguration("ds", "ds_shadow"));
+    private Collection<ShadowDataSourceConfiguration> createDataSources() {
+        Collection<ShadowDataSourceConfiguration> result = new LinkedList<>();
+        result.add(new ShadowDataSourceConfiguration("shadow-data-source", "ds", "ds_shadow"));
         return result;
     }
 }
diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/determiner/HintShadowAlgorithmDeterminerTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/determiner/HintShadowAlgorithmDeterminerTest.java
index 9929a45e32d..5285563fdd1 100644
--- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/determiner/HintShadowAlgorithmDeterminerTest.java
+++ b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/determiner/HintShadowAlgorithmDeterminerTest.java
@@ -28,9 +28,9 @@ import org.apache.shardingsphere.shadow.factory.ShadowAlgorithmFactory;
 import org.apache.shardingsphere.shadow.rule.ShadowRule;
 import org.junit.Test;
 
+import java.util.Collection;
 import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.LinkedList;
 import java.util.Properties;
 
 import static org.junit.Assert.assertTrue;
@@ -61,10 +61,10 @@ public final class HintShadowAlgorithmDeterminerTest {
         return result;
     }
     
-    private Map<String, ShadowDataSourceConfiguration> createDataSources() {
-        Map<String, ShadowDataSourceConfiguration> result = new LinkedHashMap<>(2, 1);
-        result.put("shadow-data-source-0", new ShadowDataSourceConfiguration("ds", "ds_shadow"));
-        result.put("shadow-data-source-1", new ShadowDataSourceConfiguration("ds1", "ds1_shadow"));
+    private Collection<ShadowDataSourceConfiguration> createDataSources() {
+        Collection<ShadowDataSourceConfiguration> result = new LinkedList<>();
+        result.add(new ShadowDataSourceConfiguration("shadow-data-source-0", "ds", "ds_shadow"));
+        result.add(new ShadowDataSourceConfiguration("shadow-data-source-1", "ds1", "ds1_shadow"));
         return result;
     }
     
diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowDeleteStatementRoutingEngineTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowDeleteStatementRoutingEngineTest.java
index 620b0fbd612..773a696f18a 100644
--- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowDeleteStatementRoutingEngineTest.java
+++ b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowDeleteStatementRoutingEngineTest.java
@@ -94,7 +94,7 @@ public final class ShadowDeleteStatementRoutingEngineTest {
     
     private AlgorithmProvidedShadowRuleConfiguration createAlgorithmProvidedShadowRuleConfiguration() {
         AlgorithmProvidedShadowRuleConfiguration result = new AlgorithmProvidedShadowRuleConfiguration();
-        result.setDataSources(Collections.singletonMap("shadow-data-source-0", new ShadowDataSourceConfiguration("ds", "ds_shadow")));
+        result.setDataSources(Collections.singletonList(new ShadowDataSourceConfiguration("shadow-data-source-0", "ds", "ds_shadow")));
         result.setTables(
                 Collections.singletonMap("t_order", new ShadowTableConfiguration(Collections.singletonList("shadow-data-source-0"), Collections.singleton("user-id-delete-regex-algorithm"))));
         result.setShadowAlgorithms(Collections.singletonMap("user-id-delete-regex-algorithm", createShadowAlgorithm()));
diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowInsertStatementRoutingEngineTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowInsertStatementRoutingEngineTest.java
index abe4aaab7b1..be7ba49dbaf 100644
--- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowInsertStatementRoutingEngineTest.java
+++ b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowInsertStatementRoutingEngineTest.java
@@ -91,7 +91,7 @@ public final class ShadowInsertStatementRoutingEngineTest {
     
     private AlgorithmProvidedShadowRuleConfiguration createAlgorithmProvidedShadowRuleConfiguration() {
         AlgorithmProvidedShadowRuleConfiguration result = new AlgorithmProvidedShadowRuleConfiguration();
-        result.setDataSources(Collections.singletonMap("shadow-data-source-0", new ShadowDataSourceConfiguration("ds", "ds_shadow")));
+        result.setDataSources(Collections.singletonList(new ShadowDataSourceConfiguration("shadow-data-source-0", "ds", "ds_shadow")));
         result.setTables(Collections.singletonMap("t_order", new ShadowTableConfiguration(Collections.singleton("shadow-data-source-0"), Collections.singleton("user-id-insert-regex-algorithm"))));
         result.setShadowAlgorithms(Collections.singletonMap("user-id-insert-regex-algorithm", createShadowAlgorithm()));
         return result;
diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRoutingEngineTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRoutingEngineTest.java
index b97487c1b9b..24b7b9929f9 100644
--- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRoutingEngineTest.java
+++ b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRoutingEngineTest.java
@@ -90,7 +90,7 @@ public final class ShadowSelectStatementRoutingEngineTest {
     
     private AlgorithmProvidedShadowRuleConfiguration createAlgorithmProvidedShadowRuleConfiguration() {
         AlgorithmProvidedShadowRuleConfiguration result = new AlgorithmProvidedShadowRuleConfiguration();
-        result.setDataSources(Collections.singletonMap("shadow-data-source-0", new ShadowDataSourceConfiguration("ds", "ds_shadow")));
+        result.setDataSources(Collections.singletonList(new ShadowDataSourceConfiguration("shadow-data-source-0", "ds", "ds_shadow")));
         result.setTables(Collections.singletonMap("t_order", new ShadowTableConfiguration(Collections.singleton("shadow-data-source-0"), Collections.singleton("user-id-select-regex-algorithm"))));
         result.setShadowAlgorithms(Collections.singletonMap("user-id-select-regex-algorithm", createShadowAlgorithm()));
         return result;
diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/impl/ShadowNonDMLStatementRoutingEngineTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/impl/ShadowNonDMLStatementRoutingEngineTest.java
index a8f5804ae5f..edfd231f575 100644
--- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/impl/ShadowNonDMLStatementRoutingEngineTest.java
+++ b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/route/engine/impl/ShadowNonDMLStatementRoutingEngineTest.java
@@ -84,7 +84,7 @@ public final class ShadowNonDMLStatementRoutingEngineTest {
     
     private AlgorithmProvidedShadowRuleConfiguration createAlgorithmProvidedShadowRuleConfiguration() {
         AlgorithmProvidedShadowRuleConfiguration result = new AlgorithmProvidedShadowRuleConfiguration();
-        result.setDataSources(Collections.singletonMap("shadow-data-source", new ShadowDataSourceConfiguration("ds", "ds_shadow")));
+        result.setDataSources(Collections.singletonList(new ShadowDataSourceConfiguration("shadow-data-source", "ds", "ds_shadow")));
         result.setTables(Collections.singletonMap("t_order", new ShadowTableConfiguration(Collections.singletonList("shadow-data-source"), Collections.singleton("simple-hint-algorithm"))));
         result.setShadowAlgorithms(createShadowAlgorithms());
         return result;
diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/rule/ShadowRuleTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/rule/ShadowRuleTest.java
index 6ff2dc47a0d..6f65ec0b99a 100644
--- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/rule/ShadowRuleTest.java
+++ b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/rule/ShadowRuleTest.java
@@ -97,10 +97,10 @@ public final class ShadowRuleTest {
         return result;
     }
     
-    private Map<String, ShadowDataSourceConfiguration> createDataSources() {
-        Map<String, ShadowDataSourceConfiguration> result = new LinkedHashMap<>(2, 1);
-        result.put("shadow-data-source-0", new ShadowDataSourceConfiguration("ds", "ds_shadow"));
-        result.put("shadow-data-source-1", new ShadowDataSourceConfiguration("ds1", "ds1_shadow"));
+    private Collection<ShadowDataSourceConfiguration> createDataSources() {
+        Collection<ShadowDataSourceConfiguration> result = new LinkedList<>();
+        result.add(new ShadowDataSourceConfiguration("shadow-data-source-0", "ds", "ds_shadow"));
+        result.add(new ShadowDataSourceConfiguration("shadow-data-source-1", "ds1", "ds1_shadow"));
         return result;
     }
     
diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleAlgorithmProviderConfigurationSwapperTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleAlgorithmProviderConfigurationSwapperTest.java
index 1a41459b3a5..48e8145c966 100644
--- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleAlgorithmProviderConfigurationSwapperTest.java
+++ b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/yaml/swapper/YamlShadowRuleAlgorithmProviderConfigurationSwapperTest.java
@@ -30,10 +30,13 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.Optional;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
 
 public final class YamlShadowRuleAlgorithmProviderConfigurationSwapperTest {
     
@@ -49,9 +52,10 @@ public final class YamlShadowRuleAlgorithmProviderConfigurationSwapperTest {
         AlgorithmProvidedShadowRuleConfiguration expected = buildAlgorithmProvidedShadowRuleConfiguration();
         YamlShadowRuleConfiguration actual = swapper.swapToYamlConfiguration(expected);
         actual.getDataSources().forEach((key, value) -> {
-            ShadowDataSourceConfiguration dataSourceConfig = expected.getDataSources().get(key);
-            assertThat(value.getShadowDataSourceName(), is(dataSourceConfig.getShadowDataSourceName()));
-            assertThat(value.getProductionDataSourceName(), is(dataSourceConfig.getProductionDataSourceName()));
+            Optional<ShadowDataSourceConfiguration> dataSourceConfig = getDataSourceConfig(expected.getDataSources(), key);
+            assertTrue(dataSourceConfig.isPresent());
+            assertThat(value.getShadowDataSourceName(), is(dataSourceConfig.get().getShadowDataSourceName()));
+            assertThat(value.getProductionDataSourceName(), is(dataSourceConfig.get().getProductionDataSourceName()));
         });
         actual.getTables().forEach((key, value) -> {
             ShadowTableConfiguration shadowTableConfig = expected.getTables().get(key);
@@ -63,9 +67,18 @@ public final class YamlShadowRuleAlgorithmProviderConfigurationSwapperTest {
         });
     }
     
+    private Optional<ShadowDataSourceConfiguration> getDataSourceConfig(final Collection<ShadowDataSourceConfiguration> dataSources, final String name) {
+        for (ShadowDataSourceConfiguration each : dataSources) {
+            if (name.equals(each.getName())) {
+                return Optional.of(each);
+            }
+        }
+        return Optional.empty();
+    }
+    
     private AlgorithmProvidedShadowRuleConfiguration buildAlgorithmProvidedShadowRuleConfiguration() {
         AlgorithmProvidedShadowRuleConfiguration result = new AlgorithmProvidedShadowRuleConfiguration();
-        result.getDataSources().put("shadow-data-source", new ShadowDataSourceConfiguration("ds", "ds-shadow"));
+        result.getDataSources().add(new ShadowDataSourceConfiguration("shadow-data-source", "ds", "ds-shadow"));
         result.getTables().put("t_order", new ShadowTableConfiguration(Collections.singletonList("shadow-data-source"), Arrays.asList("user-id-match-algorithm", "note-algorithm")));
         result.getShadowAlgorithms().put("user-id-match-algorithm", new ColumnRegexMatchedShadowAlgorithm());
         return result;
@@ -75,10 +88,10 @@ public final class YamlShadowRuleAlgorithmProviderConfigurationSwapperTest {
     public void assertSwapToObject() {
         YamlShadowRuleConfiguration expected = buildYamlShadowRuleConfiguration();
         AlgorithmProvidedShadowRuleConfiguration actual = swapper.swapToObject(expected);
-        actual.getDataSources().forEach((key, value) -> {
-            YamlShadowDataSourceConfiguration yamlShadowDataSourceConfig = expected.getDataSources().get(key);
-            assertThat(value.getShadowDataSourceName(), is(yamlShadowDataSourceConfig.getShadowDataSourceName()));
-            assertThat(value.getProductionDataSourceName(), is(yamlShadowDataSourceConfig.getProductionDataSourceName()));
+        actual.getDataSources().forEach(each -> {
+            YamlShadowDataSourceConfiguration yamlShadowDataSourceConfig = expected.getDataSources().get(each.getName());
+            assertThat(each.getShadowDataSourceName(), is(yamlShadowDataSourceConfig.getShadowDataSourceName()));
+            assertThat(each.getProductionDataSourceName(), is(yamlShadowDataSourceConfig.getProductionDataSourceName()));
         });
         actual.getTables().forEach((key, value) -> assertThat(value.getShadowAlgorithmNames(), is(expected.getTables().get(key).getShadowAlgorithmNames())));
         actual.getShadowAlgorithms().forEach((key, value) -> assertThat(value.getType(), is(expected.getShadowAlgorithms().get(key).getType())));
diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/yaml/swapper/datasource/YamlShadowDataSourceConfigurationSwapperTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/yaml/swapper/datasource/YamlShadowDataSourceConfigurationSwapperTest.java
deleted file mode 100644
index 137c1301283..00000000000
--- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/yaml/swapper/datasource/YamlShadowDataSourceConfigurationSwapperTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.shardingsphere.shadow.yaml.swapper.datasource;
-
-import org.apache.shardingsphere.shadow.api.config.datasource.ShadowDataSourceConfiguration;
-import org.apache.shardingsphere.shadow.yaml.config.datasource.YamlShadowDataSourceConfiguration;
-import org.junit.Test;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-public final class YamlShadowDataSourceConfigurationSwapperTest {
-    
-    @Test
-    public void assertSwapToYamlConfiguration() {
-        ShadowDataSourceConfiguration shadowDataSourceConfig = new ShadowDataSourceConfiguration("ds", "shadow_ds");
-        YamlShadowDataSourceConfiguration actual = new YamlShadowDataSourceConfigurationSwapper().swapToYamlConfiguration(shadowDataSourceConfig);
-        assertThat(actual.getProductionDataSourceName(), is("ds"));
-        assertThat(actual.getShadowDataSourceName(), is("shadow_ds"));
-    }
-    
-    @Test
-    public void assertSwapToObject() {
-        YamlShadowDataSourceConfiguration yamlConfig = new YamlShadowDataSourceConfiguration();
-        yamlConfig.setProductionDataSourceName("ds");
-        yamlConfig.setShadowDataSourceName("shadow_ds");
-        ShadowDataSourceConfiguration actual = new YamlShadowDataSourceConfigurationSwapper().swapToObject(yamlConfig);
-        assertThat(actual.getProductionDataSourceName(), is("ds"));
-        assertThat(actual.getShadowDataSourceName(), is("shadow_ds"));
-    }
-}
diff --git a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/converter/ShadowRuleStatementConverter.java b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/converter/ShadowRuleStatementConverter.java
index 3b78e9e387a..dc1bf47c28c 100644
--- a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/converter/ShadowRuleStatementConverter.java
+++ b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/converter/ShadowRuleStatementConverter.java
@@ -31,6 +31,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.stream.Collectors;
@@ -69,8 +70,10 @@ public final class ShadowRuleStatementConverter {
         return new ShadowTableConfiguration(new ArrayList<>(Collections.singleton(ruleName)), entry.getValue().stream().map(ShadowAlgorithmSegment::getAlgorithmName).collect(Collectors.toList()));
     }
     
-    private static Map<String, ShadowDataSourceConfiguration> getDataSource(final Collection<ShadowRuleSegment> rules) {
-        return rules.stream().collect(Collectors.toMap(ShadowRuleSegment::getRuleName, each -> new ShadowDataSourceConfiguration(each.getSource(), each.getShadow())));
+    private static Collection<ShadowDataSourceConfiguration> getDataSource(final Collection<ShadowRuleSegment> rules) {
+        Collection<ShadowDataSourceConfiguration> result = new LinkedList<>();
+        rules.forEach(each -> result.add(new ShadowDataSourceConfiguration(each.getRuleName(), each.getSource(), each.getShadow())));
+        return result;
     }
     
     private static Map<String, AlgorithmConfiguration> getShadowAlgorithms(final Collection<ShadowRuleSegment> rules) {
diff --git a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/query/ShadowRuleQueryResultSet.java b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/query/ShadowRuleQueryResultSet.java
index 354afb55c0b..8ce0f1b5984 100644
--- a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/query/ShadowRuleQueryResultSet.java
+++ b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/query/ShadowRuleQueryResultSet.java
@@ -33,7 +33,6 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -60,8 +59,8 @@ public final class ShadowRuleQueryResultSet implements DatabaseDistSQLResultSet
     
     private void buildDataSourceIterator(final ShadowRuleConfiguration ruleConfig, final ShowShadowRulesStatement sqlStatement) {
         Map<String, Map<String, ShadowTableConfiguration>> dataSourceTableMap = convertToDataSourceTableMap(ruleConfig.getTables());
-        Collection<Entry<String, ShadowDataSourceConfiguration>> specifiedConfigs = !isSpecified(sqlStatement) ? ruleConfig.getDataSources().entrySet()
-                : ruleConfig.getDataSources().entrySet().stream().filter(entry -> entry.getKey().equalsIgnoreCase(sqlStatement.getRuleName())).collect(Collectors.toList());
+        Collection<ShadowDataSourceConfiguration> specifiedConfigs = !isSpecified(sqlStatement) ? ruleConfig.getDataSources()
+                : ruleConfig.getDataSources().stream().filter(each -> each.getName().equalsIgnoreCase(sqlStatement.getRuleName())).collect(Collectors.toList());
         data = specifiedConfigs.stream().map(each -> buildDataItem(each, dataSourceTableMap)).collect(Collectors.toList()).iterator();
     }
     
@@ -76,18 +75,18 @@ public final class ShadowRuleQueryResultSet implements DatabaseDistSQLResultSet
         return null != sqlStatement.getRuleName() && !sqlStatement.getRuleName().isEmpty();
     }
     
-    private Map<String, String> buildDataItem(final Entry<String, ShadowDataSourceConfiguration> dataSource, final Map<String, Map<String, ShadowTableConfiguration>> dataSourceTableMap) {
-        Map<String, String> result = convertToDataSourceMap(dataSource);
+    private Map<String, String> buildDataItem(final ShadowDataSourceConfiguration dataSourceConfiguration, final Map<String, Map<String, ShadowTableConfiguration>> dataSourceTableMap) {
+        Map<String, String> result = convertToDataSourceMap(dataSourceConfiguration);
         Map<String, ShadowTableConfiguration> dataSourceTable = dataSourceTableMap.getOrDefault(result.get(RULE_NAME), Collections.emptyMap());
         result.put(SHADOW_TABLE, convertToString(dataSourceTable.keySet()));
         return result;
     }
     
-    private Map<String, String> convertToDataSourceMap(final Entry<String, ShadowDataSourceConfiguration> dataSource) {
+    private Map<String, String> convertToDataSourceMap(final ShadowDataSourceConfiguration dataSourceConfiguration) {
         Map<String, String> result = new HashMap<>();
-        result.put(RULE_NAME, dataSource.getKey());
-        result.put(SOURCE_NAME, dataSource.getValue().getProductionDataSourceName());
-        result.put(SHADOW_NAME, dataSource.getValue().getShadowDataSourceName());
+        result.put(RULE_NAME, dataSourceConfiguration.getName());
+        result.put(SOURCE_NAME, dataSourceConfiguration.getProductionDataSourceName());
+        result.put(SHADOW_NAME, dataSourceConfiguration.getShadowDataSourceName());
         return result;
     }
     
diff --git a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/supporter/ShadowRuleStatementSupporter.java b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/supporter/ShadowRuleStatementSupporter.java
index 9e2badf9b9a..b5b81069606 100644
--- a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/supporter/ShadowRuleStatementSupporter.java
+++ b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/supporter/ShadowRuleStatementSupporter.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
@@ -42,7 +43,7 @@ public final class ShadowRuleStatementSupporter {
      * @return rule names
      */
     public static List<String> getRuleNames(final ShadowRuleConfiguration ruleConfig) {
-        return null == ruleConfig ? Collections.emptyList() : new ArrayList<>(ruleConfig.getDataSources().keySet());
+        return null == ruleConfig ? Collections.emptyList() : getDataSources(ruleConfig);
     }
     
     /**
@@ -55,6 +56,12 @@ public final class ShadowRuleStatementSupporter {
         return segments.isEmpty() ? Collections.emptyList() : segments.stream().map(ShadowRuleSegment::getRuleName).collect(Collectors.toList());
     }
     
+    private static List<String> getDataSources(final ShadowRuleConfiguration ruleConfig) {
+        List<String> result = new LinkedList<>();
+        ruleConfig.getDataSources().forEach(each -> result.add(each.getName()));
+        return result;
+    }
+    
     /**
      * Get the resource names from the rules.
      *
diff --git a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterShadowRuleStatementUpdater.java b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterShadowRuleStatementUpdater.java
index 68ef37c45cc..d85e833b60f 100644
--- a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterShadowRuleStatementUpdater.java
+++ b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/AlterShadowRuleStatementUpdater.java
@@ -61,9 +61,8 @@ public final class AlterShadowRuleStatementUpdater implements RuleDefinitionAlte
         currentRuleConfig.getShadowAlgorithms().putAll(toBeAlteredRuleConfig.getShadowAlgorithms());
     }
     
-    private void updateDataSources(final ShadowRuleConfiguration currentRuleConfig, final Map<String, ShadowDataSourceConfiguration> toBeAlteredDataSources) {
-        currentRuleConfig.getTables().values().forEach(each -> each.getDataSourceNames().removeIf(toBeAlteredDataSources::containsKey));
-        currentRuleConfig.getDataSources().putAll(toBeAlteredDataSources);
+    private void updateDataSources(final ShadowRuleConfiguration currentRuleConfig, final Collection<ShadowDataSourceConfiguration> toBeAlteredDataSources) {
+        currentRuleConfig.getDataSources().addAll(toBeAlteredDataSources);
     }
     
     private void updateTables(final Map<String, ShadowTableConfiguration> currentTables, final Map<String, ShadowTableConfiguration> toBeAlteredTables) {
diff --git a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleStatementUpdater.java b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleStatementUpdater.java
index 476461455b8..c5c9cd754b7 100644
--- a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleStatementUpdater.java
+++ b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/CreateShadowRuleStatementUpdater.java
@@ -52,7 +52,7 @@ public final class CreateShadowRuleStatementUpdater implements RuleDefinitionCre
     @Override
     public void updateCurrentRuleConfiguration(final ShadowRuleConfiguration currentRuleConfig, final ShadowRuleConfiguration toBeCreatedRuleConfig) {
         if (null != currentRuleConfig) {
-            currentRuleConfig.getDataSources().putAll(toBeCreatedRuleConfig.getDataSources());
+            currentRuleConfig.getDataSources().addAll(toBeCreatedRuleConfig.getDataSources());
             currentRuleConfig.getShadowAlgorithms().putAll(toBeCreatedRuleConfig.getShadowAlgorithms());
             updateTables(currentRuleConfig.getTables(), toBeCreatedRuleConfig.getTables());
         }
diff --git a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowRuleStatementUpdater.java b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowRuleStatementUpdater.java
index 3a548819608..a4ef9b653a3 100644
--- a/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowRuleStatementUpdater.java
+++ b/features/shadow/distsql/handler/src/main/java/org/apache/shardingsphere/shadow/distsql/handler/update/DropShadowRuleStatementUpdater.java
@@ -25,6 +25,7 @@ import org.apache.shardingsphere.shadow.distsql.handler.checker.ShadowRuleStatem
 import org.apache.shardingsphere.shadow.distsql.parser.statement.DropShadowRuleStatement;
 
 import java.util.Collection;
+import java.util.LinkedList;
 
 /**
  * Drop shadow rule statement updater.
@@ -48,15 +49,21 @@ public final class DropShadowRuleStatementUpdater implements RuleDefinitionDropU
     }
     
     private void checkRuleNames(final String databaseName, final DropShadowRuleStatement sqlStatement, final ShadowRuleConfiguration currentRuleConfig) {
-        Collection<String> currentRuleNames = currentRuleConfig.getDataSources().keySet();
         if (!sqlStatement.isIfExists()) {
-            ShadowRuleStatementChecker.checkRulesExist(sqlStatement.getRuleNames(), currentRuleNames, different -> new MissingRequiredRuleException(SHADOW, databaseName, different));
+            ShadowRuleStatementChecker.checkRulesExist(sqlStatement.getRuleNames(), getDataSourceNames(currentRuleConfig),
+                    different -> new MissingRequiredRuleException(SHADOW, databaseName, different));
         }
     }
     
+    private Collection<String> getDataSourceNames(final ShadowRuleConfiguration shadowRuleConfiguration) {
+        Collection<String> result = new LinkedList<>();
+        shadowRuleConfiguration.getDataSources().forEach(each -> result.add(each.getName()));
+        return result;
+    }
+    
     @Override
     public boolean hasAnyOneToBeDropped(final DropShadowRuleStatement sqlStatement, final ShadowRuleConfiguration currentRuleConfig) {
-        return isExistRuleConfig(currentRuleConfig) && !getIdenticalData(sqlStatement.getRuleNames(), currentRuleConfig.getDataSources().keySet()).isEmpty();
+        return isExistRuleConfig(currentRuleConfig) && !getIdenticalData(sqlStatement.getRuleNames(), getDataSourceNames(currentRuleConfig)).isEmpty();
     }
     
     @Override
diff --git a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/converter/ShadowRuleStatementConverterTest.java b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/converter/ShadowRuleStatementConverterTest.java
index bac723e3df5..bc6a4bf7ed8 100644
--- a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/converter/ShadowRuleStatementConverterTest.java
+++ b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/converter/ShadowRuleStatementConverterTest.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.shadow.distsql.converter;
 
 import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment;
 import org.apache.shardingsphere.shadow.api.config.ShadowRuleConfiguration;
+import org.apache.shardingsphere.shadow.api.config.datasource.ShadowDataSourceConfiguration;
 import org.apache.shardingsphere.shadow.distsql.handler.converter.ShadowRuleStatementConverter;
 import org.apache.shardingsphere.shadow.distsql.parser.segment.ShadowAlgorithmSegment;
 import org.apache.shardingsphere.shadow.distsql.parser.segment.ShadowRuleSegment;
@@ -35,8 +36,9 @@ public final class ShadowRuleStatementConverterTest {
     @Test
     public void assertConvert() {
         ShadowRuleConfiguration config = ShadowRuleStatementConverter.convert(Collections.singleton(createTableRuleSegment()));
-        assertThat(config.getDataSources().get("ruleName").getProductionDataSourceName(), is("source"));
-        assertThat(config.getDataSources().get("ruleName").getShadowDataSourceName(), is("shadow"));
+        ShadowDataSourceConfiguration shadowDataSourceConfiguration = config.getDataSources().iterator().next();
+        assertThat(shadowDataSourceConfiguration.getProductionDataSourceName(), is("source"));
+        assertThat(shadowDataSourceConfiguration.getShadowDataSourceName(), is("shadow"));
         assertThat(config.getTables().size(), is(1));
         assertThat(config.getShadowAlgorithms().size(), is(1));
         assertThat(config.getShadowAlgorithms().get("algorithmsName").getProps().getProperty("foo"), is("bar"));
diff --git a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/query/ShadowRuleQueryResultSetTest.java b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/query/ShadowRuleQueryResultSetTest.java
index 7d51b44280d..a170ab82bd1 100644
--- a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/query/ShadowRuleQueryResultSetTest.java
+++ b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/query/ShadowRuleQueryResultSetTest.java
@@ -63,7 +63,7 @@ public final class ShadowRuleQueryResultSetTest {
     
     private RuleConfiguration createRuleConfiguration() {
         ShadowRuleConfiguration result = new ShadowRuleConfiguration();
-        result.getDataSources().put("shadow_rule", new ShadowDataSourceConfiguration("source", "shadow"));
+        result.getDataSources().add(new ShadowDataSourceConfiguration("shadow_rule", "source", "shadow"));
         result.getTables().put("t_order", new ShadowTableConfiguration(Collections.singletonList("shadow_rule"), Collections.emptyList()));
         result.getTables().put("t_order_1", new ShadowTableConfiguration(Collections.singletonList("shadow_rule"), Collections.emptyList()));
         return result;
diff --git a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/AlterShadowRuleStatementUpdaterTest.java b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/AlterShadowRuleStatementUpdaterTest.java
index ac6d9247c73..4e79427671f 100644
--- a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/AlterShadowRuleStatementUpdaterTest.java
+++ b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/AlterShadowRuleStatementUpdaterTest.java
@@ -39,10 +39,10 @@ import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -64,11 +64,11 @@ public final class AlterShadowRuleStatementUpdaterTest {
     
     @Before
     public void before() {
-        Map<String, ShadowDataSourceConfiguration> map = new HashMap<>();
-        map.put("initRuleName1", new ShadowDataSourceConfiguration("ds1", "ds_shadow1"));
-        map.put("initRuleName2", new ShadowDataSourceConfiguration("ds2", "ds_shadow2"));
+        Collection<ShadowDataSourceConfiguration> shadowDataSource = new LinkedList<>();
+        shadowDataSource.add(new ShadowDataSourceConfiguration("initRuleName1", "ds1", "ds_shadow1"));
+        shadowDataSource.add(new ShadowDataSourceConfiguration("initRuleName2", "ds2", "ds_shadow2"));
         when(database.getResourceMetaData()).thenReturn(resourceMetaData);
-        when(currentConfig.getDataSources()).thenReturn(map);
+        when(currentConfig.getDataSources()).thenReturn(shadowDataSource);
     }
     
     @Test(expected = MissingRequiredRuleException.class)
diff --git a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/CreateShadowRuleStatementUpdaterTest.java b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/CreateShadowRuleStatementUpdaterTest.java
index 32bd27aa2e7..27555b7c10a 100644
--- a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/CreateShadowRuleStatementUpdaterTest.java
+++ b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/CreateShadowRuleStatementUpdaterTest.java
@@ -61,7 +61,8 @@ public final class CreateShadowRuleStatementUpdaterTest {
     @Before
     public void before() {
         when(database.getResourceMetaData()).thenReturn(resourceMetaData);
-        when(currentConfig.getDataSources()).thenReturn(Collections.singletonMap("initRuleName", new ShadowDataSourceConfiguration("initDs0", "initDs0Shadow")));
+        when(database.getName()).thenReturn("aa");
+        when(currentConfig.getDataSources()).thenReturn(Collections.singletonList(new ShadowDataSourceConfiguration("initRuleName", "initDs0", "initDs0Shadow")));
     }
     
     @Test(expected = DuplicateRuleException.class)
@@ -72,7 +73,7 @@ public final class CreateShadowRuleStatementUpdaterTest {
     
     @Test(expected = DuplicateRuleException.class)
     public void assertExecuteWithDuplicateRuleNameInMetaData() {
-        when(currentConfig.getDataSources()).thenReturn(Collections.singletonMap("ruleName", null));
+        when(currentConfig.getDataSources()).thenReturn(Collections.singletonList(new ShadowDataSourceConfiguration("ruleName", "ds", "ds_shadow")));
         ShadowRuleSegment ruleSegment = new ShadowRuleSegment("ruleName", null, null, null);
         updater.checkSQLStatement(database, createSQLStatement(ruleSegment), currentConfig);
     }
diff --git a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/DropShadowRuleStatementUpdaterTest.java b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/DropShadowRuleStatementUpdaterTest.java
index 7b35cfa8799..0bc49cf68e6 100644
--- a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/DropShadowRuleStatementUpdaterTest.java
+++ b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/update/DropShadowRuleStatementUpdaterTest.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.shadow.distsql.update;
 import org.apache.shardingsphere.infra.distsql.exception.rule.MissingRequiredRuleException;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.shadow.api.config.ShadowRuleConfiguration;
+import org.apache.shardingsphere.shadow.api.config.datasource.ShadowDataSourceConfiguration;
 import org.apache.shardingsphere.shadow.api.config.table.ShadowTableConfiguration;
 import org.apache.shardingsphere.shadow.distsql.handler.update.DropShadowRuleStatementUpdater;
 import org.apache.shardingsphere.shadow.distsql.parser.statement.DropShadowRuleStatement;
@@ -51,7 +52,7 @@ public final class DropShadowRuleStatementUpdaterTest {
     
     @Before
     public void before() {
-        when(currentConfig.getDataSources()).thenReturn(Collections.singletonMap("initRuleName", null));
+        when(currentConfig.getDataSources()).thenReturn(Collections.singletonList(new ShadowDataSourceConfiguration("initRuleName", "ds", "ds_shadow")));
     }
     
     @Test(expected = MissingRequiredRuleException.class)
diff --git a/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/PropertiesShadowSpringBootStarterTest.java b/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/PropertiesShadowSpringBootStarterTest.java
index d4f18b46fca..e4ccac05d23 100644
--- a/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/PropertiesShadowSpringBootStarterTest.java
+++ b/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/PropertiesShadowSpringBootStarterTest.java
@@ -32,6 +32,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 import javax.annotation.Resource;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 
@@ -78,11 +79,20 @@ public class PropertiesShadowSpringBootStarterTest {
         assertThat(shadowTables.get("t_user").getShadowAlgorithmNames(), is(Collections.singletonList("simple-hint-algorithm")));
     }
     
-    private void assertShadowDataSources(final Map<String, ShadowDataSourceConfiguration> dataSources) {
+    private void assertShadowDataSources(final Collection<ShadowDataSourceConfiguration> dataSources) {
         assertThat(dataSources.size(), is(2));
-        assertThat(dataSources.get("shadow-data-source-0").getProductionDataSourceName(), is("ds"));
-        assertThat(dataSources.get("shadow-data-source-0").getShadowDataSourceName(), is("ds-shadow"));
-        assertThat(dataSources.get("shadow-data-source-1").getProductionDataSourceName(), is("ds1"));
-        assertThat(dataSources.get("shadow-data-source-1").getShadowDataSourceName(), is("ds1-shadow"));
+        for (ShadowDataSourceConfiguration each : dataSources) {
+            assertShadowDataSource(each);
+        }
+    }
+    
+    private void assertShadowDataSource(final ShadowDataSourceConfiguration shadowDataSourceConfiguration) {
+        if ("shadow-data-source-0".equals(shadowDataSourceConfiguration.getName())) {
+            assertThat(shadowDataSourceConfiguration.getProductionDataSourceName(), is("ds"));
+            assertThat(shadowDataSourceConfiguration.getShadowDataSourceName(), is("ds-shadow"));
+        } else {
+            assertThat(shadowDataSourceConfiguration.getProductionDataSourceName(), is("ds1"));
+            assertThat(shadowDataSourceConfiguration.getShadowDataSourceName(), is("ds1-shadow"));
+        }
     }
 }
diff --git a/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/YamlShadowDefaultSpringBootStarterTest.java b/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/YamlShadowDefaultSpringBootStarterTest.java
index dd7af25ef37..d6383aee847 100644
--- a/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/YamlShadowDefaultSpringBootStarterTest.java
+++ b/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/YamlShadowDefaultSpringBootStarterTest.java
@@ -29,6 +29,7 @@ import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 import javax.annotation.Resource;
+import java.util.Collection;
 import java.util.Map;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
@@ -61,9 +62,10 @@ public class YamlShadowDefaultSpringBootStarterTest {
         assertThat(simpleHintAlgorithm.getProps().getProperty("foo"), is("bar"));
     }
     
-    private void assertShadowDataSources(final Map<String, ShadowDataSourceConfiguration> dataSources) {
+    private void assertShadowDataSources(final Collection<ShadowDataSourceConfiguration> dataSources) {
         assertThat(dataSources.size(), is(1));
-        assertThat(dataSources.get("shadow-data-source").getProductionDataSourceName(), is("ds"));
-        assertThat(dataSources.get("shadow-data-source").getShadowDataSourceName(), is("ds-shadow"));
+        ShadowDataSourceConfiguration shadowDataSourceConfiguration = dataSources.iterator().next();
+        assertThat(shadowDataSourceConfiguration.getProductionDataSourceName(), is("ds"));
+        assertThat(shadowDataSourceConfiguration.getShadowDataSourceName(), is("ds-shadow"));
     }
 }
diff --git a/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/YmlShadowSpringBootStarterTest.java b/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/YmlShadowSpringBootStarterTest.java
index 3fc19459a6e..1f806f2a2ba 100644
--- a/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/YmlShadowSpringBootStarterTest.java
+++ b/features/shadow/spring/spring-boot-starter/src/test/java/org/apache/shardingsphere/shadow/spring/boot/YmlShadowSpringBootStarterTest.java
@@ -33,6 +33,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 import javax.annotation.Resource;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.Map;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
@@ -84,11 +86,14 @@ public class YmlShadowSpringBootStarterTest {
         assertThat(shadowTables.get("t_user").getShadowAlgorithmNames(), is(Arrays.asList("user-id-value-match-algorithm", "simple-hint-algorithm")));
     }
     
-    private void assertShadowDataSources(final Map<String, ShadowDataSourceConfiguration> dataSources) {
+    private void assertShadowDataSources(final Collection<ShadowDataSourceConfiguration> dataSources) {
         assertThat(dataSources.size(), is(2));
-        assertThat(dataSources.get("shadow-data-source-0").getProductionDataSourceName(), is("ds"));
-        assertThat(dataSources.get("shadow-data-source-0").getShadowDataSourceName(), is("ds-shadow"));
-        assertThat(dataSources.get("shadow-data-source-1").getProductionDataSourceName(), is("ds1"));
-        assertThat(dataSources.get("shadow-data-source-1").getShadowDataSourceName(), is("ds1-shadow"));
+        Iterator<ShadowDataSourceConfiguration> iterator = dataSources.iterator();
+        ShadowDataSourceConfiguration shadowDataSourceConfiguration1 = iterator.next();
+        assertThat(shadowDataSourceConfiguration1.getProductionDataSourceName(), is("ds"));
+        assertThat(shadowDataSourceConfiguration1.getShadowDataSourceName(), is("ds-shadow"));
+        ShadowDataSourceConfiguration shadowDataSourceConfiguration2 = iterator.next();
+        assertThat(shadowDataSourceConfiguration2.getProductionDataSourceName(), is("ds1"));
+        assertThat(shadowDataSourceConfiguration2.getShadowDataSourceName(), is("ds1-shadow"));
     }
 }
diff --git a/features/shadow/spring/spring-namespace/src/main/java/org/apache/shardingsphere/shadow/spring/namespace/parser/ShadowRuleBeanDefinitionParser.java b/features/shadow/spring/spring-namespace/src/main/java/org/apache/shardingsphere/shadow/spring/namespace/parser/ShadowRuleBeanDefinitionParser.java
index 4522525a67c..6afc05a87c2 100644
--- a/features/shadow/spring/spring-namespace/src/main/java/org/apache/shardingsphere/shadow/spring/namespace/parser/ShadowRuleBeanDefinitionParser.java
+++ b/features/shadow/spring/spring-namespace/src/main/java/org/apache/shardingsphere/shadow/spring/namespace/parser/ShadowRuleBeanDefinitionParser.java
@@ -95,17 +95,18 @@ public final class ShadowRuleBeanDefinitionParser extends AbstractBeanDefinition
         return result;
     }
     
-    private Map<String, BeanDefinition> parseDataSourcesConfiguration(final Element element) {
+    private Collection<BeanDefinition> parseDataSourcesConfiguration(final Element element) {
         List<Element> dataSourcesElements = DomUtils.getChildElementsByTagName(element, ShadowRuleBeanDefinitionTag.DATA_SOURCE_TAG);
-        Map<String, BeanDefinition> result = new ManagedMap<>(dataSourcesElements.size());
+        Collection<BeanDefinition> result = new ManagedList<>(dataSourcesElements.size());
         for (Element each : dataSourcesElements) {
-            result.put(each.getAttribute(ShadowRuleBeanDefinitionTag.DATA_SOURCE_ID_ATTRIBUTE), parseDataSourceConfiguration(each));
+            result.add(parseDataSourceConfiguration(each));
         }
         return result;
     }
     
     private BeanDefinition parseDataSourceConfiguration(final Element element) {
         BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(ShadowDataSourceConfiguration.class);
+        factory.addConstructorArgValue(element.getAttribute(ShadowRuleBeanDefinitionTag.DATA_SOURCE_ID_ATTRIBUTE));
         factory.addConstructorArgValue(element.getAttribute(ShadowRuleBeanDefinitionTag.PRODUCTION_DATA_SOURCE_NAME_ATTRIBUTE));
         factory.addConstructorArgValue(element.getAttribute(ShadowRuleBeanDefinitionTag.SHADOW_DATA_SOURCE_NAME_ATTRIBUTE));
         return factory.getBeanDefinition();
diff --git a/features/shadow/spring/spring-namespace/src/test/java/org/apache/shardingsphere/shadow/spring/namespace/ShadowAlgorithmSpringNamespaceTest.java b/features/shadow/spring/spring-namespace/src/test/java/org/apache/shardingsphere/shadow/spring/namespace/ShadowAlgorithmSpringNamespaceTest.java
index d808bda4e0a..d610bccae2b 100644
--- a/features/shadow/spring/spring-namespace/src/test/java/org/apache/shardingsphere/shadow/spring/namespace/ShadowAlgorithmSpringNamespaceTest.java
+++ b/features/shadow/spring/spring-namespace/src/test/java/org/apache/shardingsphere/shadow/spring/namespace/ShadowAlgorithmSpringNamespaceTest.java
@@ -30,6 +30,8 @@ import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
 
 import javax.annotation.Resource;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.Map;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
@@ -78,11 +80,14 @@ public final class ShadowAlgorithmSpringNamespaceTest extends AbstractJUnit4Spri
         assertThat(shadowTables.get("t_user").getShadowAlgorithmNames(), is(Arrays.asList("user-id-value-match-algorithm", "simple-hint-algorithm")));
     }
     
-    private void assertShadowDataSources(final Map<String, ShadowDataSourceConfiguration> dataSources) {
+    private void assertShadowDataSources(final Collection<ShadowDataSourceConfiguration> dataSources) {
         assertThat(dataSources.size(), is(2));
-        assertThat(dataSources.get("shadow-data-source-0").getProductionDataSourceName(), is("ds"));
-        assertThat(dataSources.get("shadow-data-source-0").getShadowDataSourceName(), is("ds-shadow"));
-        assertThat(dataSources.get("shadow-data-source-1").getProductionDataSourceName(), is("ds1"));
-        assertThat(dataSources.get("shadow-data-source-1").getShadowDataSourceName(), is("ds1-shadow"));
+        Iterator<ShadowDataSourceConfiguration> iterator = dataSources.iterator();
+        ShadowDataSourceConfiguration shadowDataSourceConfiguration1 = iterator.next();
+        assertThat(shadowDataSourceConfiguration1.getProductionDataSourceName(), is("ds"));
+        assertThat(shadowDataSourceConfiguration1.getShadowDataSourceName(), is("ds-shadow"));
+        ShadowDataSourceConfiguration shadowDataSourceConfiguration2 = iterator.next();
+        assertThat(shadowDataSourceConfiguration2.getProductionDataSourceName(), is("ds1"));
+        assertThat(shadowDataSourceConfiguration2.getShadowDataSourceName(), is("ds1-shadow"));
     }
 }
diff --git a/features/shadow/spring/spring-namespace/src/test/java/org/apache/shardingsphere/shadow/spring/namespace/ShadowDefaultAlgorithmSpringNamespaceTest.java b/features/shadow/spring/spring-namespace/src/test/java/org/apache/shardingsphere/shadow/spring/namespace/ShadowDefaultAlgorithmSpringNamespaceTest.java
index 6f91c259827..0c51e37d49d 100644
--- a/features/shadow/spring/spring-namespace/src/test/java/org/apache/shardingsphere/shadow/spring/namespace/ShadowDefaultAlgorithmSpringNamespaceTest.java
+++ b/features/shadow/spring/spring-namespace/src/test/java/org/apache/shardingsphere/shadow/spring/namespace/ShadowDefaultAlgorithmSpringNamespaceTest.java
@@ -26,6 +26,7 @@ import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
 
 import javax.annotation.Resource;
+import java.util.Collection;
 import java.util.Map;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
@@ -55,9 +56,10 @@ public final class ShadowDefaultAlgorithmSpringNamespaceTest extends AbstractJUn
         assertThat(simpleHintAlgorithm.getProps().getProperty("foo"), is("bar"));
     }
     
-    private void assertShadowDataSources(final Map<String, ShadowDataSourceConfiguration> dataSources) {
+    private void assertShadowDataSources(final Collection<ShadowDataSourceConfiguration> dataSources) {
         assertThat(dataSources.size(), is(1));
-        assertThat(dataSources.get("shadow-data-source").getProductionDataSourceName(), is("ds"));
-        assertThat(dataSources.get("shadow-data-source").getShadowDataSourceName(), is("ds-shadow"));
+        ShadowDataSourceConfiguration shadowDataSourceConfiguration = dataSources.iterator().next();
+        assertThat(shadowDataSourceConfiguration.getProductionDataSourceName(), is("ds"));
+        assertThat(shadowDataSourceConfiguration.getShadowDataSourceName(), is("ds-shadow"));
     }
 }
diff --git a/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandler.java b/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandler.java
index a31bcfee088..9797990418e 100644
--- a/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandler.java
+++ b/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/queryable/ConvertYamlConfigurationHandler.java
@@ -438,12 +438,12 @@ public final class ConvertYamlConfigurationHandler extends QueryableRALBackendHa
             return;
         }
         result.append(DistSQLScriptConstants.CREATE_SHADOW);
-        Iterator<Entry<String, ShadowDataSourceConfiguration>> iterator = ruleConfig.getDataSources().entrySet().iterator();
+        Iterator<ShadowDataSourceConfiguration> iterator = ruleConfig.getDataSources().iterator();
         while (iterator.hasNext()) {
-            Entry<String, ShadowDataSourceConfiguration> dataSourceConfig = iterator.next();
-            String source = dataSourceConfig.getValue().getProductionDataSourceName();
-            String shadow = dataSourceConfig.getValue().getShadowDataSourceName();
-            String shadowRuleName = dataSourceConfig.getKey();
+            ShadowDataSourceConfiguration dataSourceConfig = iterator.next();
+            String source = dataSourceConfig.getProductionDataSourceName();
+            String shadow = dataSourceConfig.getShadowDataSourceName();
+            String shadowRuleName = dataSourceConfig.getName();
             String shadowTables = getShadowTables(shadowRuleName, ruleConfig.getTables(), ruleConfig.getShadowAlgorithms());
             result.append(String.format(DistSQLScriptConstants.SHADOW, shadowRuleName, source, shadow, shadowTables));
             if (iterator.hasNext()) {
diff --git a/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rql/rule/RulesUsedStorageUnitQueryResultSet.java b/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rql/rule/RulesUsedStorageUnitQueryResultSet.java
index 102601108a6..5583521437d 100644
--- a/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rql/rule/RulesUsedStorageUnitQueryResultSet.java
+++ b/proxy/backend/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rql/rule/RulesUsedStorageUnitQueryResultSet.java
@@ -136,9 +136,9 @@ public final class RulesUsedStorageUnitQueryResultSet implements DatabaseDistSQL
             return Collections.emptyList();
         }
         ShadowRuleConfiguration config = (ShadowRuleConfiguration) rule.get().getConfiguration();
-        return config.getDataSources().entrySet().stream()
-                .filter(entry -> entry.getValue().getShadowDataSourceName().equalsIgnoreCase(resourceName) || entry.getValue().getProductionDataSourceName().equalsIgnoreCase(resourceName))
-                .map(entry -> buildRow(SHADOW, entry.getKey())).collect(Collectors.toList());
+        return config.getDataSources().stream()
+                .filter(each -> each.getShadowDataSourceName().equalsIgnoreCase(resourceName) || each.getProductionDataSourceName().equalsIgnoreCase(resourceName))
+                .map(each -> buildRow(SHADOW, each.getName())).collect(Collectors.toList());
     }
     
     private Collection<Object> buildRow(final String type, final String name) {
diff --git a/proxy/backend/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rql/RulesUsedStorageUnitQueryResultSetTest.java b/proxy/backend/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rql/RulesUsedStorageUnitQueryResultSetTest.java
index 4888f7b02a1..101f5756e08 100644
--- a/proxy/backend/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rql/RulesUsedStorageUnitQueryResultSetTest.java
+++ b/proxy/backend/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rql/RulesUsedStorageUnitQueryResultSetTest.java
@@ -120,7 +120,7 @@ public final class RulesUsedStorageUnitQueryResultSetTest {
     private ShadowRule mockShadowRule() {
         ShadowRule result = mock(ShadowRule.class);
         ShadowRuleConfiguration config = mock(ShadowRuleConfiguration.class);
-        when(config.getDataSources()).thenReturn(Collections.singletonMap("shadow_source", new ShadowDataSourceConfiguration("foo_ds", "shadow_ds")));
+        when(config.getDataSources()).thenReturn(Collections.singletonList(new ShadowDataSourceConfiguration("shadow_source", "foo_ds", "shadow_ds")));
         when(result.getConfiguration()).thenReturn(config);
         return result;
     }