提交 1182121f 编写于 作者: H haocao

Add orchestration spring support 1th.

上级 17c400be
......@@ -11,6 +11,7 @@
<module>sharding-jdbc-spring</module>
<module>sharding-jdbc-transaction-parent</module>
<module>sharding-jdbc-orchestration</module>
<module>sharding-jdbc-orchestration-spring</module>
</modules>
<properties>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc</artifactId>
<version>2.0.0.M2-SNAPSHOT</version>
</parent>
<artifactId>sharding-jdbc-orchestration-spring</artifactId>
<packaging>pom</packaging>
<modules>
<module>sharding-jdbc-orchestration-spring-namespace</module>
<module>sharding-jdbc-orchestration-spring-boot-starter</module>
</modules>
<dependencies>
<dependency>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc-orchestration</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc</artifactId>
<version>${project.parent.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc-spring</artifactId>
<version>2.0.0.M2-SNAPSHOT</version>
</parent>
<artifactId>sharding-jdbc-orchestration-spring-boot-starter</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
package io.shardingjdbc.spring.boot;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import io.shardingjdbc.core.api.MasterSlaveDataSourceFactory;
import io.shardingjdbc.core.api.ShardingDataSourceFactory;
import io.shardingjdbc.core.constant.ShardingPropertiesConstant;
import io.shardingjdbc.core.exception.ShardingJdbcException;
import io.shardingjdbc.core.util.DataSourceUtil;
import io.shardingjdbc.spring.boot.masterslave.SpringBootMasterSlaveRuleConfigurationProperties;
import io.shardingjdbc.spring.boot.sharding.SpringBootShardingRuleConfigurationProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* Spring boot sharding and master-slave configuration.
*
* @author caohao
*/
@Configuration
@EnableConfigurationProperties({SpringBootShardingRuleConfigurationProperties.class, SpringBootMasterSlaveRuleConfigurationProperties.class})
public class SpringBootConfiguration implements EnvironmentAware {
@Autowired
private SpringBootShardingRuleConfigurationProperties shardingProperties;
@Autowired
private SpringBootMasterSlaveRuleConfigurationProperties masterSlaveProperties;
private final Map<String, DataSource> dataSourceMap = new HashMap<>();
private final Properties props = new Properties();
@Bean
public DataSource dataSource() throws SQLException {
return null == masterSlaveProperties.getMasterDataSourceName() ? ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingProperties.getShardingRuleConfiguration(), props)
: MasterSlaveDataSourceFactory.createDataSource(dataSourceMap, masterSlaveProperties.getMasterSlaveRuleConfiguration());
}
@Override
public void setEnvironment(final Environment environment) {
setDataSourceMap(environment);
setShardingProperties(environment);
}
private void setDataSourceMap(final Environment environment) {
RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "sharding.jdbc.datasource.");
String dataSources = propertyResolver.getProperty("names");
for (String each : dataSources.split(",")) {
try {
Map<String, Object> dataSourceProps = propertyResolver.getSubProperties(each + ".");
Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
DataSource dataSource = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(), dataSourceProps);
dataSourceMap.put(each, dataSource);
} catch (final ReflectiveOperationException ex) {
throw new ShardingJdbcException("Can't find datasource type!", ex);
}
}
}
private void setShardingProperties(final Environment environment) {
RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "sharding.jdbc.config.sharding.props.");
String showSQL = propertyResolver.getProperty(ShardingPropertiesConstant.SQL_SHOW.getKey());
if (!Strings.isNullOrEmpty(showSQL)) {
props.setProperty(ShardingPropertiesConstant.SQL_SHOW.getKey(), showSQL);
}
String executorSize = propertyResolver.getProperty(ShardingPropertiesConstant.EXECUTOR_SIZE.getKey());
if (!Strings.isNullOrEmpty(executorSize)) {
props.setProperty(ShardingPropertiesConstant.EXECUTOR_SIZE.getKey(), executorSize);
}
}
}
package io.shardingjdbc.spring.boot.masterslave;
import io.shardingjdbc.core.yaml.masterslave.YamMasterSlaveRuleConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Master slave rule configuration properties.
*
* @author caohao
*/
@ConfigurationProperties(prefix = "sharding.jdbc.config.masterslave")
public class SpringBootMasterSlaveRuleConfigurationProperties extends YamMasterSlaveRuleConfiguration {
}
package io.shardingjdbc.spring.boot.sharding;
import io.shardingjdbc.core.yaml.sharding.YamlShardingRuleConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Sharding rule configuration properties.
*
* @author caohao
*/
@ConfigurationProperties(prefix = "sharding.jdbc.config.sharding")
public class SpringBootShardingRuleConfigurationProperties extends YamlShardingRuleConfiguration {
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
io.shardingjdbc.spring.boot.SpringBootConfiguration
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.boot;
import io.shardingjdbc.spring.boot.type.SpringBootMasterSlaveTest;
import io.shardingjdbc.spring.boot.type.SpringBootShardingTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
SpringBootMasterSlaveTest.class,
SpringBootShardingTest.class
})
public class AllSpringBootTests {
}
package io.shardingjdbc.spring.boot.type;
import io.shardingjdbc.core.jdbc.core.datasource.MasterSlaveDataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import javax.sql.DataSource;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SpringBootMasterSlaveTest.class)
@SpringBootApplication
@ActiveProfiles("masterslave")
public class SpringBootMasterSlaveTest {
@Resource
private DataSource dataSource;
@Test
public void assertWithMasterSlaveDataSource() {
assertTrue(dataSource instanceof MasterSlaveDataSource);
for (DataSource each : ((MasterSlaveDataSource) dataSource).getAllDataSources().values()) {
assertThat(((BasicDataSource) each).getMaxActive(), is(16));
}
}
}
package io.shardingjdbc.spring.boot.type;
import io.shardingjdbc.core.jdbc.core.ShardingContext;
import io.shardingjdbc.core.jdbc.core.datasource.ShardingDataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.lang.reflect.Field;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SpringBootShardingTest.class)
@SpringBootApplication
@ActiveProfiles("sharding")
public class SpringBootShardingTest {
@Resource
private DataSource dataSource;
@Test
public void assertWithShardingDataSource() throws NoSuchFieldException, IllegalAccessException {
assertTrue(dataSource instanceof ShardingDataSource);
Field field = ShardingDataSource.class.getDeclaredField("shardingContext");
field.setAccessible(true);
ShardingContext shardingContext = (ShardingContext) field.get(dataSource);
for (DataSource each : shardingContext.getShardingRule().getDataSourceMap().values()) {
assertThat(((BasicDataSource) each).getMaxActive(), is(16));
}
assertTrue(shardingContext.isShowSQL());
}
}
sharding.jdbc.datasource.names=ds_master,ds_slave_0,ds_slave_1
sharding.jdbc.datasource.ds_master.type=org.apache.commons.dbcp.BasicDataSource
sharding.jdbc.datasource.ds_master.driver-class-name=org.h2.Driver
sharding.jdbc.datasource.ds_master.url=jdbc:h2:mem:ds_master;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
sharding.jdbc.datasource.ds_master.username=root
sharding.jdbc.datasource.ds_master.password=
sharding.jdbc.datasource.ds_master.maxActive=16
sharding.jdbc.datasource.ds_slave_0.type=org.apache.commons.dbcp.BasicDataSource
sharding.jdbc.datasource.ds_slave_0.driver-class-name=org.h2.Driver
sharding.jdbc.datasource.ds_slave_0.url=jdbc:h2:mem:demo_ds_slave_0;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
sharding.jdbc.datasource.ds_slave_0.username=root
sharding.jdbc.datasource.ds_slave_0.password=
sharding.jdbc.datasource.ds_slave_0.maxActive=16
sharding.jdbc.datasource.ds_slave_1.type=org.apache.commons.dbcp.BasicDataSource
sharding.jdbc.datasource.ds_slave_1.driver-class-name=org.h2.Driver
sharding.jdbc.datasource.ds_slave_1.url=jdbc:h2:mem:demo_ds_slave_1;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
sharding.jdbc.datasource.ds_slave_1.username=root
sharding.jdbc.datasource.ds_slave_1.password=
sharding.jdbc.datasource.ds_slave_1.maxActive=16
sharding.jdbc.config.masterslave.name=ds_ms
sharding.jdbc.config.masterslave.masterDataSourceName=ds_master
sharding.jdbc.config.masterslave.slaveDataSourceNames=ds_slave_0,ds_slave_1
sharding.jdbc.datasource.names=ds,ds_0,ds_1
sharding.jdbc.datasource.ds.type=org.apache.commons.dbcp.BasicDataSource
sharding.jdbc.datasource.ds.driver-class-name=org.h2.Driver
sharding.jdbc.datasource.ds.url=jdbc:h2:mem:ds;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
sharding.jdbc.datasource.ds.username=sa
sharding.jdbc.datasource.ds.password=
sharding.jdbc.datasource.ds.maxActive=16
sharding.jdbc.datasource.ds_0.type=org.apache.commons.dbcp.BasicDataSource
sharding.jdbc.datasource.ds_0.driver-class-name=org.h2.Driver
sharding.jdbc.datasource.ds_0.url=jdbc:h2:mem:ds_0;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
sharding.jdbc.datasource.ds_0.username=sa
sharding.jdbc.datasource.ds_0.password=
sharding.jdbc.datasource.ds_0.maxActive=16
sharding.jdbc.datasource.ds_1.type=org.apache.commons.dbcp.BasicDataSource
sharding.jdbc.datasource.ds_1.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds_1.url=jdbc:h2:mem:ds_1;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
sharding.jdbc.datasource.ds_1.username=sa
sharding.jdbc.datasource.ds_1.password=
sharding.jdbc.datasource.ds_1.maxActive=16
sharding.jdbc.config.sharding.default-data-source-name=ds
sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=user_id
sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=ds_${user_id % 2}
sharding.jdbc.config.sharding.tables.t_order.actualDataNodes=ds_${0..1}.t_order_${0..1}
sharding.jdbc.config.sharding.tables.t_order.tableStrategy.inline.shardingColumn=order_id
sharding.jdbc.config.sharding.tables.t_order.tableStrategy.inline.algorithmExpression=t_order_${order_id % 2}
sharding.jdbc.config.sharding.tables.t_order.keyGeneratorColumnName=order_id
sharding.jdbc.config.sharding.tables.t_order_item.actualDataNodes=ds_${0..1}.t_order_item_${0..1}
sharding.jdbc.config.sharding.tables.t_order_item.tableStrategy.inline.shardingColumn=order_id
sharding.jdbc.config.sharding.tables.t_order_item.tableStrategy.inline.algorithmExpression=t_order_item_${order_id % 2}
sharding.jdbc.config.sharding.tables.t_order_item.keyGeneratorColumnName=order_item_id
sharding.jdbc.config.sharding.props.sql.show=true
sharding.jdbc.config.sharding.props.executor.size=100
<?xml version="1.0"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%-5level] %d{HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="io.shardingjdbc" level="info" additivity="false">
<appender-ref ref="console"/>
</logger>
<logger name="org.dbunit" level="info" additivity="false">
<appender-ref ref="console"/>
</logger>
<logger name="io.shardingjdbc.core.executor.threadlocal.ExecutorExceptionHandler" level="off">
</logger>
<root>
<level value="error" />
<appender-ref ref="console" />
</root>
</configuration>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc-spring</artifactId>
<version>2.0.0.M2-SNAPSHOT</version>
</parent>
<artifactId>sharding-jdbc-orchestration-spring-namespace</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
package io.shardingjdbc.spring.datasource;
import com.google.common.collect.Sets;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import javax.sql.DataSource;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;
/**
* Data source bean util.
*
* @author zhangliang
*/
@NoArgsConstructor(access = AccessLevel.NONE)
public final class DataSourceBeanUtil {
private static Collection<Class<?>> generalClassType;
static {
generalClassType = Sets.<Class<?>>newHashSet(boolean.class, Boolean.class, int.class, Integer.class, long.class, Long.class, String.class);
}
static void createDataSourceBean(final ApplicationContext applicationContext, final String dataSourceName, final DataSource dataSource) {
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
BeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName(dataSource.getClass().getName());
beanFactory.registerBeanDefinition(dataSourceName, beanDefinition);
Method[] methods = dataSource.getClass().getMethods();
Map<String, Method> getterMethods = new TreeMap<>();
Map<String, Method> setterMethods = new TreeMap<>();
for (Method each : methods) {
if (isGetterMethod(each)) {
getterMethods.put(getPropertyName(each), each);
} else if (isSetterMethod(each)) {
setterMethods.put(getPropertyName(each), each);
}
}
Map<String, Method> getterPairedGetterMethods = getPairedGetterMethods(getterMethods, setterMethods);
for (Map.Entry<String, Method> entry : getterPairedGetterMethods.entrySet()) {
Object getterResult = null;
try {
getterResult = entry.getValue().invoke(dataSource);
// CHECKSTYLE:OFF
} catch (final Exception ex) {
}
// CHECKSTYLE:ON
if (null != getterResult) {
beanDefinition.setAttribute(entry.getKey(), getterResult);
}
}
}
private static boolean isGetterMethod(final Method method) {
return method.getName().startsWith("get") && 0 == method.getParameterTypes().length && isGeneralClassType(method.getReturnType());
}
private static boolean isSetterMethod(final Method method) {
return method.getName().startsWith("set") && 1 == method.getParameterTypes().length && isGeneralClassType(method.getParameterTypes()[0]) && isVoid(method.getReturnType());
}
private static boolean isGeneralClassType(final Class<?> clazz) {
return generalClassType.contains(clazz);
}
private static boolean isVoid(final Class<?> clazz) {
return void.class == clazz || Void.class == clazz;
}
private static String getPropertyName(final Method method) {
return String.valueOf(method.getName().charAt(3)).toLowerCase() + method.getName().substring(4, method.getName().length());
}
private static Map<String, Method> getPairedGetterMethods(final Map<String, Method> getterMethods, final Map<String, Method> setterMethods) {
Map<String, Method> result = new TreeMap<>();
for (Map.Entry<String, Method> entry : getterMethods.entrySet()) {
if (setterMethods.containsKey(entry.getKey())) {
result.put(entry.getKey(), entry.getValue());
}
}
return result;
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.datasource;
import io.shardingjdbc.core.api.algorithm.masterslave.MasterSlaveLoadBalanceAlgorithm;
import io.shardingjdbc.core.api.algorithm.masterslave.MasterSlaveLoadBalanceAlgorithmType;
import io.shardingjdbc.core.jdbc.core.datasource.MasterSlaveDataSource;
import io.shardingjdbc.core.rule.MasterSlaveRule;
import lombok.Setter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Map;
import java.util.Map.Entry;
/**
* Master-slave datasource for spring namespace.
*
* @author zhangliang
*/
public class SpringMasterSlaveDataSource extends MasterSlaveDataSource implements ApplicationContextAware {
@Setter
private ApplicationContext applicationContext;
public SpringMasterSlaveDataSource(final String name, final String masterDataSourceName,
final DataSource masterDataSource, final Map<String, DataSource> slaveDataSourceMap) throws SQLException {
super(new MasterSlaveRule(name, masterDataSourceName, masterDataSource, slaveDataSourceMap));
}
public SpringMasterSlaveDataSource(final String name, final String masterDataSourceName,
final DataSource masterDataSource, final Map<String, DataSource> slaveDataSourceMap, final MasterSlaveLoadBalanceAlgorithm strategy) throws SQLException {
super(new MasterSlaveRule(name, masterDataSourceName, masterDataSource, slaveDataSourceMap, strategy));
}
public SpringMasterSlaveDataSource(final String name, final String masterDataSourceName, final DataSource masterDataSource,
final Map<String, DataSource> slaveDataSourceMap, final MasterSlaveLoadBalanceAlgorithmType strategyType) throws SQLException {
super(new MasterSlaveRule(name, masterDataSourceName, masterDataSource, slaveDataSourceMap, strategyType.getAlgorithm()));
}
@Override
public void renew(final MasterSlaveRule masterSlaveRule) throws SQLException {
DataSourceBeanUtil.createDataSourceBean(applicationContext, masterSlaveRule.getMasterDataSourceName(), masterSlaveRule.getMasterDataSource());
for (Entry<String, DataSource> entry : masterSlaveRule.getSlaveDataSourceMap().entrySet()) {
DataSourceBeanUtil.createDataSourceBean(applicationContext, entry.getKey(), entry.getValue());
}
super.renew(masterSlaveRule);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.datasource;
import io.shardingjdbc.core.api.config.ShardingRuleConfiguration;
import io.shardingjdbc.core.jdbc.core.datasource.MasterSlaveDataSource;
import io.shardingjdbc.core.jdbc.core.datasource.ShardingDataSource;
import io.shardingjdbc.core.rule.ShardingRule;
import lombok.Setter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
/**
* Sharding datasource for spring namespace.
*
* @author caohao
* @author zhanglaing
*/
public class SpringShardingDataSource extends ShardingDataSource implements ApplicationContextAware {
@Setter
private ApplicationContext applicationContext;
public SpringShardingDataSource(final Map<String, DataSource> dataSourceMap, final ShardingRuleConfiguration shardingRuleConfig, final Properties props) throws SQLException {
super(shardingRuleConfig.build(dataSourceMap), props);
}
@Override
public void renew(final ShardingRule newShardingRule, final Properties newProps) throws SQLException {
for (Entry<String, DataSource> entry : newShardingRule.getDataSourceMap().entrySet()) {
if (entry.getValue() instanceof MasterSlaveDataSource) {
for (Entry<String, DataSource> masterSlaveEntry : ((MasterSlaveDataSource) entry.getValue()).getAllDataSources().entrySet()) {
DataSourceBeanUtil.createDataSourceBean(applicationContext, masterSlaveEntry.getKey(), masterSlaveEntry.getValue());
}
} else {
DataSourceBeanUtil.createDataSourceBean(applicationContext, entry.getKey(), entry.getValue());
}
}
super.renew(newShardingRule, newProps);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.constants;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* Master-slave data source parser tag constants.
*
* @author zhangliang
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class MasterSlaveDataSourceBeanDefinitionParserTag {
public static final String ROOT_TAG = "data-source";
public static final String MASTER_DATA_SOURCE_NAME_ATTRIBUTE = "master-data-source-name";
public static final String SLAVE_DATA_SOURCE_NAMES_ATTRIBUTE = "slave-data-source-names";
public static final String STRATEGY_REF_ATTRIBUTE = "strategy-ref";
public static final String STRATEGY_TYPE_ATTRIBUTE = "strategy-type";
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.constants;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* Sharding data source parser tag constants.
*
* @author caohao
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ShardingJdbcDataSourceBeanDefinitionParserTag {
public static final String ROOT_TAG = "data-source";
public static final String SHARDING_RULE_CONFIG_TAG = "sharding-rule";
public static final String PROPS_TAG = "props";
public static final String DATA_SOURCE_NAMES_TAG = "data-source-names";
public static final String DEFAULT_DATA_SOURCE_NAME_TAG = "default-data-source-name";
public static final String TABLE_RULES_TAG = "table-rules";
public static final String TABLE_RULE_TAG = "table-rule";
public static final String BINDING_TABLE_RULES_TAG = "binding-table-rules";
public static final String BINDING_TABLE_RULE_TAG = "binding-table-rule";
public static final String LOGIC_TABLE_ATTRIBUTE = "logic-table";
public static final String LOGIC_TABLES_ATTRIBUTE = "logic-tables";
public static final String ACTUAL_DATA_NODES_ATTRIBUTE = "actual-data-nodes";
public static final String DATABASE_STRATEGY_REF_ATTRIBUTE = "database-strategy-ref";
public static final String TABLE_STRATEGY_REF_ATTRIBUTE = "table-strategy-ref";
public static final String DEFAULT_DATABASE_STRATEGY_REF_ATTRIBUTE = "default-database-strategy-ref";
public static final String DEFAULT_TABLE_STRATEGY_REF_ATTRIBUTE = "default-table-strategy-ref";
public static final String GENERATE_KEY_COLUMN = "generate-key-column";
public static final String COLUMN_KEY_GENERATOR_CLASS = "column-key-generator-class";
public static final String KEY_GENERATOR_CLASS = "key-generator-class";
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.constants;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* Sharding strategy parser tag constants.
*
* @author caohao
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ShardingJdbcStrategyBeanDefinitionParserTag {
public static final String STANDARD_STRATEGY_ROOT_TAG = "standard-strategy";
public static final String COMPLEX_STRATEGY_ROOT_TAG = "complex-strategy";
public static final String INLINE_STRATEGY_ROOT_TAG = "inline-strategy";
public static final String HINT_STRATEGY_ROOT_TAG = "hint-strategy";
public static final String NONE_STRATEGY_ROOT_TAG = "none-strategy";
public static final String SHARDING_COLUMN_ATTRIBUTE = "sharding-column";
public static final String SHARDING_COLUMNS_ATTRIBUTE = "sharding-columns";
public static final String ALGORITHM_CLASS_ATTRIBUTE = "algorithm-class";
public static final String PRECISE_ALGORITHM_CLASS_ATTRIBUTE = "precise-algorithm-class";
public static final String RANGE_ALGORITHM_CLASS_ATTRIBUTE = "range-algorithm-class";
public static final String ALGORITHM_EXPRESSION_ATTRIBUTE = "algorithm-expression";
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.handler;
import io.shardingjdbc.spring.namespace.constants.MasterSlaveDataSourceBeanDefinitionParserTag;
import io.shardingjdbc.spring.namespace.parser.MasterSlaveDataSourceBeanDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* Spring namespace handler for master-slave.
*
* @author zhangliang
*/
public final class MasterSlaveNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser(MasterSlaveDataSourceBeanDefinitionParserTag.ROOT_TAG, new MasterSlaveDataSourceBeanDefinitionParser());
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.handler;
import io.shardingjdbc.spring.namespace.parser.ZookeeperBeanDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* Registry center namespace handler.
*
* @author caohao
*/
public final class RegNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("zookeeper", new ZookeeperBeanDefinitionParser());
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.handler;
import io.shardingjdbc.spring.namespace.constants.ShardingJdbcDataSourceBeanDefinitionParserTag;
import io.shardingjdbc.spring.namespace.constants.ShardingJdbcStrategyBeanDefinitionParserTag;
import io.shardingjdbc.spring.namespace.parser.ShardingDataSourceBeanDefinitionParser;
import io.shardingjdbc.spring.namespace.parser.ShardingStrategyBeanDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* Spring namespace handler for sharding.
*
* @author caohao
* @author zhangliang
*/
public final class ShardingNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser(ShardingJdbcStrategyBeanDefinitionParserTag.STANDARD_STRATEGY_ROOT_TAG, new ShardingStrategyBeanDefinitionParser());
registerBeanDefinitionParser(ShardingJdbcStrategyBeanDefinitionParserTag.COMPLEX_STRATEGY_ROOT_TAG, new ShardingStrategyBeanDefinitionParser());
registerBeanDefinitionParser(ShardingJdbcStrategyBeanDefinitionParserTag.INLINE_STRATEGY_ROOT_TAG, new ShardingStrategyBeanDefinitionParser());
registerBeanDefinitionParser(ShardingJdbcStrategyBeanDefinitionParserTag.HINT_STRATEGY_ROOT_TAG, new ShardingStrategyBeanDefinitionParser());
registerBeanDefinitionParser(ShardingJdbcStrategyBeanDefinitionParserTag.NONE_STRATEGY_ROOT_TAG, new ShardingStrategyBeanDefinitionParser());
registerBeanDefinitionParser(ShardingJdbcDataSourceBeanDefinitionParserTag.ROOT_TAG, new ShardingDataSourceBeanDefinitionParser());
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.parser;
import io.shardingjdbc.core.api.algorithm.masterslave.MasterSlaveLoadBalanceAlgorithmType;
import io.shardingjdbc.spring.datasource.SpringMasterSlaveDataSource;
import io.shardingjdbc.spring.namespace.constants.MasterSlaveDataSourceBeanDefinitionParserTag;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import java.util.List;
import java.util.Map;
/**
* Master-slave data source parser for spring namespace.
*
* @author zhangliang
*/
public class MasterSlaveDataSourceBeanDefinitionParser extends AbstractBeanDefinitionParser {
@Override
//CHECKSTYLE:OFF
protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext parserContext) {
//CHECKSTYLE:ON
BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(SpringMasterSlaveDataSource.class);
factory.addConstructorArgValue(parseId(element));
String masterDataSourceName = parseMasterDataSourceRef(element);
factory.addConstructorArgValue(masterDataSourceName);
factory.addConstructorArgReference(masterDataSourceName);
factory.addConstructorArgValue(parseSlaveDataSources(element, parserContext));
String strategyRef = parseStrategyRef(element);
if (!Strings.isNullOrEmpty(strategyRef)) {
factory.addConstructorArgReference(strategyRef);
} else {
factory.addConstructorArgValue(parseStrategyType(element));
}
return factory.getBeanDefinition();
}
private String parseId(final Element element) {
return element.getAttribute(ID_ATTRIBUTE);
}
private String parseMasterDataSourceRef(final Element element) {
return element.getAttribute(MasterSlaveDataSourceBeanDefinitionParserTag.MASTER_DATA_SOURCE_NAME_ATTRIBUTE);
}
private Map<String, BeanDefinition> parseSlaveDataSources(final Element element, final ParserContext parserContext) {
List<String> slaveDataSources = Splitter.on(",").trimResults().splitToList(element.getAttribute(MasterSlaveDataSourceBeanDefinitionParserTag.SLAVE_DATA_SOURCE_NAMES_ATTRIBUTE));
Map<String, BeanDefinition> result = new ManagedMap<>(slaveDataSources.size());
for (String each : slaveDataSources) {
result.put(each, parserContext.getRegistry().getBeanDefinition(each));
}
return result;
}
private String parseStrategyRef(final Element element) {
return element.getAttribute(MasterSlaveDataSourceBeanDefinitionParserTag.STRATEGY_REF_ATTRIBUTE);
}
private MasterSlaveLoadBalanceAlgorithmType parseStrategyType(final Element element) {
String result = element.getAttribute(MasterSlaveDataSourceBeanDefinitionParserTag.STRATEGY_TYPE_ATTRIBUTE);
return Strings.isNullOrEmpty(result) ? MasterSlaveLoadBalanceAlgorithmType.getDefaultAlgorithmType() : MasterSlaveLoadBalanceAlgorithmType.valueOf(result);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.parser;
import io.shardingjdbc.core.api.config.ShardingRuleConfiguration;
import io.shardingjdbc.core.api.config.TableRuleConfiguration;
import io.shardingjdbc.spring.datasource.SpringShardingDataSource;
import io.shardingjdbc.spring.namespace.constants.ShardingJdbcDataSourceBeanDefinitionParserTag;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* Sharding data source parser for spring namespace.
*
* @author caohao
*/
public class ShardingDataSourceBeanDefinitionParser extends AbstractBeanDefinitionParser {
@Override
//CHECKSTYLE:OFF
protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext parserContext) {
//CHECKSTYLE:ON
BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(SpringShardingDataSource.class);
factory.addConstructorArgValue(parseDataSources(element, parserContext));
factory.addConstructorArgValue(parseShardingRuleConfig(element));
factory.addConstructorArgValue(parseProperties(element, parserContext));
factory.setDestroyMethodName("close");
return factory.getBeanDefinition();
}
private Map<String, BeanDefinition> parseDataSources(final Element element, final ParserContext parserContext) {
Element shardingRuleElement = DomUtils.getChildElementByTagName(element, ShardingJdbcDataSourceBeanDefinitionParserTag.SHARDING_RULE_CONFIG_TAG);
List<String> dataSources = Splitter.on(",").trimResults().splitToList(shardingRuleElement.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.DATA_SOURCE_NAMES_TAG));
Map<String, BeanDefinition> result = new ManagedMap<>(dataSources.size());
for (String each : dataSources) {
result.put(each, parserContext.getRegistry().getBeanDefinition(each));
}
return result;
}
private BeanDefinition parseShardingRuleConfig(final Element element) {
Element shardingRuleElement = DomUtils.getChildElementByTagName(element, ShardingJdbcDataSourceBeanDefinitionParserTag.SHARDING_RULE_CONFIG_TAG);
BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(ShardingRuleConfiguration.class);
parseDefaultDataSource(factory, shardingRuleElement);
parseDefaultDatabaseShardingStrategy(factory, shardingRuleElement);
parseDefaultTableShardingStrategy(factory, shardingRuleElement);
factory.addPropertyValue("tableRuleConfigs", parseTableRulesConfig(shardingRuleElement));
factory.addPropertyValue("bindingTableGroups", parseBindingTablesConfig(shardingRuleElement));
parseKeyGenerator(factory, shardingRuleElement);
return factory.getBeanDefinition();
}
private void parseKeyGenerator(final BeanDefinitionBuilder factory, final Element element) {
String keyGeneratorClass = element.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.KEY_GENERATOR_CLASS);
if (!Strings.isNullOrEmpty(keyGeneratorClass)) {
factory.addPropertyValue("defaultKeyGeneratorClass", keyGeneratorClass);
}
}
private void parseDefaultDataSource(final BeanDefinitionBuilder factory, final Element element) {
String defaultDataSource = element.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.DEFAULT_DATA_SOURCE_NAME_TAG);
if (!Strings.isNullOrEmpty(defaultDataSource)) {
factory.addPropertyValue("defaultDataSourceName", defaultDataSource);
}
}
private void parseDefaultDatabaseShardingStrategy(final BeanDefinitionBuilder factory, final Element element) {
String defaultDatabaseShardingStrategy = element.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.DEFAULT_DATABASE_STRATEGY_REF_ATTRIBUTE);
if (!Strings.isNullOrEmpty(defaultDatabaseShardingStrategy)) {
factory.addPropertyReference("defaultDatabaseShardingStrategyConfig", defaultDatabaseShardingStrategy);
}
}
private void parseDefaultTableShardingStrategy(final BeanDefinitionBuilder factory, final Element element) {
String defaultTableShardingStrategy = element.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.DEFAULT_TABLE_STRATEGY_REF_ATTRIBUTE);
if (!Strings.isNullOrEmpty(defaultTableShardingStrategy)) {
factory.addPropertyReference("defaultTableShardingStrategyConfig", defaultTableShardingStrategy);
}
}
private List<BeanDefinition> parseTableRulesConfig(final Element element) {
Element tableRulesElement = DomUtils.getChildElementByTagName(element, ShardingJdbcDataSourceBeanDefinitionParserTag.TABLE_RULES_TAG);
List<Element> tableRuleElements = DomUtils.getChildElementsByTagName(tableRulesElement, ShardingJdbcDataSourceBeanDefinitionParserTag.TABLE_RULE_TAG);
List<BeanDefinition> result = new ManagedList<>(tableRuleElements.size());
for (Element each : tableRuleElements) {
result.add(parseTableRuleConfig(each));
}
return result;
}
private BeanDefinition parseTableRuleConfig(final Element tableElement) {
BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(TableRuleConfiguration.class);
factory.addPropertyValue("logicTable", tableElement.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.LOGIC_TABLE_ATTRIBUTE));
String actualDataNodes = tableElement.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.ACTUAL_DATA_NODES_ATTRIBUTE);
if (!Strings.isNullOrEmpty(actualDataNodes)) {
factory.addPropertyValue("actualDataNodes", actualDataNodes);
}
String databaseStrategy = tableElement.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.DATABASE_STRATEGY_REF_ATTRIBUTE);
if (!Strings.isNullOrEmpty(databaseStrategy)) {
factory.addPropertyReference("databaseShardingStrategyConfig", databaseStrategy);
}
String tableStrategy = tableElement.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.TABLE_STRATEGY_REF_ATTRIBUTE);
if (!Strings.isNullOrEmpty(tableStrategy)) {
factory.addPropertyReference("tableShardingStrategyConfig", tableStrategy);
}
String keyGeneratorColumnName = tableElement.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.GENERATE_KEY_COLUMN);
if (!Strings.isNullOrEmpty(keyGeneratorColumnName)) {
factory.addPropertyValue("keyGeneratorColumnName", keyGeneratorColumnName);
}
String keyGeneratorClass = tableElement.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.COLUMN_KEY_GENERATOR_CLASS);
if (!Strings.isNullOrEmpty(keyGeneratorClass)) {
factory.addPropertyValue("keyGeneratorClass", keyGeneratorClass);
}
return factory.getBeanDefinition();
}
private List<String> parseBindingTablesConfig(final Element element) {
Element bindingTableRulesElement = DomUtils.getChildElementByTagName(element, ShardingJdbcDataSourceBeanDefinitionParserTag.BINDING_TABLE_RULES_TAG);
if (null == bindingTableRulesElement) {
return Collections.emptyList();
}
List<Element> bindingTableRuleElements = DomUtils.getChildElementsByTagName(bindingTableRulesElement, ShardingJdbcDataSourceBeanDefinitionParserTag.BINDING_TABLE_RULE_TAG);
List<String> result = new LinkedList<>();
for (Element bindingTableRuleElement : bindingTableRuleElements) {
result.add(bindingTableRuleElement.getAttribute(ShardingJdbcDataSourceBeanDefinitionParserTag.LOGIC_TABLES_ATTRIBUTE));
}
return result;
}
private BeanDefinition parseDefaultStrategyConfig(final Element element, final String attr) {
Element strategyElement = DomUtils.getChildElementByTagName(element, attr);
return null == strategyElement ? null : ShardingStrategyBeanDefinition.getBeanDefinitionByElement(strategyElement);
}
private Properties parseProperties(final Element element, final ParserContext parserContext) {
Element propsElement = DomUtils.getChildElementByTagName(element, ShardingJdbcDataSourceBeanDefinitionParserTag.PROPS_TAG);
return null == propsElement ? new Properties() : parserContext.getDelegate().parsePropsElement(propsElement);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.parser;
import io.shardingjdbc.core.api.config.strategy.ComplexShardingStrategyConfiguration;
import io.shardingjdbc.core.api.config.strategy.HintShardingStrategyConfiguration;
import io.shardingjdbc.core.api.config.strategy.InlineShardingStrategyConfiguration;
import io.shardingjdbc.core.api.config.strategy.NoneShardingStrategyConfiguration;
import io.shardingjdbc.core.api.config.strategy.StandardShardingStrategyConfiguration;
import io.shardingjdbc.core.exception.ShardingJdbcException;
import io.shardingjdbc.spring.namespace.constants.ShardingJdbcStrategyBeanDefinitionParserTag;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.w3c.dom.Element;
/**
* Sharding strategy parser for spring namespace.
*
* @author caohao
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ShardingStrategyBeanDefinition {
static AbstractBeanDefinition getBeanDefinitionByElement(final Element element) {
String type = element.getLocalName();
switch (type) {
case ShardingJdbcStrategyBeanDefinitionParserTag.STANDARD_STRATEGY_ROOT_TAG:
return getStandardShardingStrategyConfigBeanDefinition(element);
case ShardingJdbcStrategyBeanDefinitionParserTag.COMPLEX_STRATEGY_ROOT_TAG:
return getComplexShardingStrategyConfigBeanDefinition(element);
case ShardingJdbcStrategyBeanDefinitionParserTag.INLINE_STRATEGY_ROOT_TAG:
return getInlineShardingStrategyConfigBeanDefinition(element);
case ShardingJdbcStrategyBeanDefinitionParserTag.HINT_STRATEGY_ROOT_TAG:
return getHintShardingStrategyConfigBeanDefinition(element);
case ShardingJdbcStrategyBeanDefinitionParserTag.NONE_STRATEGY_ROOT_TAG:
return getNoneShardingStrategyConfigBeanDefinition();
default:
throw new ShardingJdbcException("Cannot support type: %s", type);
}
}
private static AbstractBeanDefinition getStandardShardingStrategyConfigBeanDefinition(final Element element) {
BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(StandardShardingStrategyConfiguration.class);
factory.addConstructorArgValue(element.getAttribute(ShardingJdbcStrategyBeanDefinitionParserTag.SHARDING_COLUMN_ATTRIBUTE));
factory.addConstructorArgValue(element.getAttribute(ShardingJdbcStrategyBeanDefinitionParserTag.PRECISE_ALGORITHM_CLASS_ATTRIBUTE));
factory.addConstructorArgValue(element.getAttribute(ShardingJdbcStrategyBeanDefinitionParserTag.RANGE_ALGORITHM_CLASS_ATTRIBUTE));
return factory.getBeanDefinition();
}
private static AbstractBeanDefinition getComplexShardingStrategyConfigBeanDefinition(final Element element) {
BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(ComplexShardingStrategyConfiguration.class);
factory.addConstructorArgValue(element.getAttribute(ShardingJdbcStrategyBeanDefinitionParserTag.SHARDING_COLUMNS_ATTRIBUTE));
factory.addConstructorArgValue(element.getAttribute(ShardingJdbcStrategyBeanDefinitionParserTag.ALGORITHM_CLASS_ATTRIBUTE));
return factory.getBeanDefinition();
}
private static AbstractBeanDefinition getInlineShardingStrategyConfigBeanDefinition(final Element element) {
BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(InlineShardingStrategyConfiguration.class);
factory.addConstructorArgValue(element.getAttribute(ShardingJdbcStrategyBeanDefinitionParserTag.SHARDING_COLUMN_ATTRIBUTE));
factory.addConstructorArgValue(element.getAttribute(ShardingJdbcStrategyBeanDefinitionParserTag.ALGORITHM_EXPRESSION_ATTRIBUTE));
return factory.getBeanDefinition();
}
private static AbstractBeanDefinition getHintShardingStrategyConfigBeanDefinition(final Element element) {
BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(HintShardingStrategyConfiguration.class);
factory.addConstructorArgValue(element.getAttribute(ShardingJdbcStrategyBeanDefinitionParserTag.ALGORITHM_CLASS_ATTRIBUTE));
return factory.getBeanDefinition();
}
private static AbstractBeanDefinition getNoneShardingStrategyConfigBeanDefinition() {
return BeanDefinitionBuilder.rootBeanDefinition(NoneShardingStrategyConfiguration.class).getBeanDefinition();
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.parser;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
/**
* Sharding strategy bean parser for spring namespace.
* @author caohao
*/
public class ShardingStrategyBeanDefinitionParser extends AbstractBeanDefinitionParser {
@Override
protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext parserContext) {
return ShardingStrategyBeanDefinition.getBeanDefinitionByElement(element);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.namespace.parser;
import com.google.common.base.Strings;
import io.shardingjdbc.orchestration.reg.zookeeper.ZookeeperConfiguration;
import io.shardingjdbc.orchestration.reg.zookeeper.ZookeeperRegistryCenter;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
/**
* Zookeeper namespace parser for spring namespace.
*
* @author caohao
*/
public final class ZookeeperBeanDefinitionParser extends AbstractBeanDefinitionParser {
@Override
protected AbstractBeanDefinition parseInternal(final Element element, final ParserContext parserContext) {
BeanDefinitionBuilder result = BeanDefinitionBuilder.rootBeanDefinition(ZookeeperRegistryCenter.class);
result.addConstructorArgValue(buildZookeeperConfigurationBeanDefinition(element));
result.setInitMethodName("init");
return result.getBeanDefinition();
}
private AbstractBeanDefinition buildZookeeperConfigurationBeanDefinition(final Element element) {
BeanDefinitionBuilder configuration = BeanDefinitionBuilder.rootBeanDefinition(ZookeeperConfiguration.class);
configuration.addConstructorArgValue(element.getAttribute("server-lists"));
configuration.addConstructorArgValue(element.getAttribute("namespace"));
addPropertyValueIfNotEmpty("base-sleep-time-milliseconds", "baseSleepTimeMilliseconds", element, configuration);
addPropertyValueIfNotEmpty("max-sleep-time-milliseconds", "maxSleepTimeMilliseconds", element, configuration);
addPropertyValueIfNotEmpty("max-retries", "maxRetries", element, configuration);
addPropertyValueIfNotEmpty("session-timeout-milliseconds", "sessionTimeoutMilliseconds", element, configuration);
addPropertyValueIfNotEmpty("connection-timeout-milliseconds", "connectionTimeoutMilliseconds", element, configuration);
addPropertyValueIfNotEmpty("digest", "digest", element, configuration);
return configuration.getBeanDefinition();
}
private void addPropertyValueIfNotEmpty(final String attributeName, final String propertyName, final Element element, final BeanDefinitionBuilder factory) {
String attributeValue = element.getAttribute(attributeName);
if (!Strings.isNullOrEmpty(attributeValue)) {
factory.addPropertyValue(propertyName, attributeValue);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://shardingjdbc.io/schema/shardingjdbc/masterslave"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://shardingjdbc.io/schema/shardingjdbc/masterslave"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd"/>
<xsd:element name="data-source">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" use="required" />
<xsd:attribute name="master-data-source-name" type="xsd:string" use="required" />
<xsd:attribute name="slave-data-source-names" type="xsd:string" use="required" />
<xsd:attribute name="registry-center-ref" type="xsd:string" use="optional" />
<xsd:attribute name="strategy-ref" type="xsd:string" use="optional" />
<xsd:attribute name="strategy-type" type="xsd:string" use="optional" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.dangdang.com/schema/ddframe/reg"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.dangdang.com/schema/ddframe/reg"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:element name="zookeeper">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="server-lists" type="xsd:string" use="required" />
<xsd:attribute name="namespace" type="xsd:string" use="required" />
<xsd:attribute name="base-sleep-time-milliseconds" type="xsd:string" />
<xsd:attribute name="max-sleep-time-milliseconds" type="xsd:string" />
<xsd:attribute name="max-retries" type="xsd:string" />
<xsd:attribute name="session-timeout-milliseconds" type="xsd:string" />
<xsd:attribute name="connection-timeout-milliseconds" type="xsd:string" />
<xsd:attribute name="digest" type="xsd:string" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://shardingjdbc.io/schema/shardingjdbc/sharding"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd" />
<xsd:element name="data-source">
<xsd:complexType>
<xsd:all>
<xsd:element ref="sharding-rule" minOccurs="1" maxOccurs="1" />
<xsd:element ref="props" minOccurs="0" maxOccurs="1" />
</xsd:all>
<xsd:attribute name="id" type="xsd:string" use="required" />
<xsd:attribute name="registry-center-ref" type="xsd:string" use="optional" />
</xsd:complexType>
</xsd:element>
<xsd:element name="sharding-rule">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="table-rules" minOccurs="1" maxOccurs="1" />
<xsd:element ref="binding-table-rules" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
<xsd:attribute name="data-source-names" type="xsd:string" use="required" />
<xsd:attribute name="default-data-source-name" type="xsd:string" use="optional" />
<xsd:attribute name="default-database-strategy-ref" type="xsd:string" use="optional" />
<xsd:attribute name="default-table-strategy-ref" type="xsd:string" use="optional" />
<xsd:attribute name="key-generator-class" type="xsd:string" use="optional" />
</xsd:complexType>
</xsd:element>
<xsd:element name="table-rules">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="table-rule" minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="table-rule">
<xsd:complexType>
<xsd:attribute name="logic-table" type="xsd:string" use="required" />
<xsd:attribute name="actual-data-nodes" type="xsd:string" use="optional" />
<xsd:attribute name="database-strategy-ref" type="xsd:string" use="optional" />
<xsd:attribute name="table-strategy-ref" type="xsd:string" use="optional" />
<xsd:attribute name="generate-key-column" type="xsd:string" use="optional" />
<xsd:attribute name="column-key-generator-class" type="xsd:string" use="optional"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="binding-table-rules">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="binding-table-rule" minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="binding-table-rule">
<xsd:complexType>
<xsd:attribute name="logic-tables" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
<xsd:element name="standard-strategy">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" use="required" />
<xsd:attribute name="sharding-column" type="xsd:string" use="required" />
<xsd:attribute name="precise-algorithm-class" type="xsd:string" use="required" />
<xsd:attribute name="range-algorithm-class" type="xsd:string" use="optional" />
</xsd:complexType>
</xsd:element>
<xsd:element name="complex-strategy">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" use="required" />
<xsd:attribute name="sharding-columns" type="xsd:string" use="required" />
<xsd:attribute name="algorithm-class" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
<xsd:element name="inline-strategy">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" use="required" />
<xsd:attribute name="sharding-column" type="xsd:string" use="required" />
<xsd:attribute name="algorithm-expression" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
<xsd:element name="hint-strategy">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" use="required" />
<xsd:attribute name="algorithm-class" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
<xsd:element name="none-strategy">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
<xsd:element name="props">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:propsType" />
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
http\://shardingjdbc.io/schema/shardingjdbc/sharding=io.shardingjdbc.spring.namespace.handler.ShardingNamespaceHandler
http\://shardingjdbc.io/schema/shardingjdbc/masterslave=io.shardingjdbc.spring.namespace.handler.MasterSlaveNamespaceHandler
http\://shardingjdbc.io/schema/shardingjdbc/reg=io.shardingjdbc.spring.namespace.handler.RegNamespaceHandler
http\://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd=META-INF/namespace/sharding.xsd
http\://shardingjdbc.io/schema/shardingjdbc/masterslave/master-slave.xsd=META-INF/namespace/master-slave.xsd
http\://shardingjdbc.io/schema/shardingjdbc/reg/reg.xsd=META-INF/namespace/reg.xsd
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
public abstract class AbstractShardingBothDataBasesAndTablesSpringDBUnitTest extends AbstractSpringDBUnitTest {
@Test
public void testWithAllPlaceholders() throws SQLException {
insertData();
selectData();
}
private void insertData() throws SQLException {
String orderSql = "INSERT INTO `t_order` (`order_id`, `user_id`, `status`) VALUES (?, ?, ?)";
String orderItemSql = "INSERT INTO `t_order_item` (`order_item_id`, `order_id`, `user_id`, `status`) VALUES (?, ?, ?, ?)";
String configSql = "INSERT INTO `t_config` (`id`, `status`) VALUES (?, ?)";
for (int orderId = 1; orderId <= 4; orderId++) {
for (int userId = 1; userId <= 2; userId++) {
try (Connection connection = getShardingDataSource().getConnection()) {
PreparedStatement preparedStatement = connection.prepareStatement(orderSql);
preparedStatement.setInt(1, orderId);
preparedStatement.setInt(2, userId);
preparedStatement.setString(3, "insert");
preparedStatement.execute();
preparedStatement.close();
preparedStatement = connection.prepareStatement(orderItemSql);
preparedStatement.setInt(1, orderId);
preparedStatement.setInt(2, orderId);
preparedStatement.setInt(3, userId);
preparedStatement.setString(4, "insert");
preparedStatement.execute();
preparedStatement.close();
preparedStatement = connection.prepareStatement(orderItemSql);
preparedStatement.setInt(1, orderId + 4);
preparedStatement.setInt(2, orderId);
preparedStatement.setInt(3, userId);
preparedStatement.setString(4, "insert");
preparedStatement.execute();
preparedStatement.close();
preparedStatement = connection.prepareStatement(configSql);
preparedStatement.setInt(1, new Long(System.nanoTime()).intValue());
preparedStatement.setString(2, "insert");
preparedStatement.execute();
preparedStatement.close();
}
}
}
}
private void selectData() throws SQLException {
String sql = "SELECT i.order_id, i.order_item_id FROM `t_order` o JOIN `t_order_item` i ON o.user_id = i.user_id AND o.order_id = i.order_id"
+ " WHERE o.`user_id` = ? AND o.`order_id` = ? AND i.`order_id` = ? ORDER BY i.order_item_id DESC";
try (Connection connection = getShardingDataSource().getConnection()) {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 1);
preparedStatement.setInt(2, 1);
preparedStatement.setInt(3, 1);
ResultSet resultSet = preparedStatement.executeQuery();
int count = 0;
while (resultSet.next()) {
if (0 == count) {
assertThat(resultSet.getInt(1), is(1));
assertThat(resultSet.getInt(2), is(5));
} else if (1 == count) {
assertThat(resultSet.getInt(1), is(1));
assertThat(resultSet.getInt(2), is(1));
}
count++;
}
preparedStatement.close();
}
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring;
import io.shardingjdbc.core.jdbc.core.datasource.ShardingDataSource;
import lombok.Getter;
import org.apache.commons.dbcp.BasicDataSource;
import org.h2.tools.RunScript;
import org.junit.Before;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.File;
import java.io.InputStreamReader;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
@TestExecutionListeners(inheritListeners = false, listeners =
{DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class})
public abstract class AbstractSpringDBUnitTest extends AbstractJUnit4SpringContextTests {
@Resource
@Getter
private ShardingDataSource shardingDataSource;
private final ClassLoader classLoader = AbstractSpringDBUnitTest.class.getClassLoader();
@Before
public void createSchema() throws SQLException {
for (String each : getSchemaFiles()) {
RunScript.execute(createDataSource(each).getConnection(), new InputStreamReader(classLoader.getResourceAsStream(each)));
}
}
private DataSource createDataSource(final String dataSetFile) {
BasicDataSource result = new BasicDataSource();
result.setDriverClassName(org.h2.Driver.class.getName());
result.setUrl(String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL", getFileName(dataSetFile)));
result.setUsername("sa");
result.setPassword("");
result.setMaxActive(100);
return result;
}
private String getFileName(final String dataSetFile) {
String fileName = new File(dataSetFile).getName();
if (-1 == fileName.lastIndexOf('.')) {
return fileName;
}
return fileName.substring(0, fileName.lastIndexOf('.'));
}
protected List<String> getSchemaFiles() {
return Arrays.asList("schema/dbtbl_0.sql", "schema/dbtbl_1.sql");
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring;
import io.shardingjdbc.spring.cases.WithNamespaceAlgorithmClassTest;
import io.shardingjdbc.spring.cases.WithNamespaceAlgorithmExpressionTest;
import io.shardingjdbc.spring.cases.WithNamespaceBindingTablesTest;
import io.shardingjdbc.spring.cases.WithNamespaceDefaultStrategyTest;
import io.shardingjdbc.spring.cases.WithNamespaceDifferentTablesTest;
import io.shardingjdbc.spring.cases.WithNamespaceForMasterSlaveWithDefaultStrategyTest;
import io.shardingjdbc.spring.cases.WithNamespaceForMasterSlaveWithStrategyRefTest;
import io.shardingjdbc.spring.cases.WithNamespaceForMasterSlaveWithStrategyTypeTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
WithNamespaceAlgorithmClassTest.class,
WithNamespaceDifferentTablesTest.class,
WithNamespaceAlgorithmExpressionTest.class,
WithNamespaceDefaultStrategyTest.class,
WithNamespaceBindingTablesTest.class,
WithNamespaceDifferentTablesTest.class,
WithNamespaceForMasterSlaveWithDefaultStrategyTest.class,
WithNamespaceForMasterSlaveWithStrategyRefTest.class,
WithNamespaceForMasterSlaveWithStrategyTypeTest.class,
GenerateKeyDBUnitTest.class,
MasterSlaveNamespaceTest.class,
ShardingNamespaceTest.class
})
public class AllSpringTests {
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring;
import io.shardingjdbc.core.jdbc.core.datasource.ShardingDataSource;
import io.shardingjdbc.core.rule.TableRule;
import io.shardingjdbc.spring.fixture.DecrementKeyGenerator;
import io.shardingjdbc.spring.fixture.IncrementKeyGenerator;
import io.shardingjdbc.spring.util.FieldValueUtil;
import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.Iterator;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@ContextConfiguration(locations = "classpath:META-INF/rdb/withNamespaceGenerateKeyColumns.xml")
public class GenerateKeyDBUnitTest extends AbstractSpringDBUnitTest {
@Resource
private ShardingDataSource shardingDataSource;
@Test
public void assertGenerateKey() throws SQLException {
try (Connection connection = getShardingDataSource().getConnection();
Statement statement = connection.createStatement()) {
statement.execute("INSERT INTO `t_order` (`user_id`, `status`) VALUES (1, 'init')", Statement.RETURN_GENERATED_KEYS);
ResultSet generateKeyResultSet = statement.getGeneratedKeys();
assertTrue(generateKeyResultSet.next());
assertThat(generateKeyResultSet.getLong(1), is(101L));
statement.execute("INSERT INTO `t_order_item` (`order_id`, `user_id`, `status`) VALUES (101, 1, 'init')", Statement.RETURN_GENERATED_KEYS);
generateKeyResultSet = statement.getGeneratedKeys();
assertTrue(generateKeyResultSet.next());
assertThat(generateKeyResultSet.getLong(1), is(99L));
}
}
@SuppressWarnings("unchecked")
@Test
public void assertGenerateKeyColumn() {
Object shardingContext = FieldValueUtil.getFieldValue(shardingDataSource, "shardingContext", true);
assertNotNull(shardingContext);
Object shardingRule = FieldValueUtil.getFieldValue(shardingContext, "shardingRule");
assertNotNull(shardingRule);
Object defaultKeyGenerator = FieldValueUtil.getFieldValue(shardingRule, "defaultKeyGenerator");
assertNotNull(defaultKeyGenerator);
assertTrue(defaultKeyGenerator instanceof IncrementKeyGenerator);
Object tableRules = FieldValueUtil.getFieldValue(shardingRule, "tableRules");
assertNotNull(tableRules);
assertThat(((Collection<TableRule>) tableRules).size(), is(2));
Iterator<TableRule> tableRuleIterator = ((Collection<TableRule>) tableRules).iterator();
TableRule orderRule = tableRuleIterator.next();
assertThat(orderRule.getGenerateKeyColumn(), is("order_id"));
TableRule orderItemRule = tableRuleIterator.next();
assertThat(orderItemRule.getGenerateKeyColumn(), is("order_item_id"));
assertTrue(orderItemRule.getKeyGenerator() instanceof DecrementKeyGenerator);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring;
import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import io.shardingjdbc.core.api.algorithm.masterslave.MasterSlaveLoadBalanceAlgorithm;
import io.shardingjdbc.core.api.algorithm.masterslave.RandomMasterSlaveLoadBalanceAlgorithm;
import io.shardingjdbc.core.api.algorithm.masterslave.RoundRobinMasterSlaveLoadBalanceAlgorithm;
import io.shardingjdbc.core.jdbc.core.datasource.MasterSlaveDataSource;
import io.shardingjdbc.core.jdbc.core.datasource.ShardingDataSource;
import io.shardingjdbc.core.rule.MasterSlaveRule;
import io.shardingjdbc.core.rule.ShardingRule;
import io.shardingjdbc.spring.datasource.SpringMasterSlaveDataSource;
import io.shardingjdbc.spring.util.FieldValueUtil;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@ContextConfiguration(locations = "classpath:META-INF/rdb/masterSlaveNamespace.xml")
public class MasterSlaveNamespaceTest extends AbstractJUnit4SpringContextTests {
@Test
public void testDefaultMaserSlaveDataSource() {
MasterSlaveRule masterSlaveRule = getMasterSlaveRule("defaultMasterSlaveDataSource");
assertThat(masterSlaveRule.getMasterDataSourceName(), is("dbtbl_0_master"));
assertNotNull(masterSlaveRule.getSlaveDataSourceMap().get("dbtbl_0_slave_0"));
assertNotNull(masterSlaveRule.getSlaveDataSourceMap().get("dbtbl_0_slave_1"));
}
@Test
public void testTypeMasterSlaveDataSource() {
MasterSlaveRule randomSlaveRule = getMasterSlaveRule("randomMasterSlaveDataSource");
MasterSlaveRule roundRobinSlaveRule = getMasterSlaveRule("roundRobinMasterSlaveDataSource");
assertTrue(randomSlaveRule.getStrategy() instanceof RandomMasterSlaveLoadBalanceAlgorithm);
assertTrue(roundRobinSlaveRule.getStrategy() instanceof RoundRobinMasterSlaveLoadBalanceAlgorithm);
}
@Test
public void testRefMasterSlaveDataSource() {
MasterSlaveLoadBalanceAlgorithm randomStrategy = this.applicationContext.getBean("randomStrategy", MasterSlaveLoadBalanceAlgorithm.class);
MasterSlaveRule masterSlaveRule = getMasterSlaveRule("refMasterSlaveDataSource");
assertTrue(masterSlaveRule.getStrategy() == randomStrategy);
}
@Test
public void testDefaultShardingDataSource() {
ShardingRule shardingRule = getShardingRule("defaultShardingDataSource");
assertNotNull(shardingRule.getDataSourceMap().get("randomMasterSlaveDataSource"));
assertNotNull(shardingRule.getDataSourceMap().get("refMasterSlaveDataSource"));
assertThat(shardingRule.getDefaultDataSourceName(), is("randomMasterSlaveDataSource"));
assertThat(shardingRule.getTableRules().size(), is(1));
assertThat(shardingRule.getTableRules().iterator().next().getLogicTable(), is("t_order"));
}
@Test
public void testShardingDataSourceType() {
assertTrue(this.applicationContext.getBean("defaultMasterSlaveDataSource", MasterSlaveDataSource.class) instanceof SpringMasterSlaveDataSource);
}
private ShardingRule getShardingRule(final String shardingDataSourceName) {
ShardingDataSource shardingDataSource = this.applicationContext.getBean(shardingDataSourceName, ShardingDataSource.class);
Object shardingContext = FieldValueUtil.getFieldValue(shardingDataSource, "shardingContext", true);
return (ShardingRule) FieldValueUtil.getFieldValue(shardingContext, "shardingRule");
}
private MasterSlaveRule getMasterSlaveRule(final String masterSlaveDataSourceName) {
MasterSlaveDataSource masterSlaveDataSource = this.applicationContext.getBean(masterSlaveDataSourceName, MasterSlaveDataSource.class);
return (MasterSlaveRule) FieldValueUtil.getFieldValue(masterSlaveDataSource, "masterSlaveRule", true);
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring;
import io.shardingjdbc.core.api.config.strategy.ComplexShardingStrategyConfiguration;
import io.shardingjdbc.core.api.config.strategy.HintShardingStrategyConfiguration;
import io.shardingjdbc.core.api.config.strategy.InlineShardingStrategyConfiguration;
import io.shardingjdbc.core.api.config.strategy.NoneShardingStrategyConfiguration;
import io.shardingjdbc.core.api.config.strategy.StandardShardingStrategyConfiguration;
import io.shardingjdbc.core.constant.ShardingProperties;
import io.shardingjdbc.core.constant.ShardingPropertiesConstant;
import io.shardingjdbc.core.jdbc.core.datasource.ShardingDataSource;
import io.shardingjdbc.core.rule.BindingTableRule;
import io.shardingjdbc.core.rule.DataNode;
import io.shardingjdbc.core.rule.ShardingRule;
import io.shardingjdbc.core.rule.TableRule;
import io.shardingjdbc.spring.datasource.SpringShardingDataSource;
import io.shardingjdbc.spring.util.FieldValueUtil;
import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import java.util.Arrays;
import java.util.Iterator;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@ContextConfiguration(locations = "classpath:META-INF/rdb/shardingNamespace.xml")
public class ShardingNamespaceTest extends AbstractJUnit4SpringContextTests {
@Test
public void testStandardStrategy() {
StandardShardingStrategyConfiguration standardStrategy = this.applicationContext.getBean("standardStrategy", StandardShardingStrategyConfiguration.class);
assertThat(standardStrategy.getShardingColumn(), is("user_id"));
assertThat(standardStrategy.getPreciseAlgorithmClassName(), is("io.shardingjdbc.spring.algorithm.PreciseModuloDatabaseShardingAlgorithm"));
}
@Test
public void testRangeStandardStrategy() {
StandardShardingStrategyConfiguration rangeStandardStrategy = this.applicationContext.getBean("rangeStandardStrategy", StandardShardingStrategyConfiguration.class);
assertThat(rangeStandardStrategy.getShardingColumn(), is("order_id"));
assertThat(rangeStandardStrategy.getPreciseAlgorithmClassName(), is("io.shardingjdbc.spring.algorithm.PreciseModuloTableShardingAlgorithm"));
assertThat(rangeStandardStrategy.getRangeAlgorithmClassName(), is("io.shardingjdbc.spring.algorithm.RangeModuloTableShardingAlgorithm"));
}
@Test
public void testComplexStrategy() {
ComplexShardingStrategyConfiguration complexStrategy = this.applicationContext.getBean("complexStrategy", ComplexShardingStrategyConfiguration.class);
assertThat(complexStrategy.getShardingColumns(), is("order_id,user_id"));
assertThat(complexStrategy.getAlgorithmClassName(), is("io.shardingjdbc.spring.algorithm.DefaultComplexKeysShardingAlgorithm"));
}
@Test
public void testInlineStrategy() {
InlineShardingStrategyConfiguration inlineStrategy = this.applicationContext.getBean("inlineStrategy", InlineShardingStrategyConfiguration.class);
assertThat(inlineStrategy.getShardingColumn(), is("order_id"));
assertThat(inlineStrategy.getAlgorithmExpression(), is("t_order_${order_id % 4}"));
}
@Test
public void testHintStrategy() {
HintShardingStrategyConfiguration hintStrategy = this.applicationContext.getBean("hintStrategy", HintShardingStrategyConfiguration.class);
assertThat(hintStrategy.getAlgorithmClassName(), is("io.shardingjdbc.spring.algorithm.DefaultHintShardingAlgorithm"));
}
@Test
public void testNoneStrategy() {
this.applicationContext.getBean("noneStrategy", NoneShardingStrategyConfiguration.class);
}
@Test
public void testSimpleShardingDataSource() {
ShardingRule shardingRule = getShardingRule("simpleShardingDataSource");
assertNotNull(shardingRule.getDataSourceMap().get("dbtbl_0"));
assertThat(shardingRule.getTableRules().size(), is(1));
assertThat(shardingRule.getTableRules().iterator().next().getLogicTable(), is("t_order"));
}
@Test
public void testShardingRuleWithAttributesDataSource() {
ShardingRule shardingRule = getShardingRule("shardingRuleWithAttributesDataSource");
assertNotNull(shardingRule.getDataSourceMap().get("dbtbl_0"));
assertNotNull(shardingRule.getDataSourceMap().get("dbtbl_1"));
assertThat(shardingRule.getDefaultDataSourceName(), is("dbtbl_0"));
assertTrue(Arrays.equals(shardingRule.getDefaultDatabaseShardingStrategy().getShardingColumns().toArray(new String[]{}),
new String[]{this.applicationContext.getBean("standardStrategy", StandardShardingStrategyConfiguration.class).getShardingColumn()}));
assertTrue(Arrays.equals(shardingRule.getDefaultTableShardingStrategy().getShardingColumns().toArray(new String[]{}),
new String[]{this.applicationContext.getBean("inlineStrategy", InlineShardingStrategyConfiguration.class).getShardingColumn()}));
assertThat(shardingRule.getDefaultKeyGenerator().getClass().getName(), is("io.shardingjdbc.spring.fixture.IncrementKeyGenerator"));
}
@Test
public void testTableRuleWithAttributesDataSource() {
ShardingRule shardingRule = getShardingRule("tableRuleWithAttributesDataSource");
assertThat(shardingRule.getTableRules().size(), is(1));
TableRule tableRule = shardingRule.getTableRules().iterator().next();
assertThat(tableRule.getLogicTable(), is("t_order"));
assertThat(tableRule.getActualDataNodes().size(), is(8));
assertTrue(tableRule.getActualDataNodes().contains(new DataNode("dbtbl_0", "t_order_0")));
assertTrue(tableRule.getActualDataNodes().contains(new DataNode("dbtbl_0", "t_order_1")));
assertTrue(tableRule.getActualDataNodes().contains(new DataNode("dbtbl_0", "t_order_2")));
assertTrue(tableRule.getActualDataNodes().contains(new DataNode("dbtbl_0", "t_order_3")));
assertTrue(tableRule.getActualDataNodes().contains(new DataNode("dbtbl_1", "t_order_0")));
assertTrue(tableRule.getActualDataNodes().contains(new DataNode("dbtbl_1", "t_order_1")));
assertTrue(tableRule.getActualDataNodes().contains(new DataNode("dbtbl_1", "t_order_2")));
assertTrue(tableRule.getActualDataNodes().contains(new DataNode("dbtbl_1", "t_order_3")));
assertTrue(Arrays.equals(tableRule.getDatabaseShardingStrategy().getShardingColumns().toArray(new String[]{}),
new String[]{this.applicationContext.getBean("standardStrategy", StandardShardingStrategyConfiguration.class).getShardingColumn()}));
assertTrue(Arrays.equals(tableRule.getTableShardingStrategy().getShardingColumns().toArray(new String[]{}),
new String[]{this.applicationContext.getBean("inlineStrategy", InlineShardingStrategyConfiguration.class).getShardingColumn()}));
assertThat(tableRule.getGenerateKeyColumn(), is("order_id"));
assertThat(tableRule.getKeyGenerator().getClass().getName(), is("io.shardingjdbc.spring.fixture.IncrementKeyGenerator"));
}
@Test
public void testMultiTableRulesDataSource() {
ShardingRule shardingRule = getShardingRule("multiTableRulesDataSource");
assertThat(shardingRule.getTableRules().size(), is(2));
Iterator<TableRule> iter = shardingRule.getTableRules().iterator();
assertThat(iter.next().getLogicTable(), is("t_order"));
assertThat(iter.next().getLogicTable(), is("t_order_item"));
}
@Test
public void testBindingTableRuleDatasource() {
ShardingRule shardingRule = getShardingRule("bindingTableRuleDatasource");
assertThat(shardingRule.getBindingTableRules().size(), is(1));
BindingTableRule bindingTableRule = shardingRule.getBindingTableRules().iterator().next();
assertThat(bindingTableRule.getBindingActualTable("dbtbl_0", "t_order", "t_order_item"), is("t_order"));
assertThat(bindingTableRule.getBindingActualTable("dbtbl_1", "t_order", "t_order_item"), is("t_order"));
}
@Test
public void testMultiBindingTableRulesDatasource() {
ShardingRule shardingRule = getShardingRule("multiBindingTableRulesDatasource");
assertThat(shardingRule.getBindingTableRules().size(), is(2));
Iterator<BindingTableRule> iter = shardingRule.getBindingTableRules().iterator();
BindingTableRule orderRule = iter.next();
assertThat(orderRule.getBindingActualTable("dbtbl_0", "t_order", "t_order_item"), is("t_order"));
assertThat(orderRule.getBindingActualTable("dbtbl_1", "t_order", "t_order_item"), is("t_order"));
BindingTableRule userRule = iter.next();
assertThat(userRule.getBindingActualTable("dbtbl_0", "t_user", "t_user_detail"), is("t_user"));
assertThat(userRule.getBindingActualTable("dbtbl_1", "t_user", "t_user_detail"), is("t_user"));
}
@Test
public void testPropsDataSource() {
ShardingDataSource shardingDataSource = this.applicationContext.getBean("propsDataSource", ShardingDataSource.class);
Object shardingContext = FieldValueUtil.getFieldValue(shardingDataSource, "shardingContext", true);
assertTrue((boolean) FieldValueUtil.getFieldValue(shardingContext, "showSQL"));
ShardingProperties shardingProperties = (ShardingProperties) FieldValueUtil.getFieldValue(shardingDataSource, "shardingProperties", true);
boolean showSql = shardingProperties.getValue(ShardingPropertiesConstant.SQL_SHOW);
assertTrue(showSql);
int executorSize = shardingProperties.getValue(ShardingPropertiesConstant.EXECUTOR_SIZE);
assertThat(executorSize, is(10));
assertNull(ShardingPropertiesConstant.findByKey("foo"));
}
@Test
public void testShardingDataSourceType() {
assertTrue(this.applicationContext.getBean("simpleShardingDataSource", ShardingDataSource.class) instanceof SpringShardingDataSource);
}
@Test
public void testDefaultActualDataNodes() {
ShardingDataSource multiTableRulesDataSource = this.applicationContext.getBean("multiTableRulesDataSource", ShardingDataSource.class);
Object shardingContext = FieldValueUtil.getFieldValue(multiTableRulesDataSource, "shardingContext", true);
ShardingRule shardingRule = (ShardingRule) FieldValueUtil.getFieldValue(shardingContext, "shardingRule");
assertThat(shardingRule.getTableRules().size(), is(2));
Iterator<TableRule> iter = shardingRule.getTableRules().iterator();
TableRule orderRule = iter.next();
assertThat(orderRule.getActualDataNodes().size(), is(2));
assertTrue(orderRule.getActualDataNodes().contains(new DataNode("dbtbl_0", "t_order")));
assertTrue(orderRule.getActualDataNodes().contains(new DataNode("dbtbl_1", "t_order")));
TableRule orderItemRule = iter.next();
assertThat(orderItemRule.getActualDataNodes().size(), is(2));
assertTrue(orderItemRule.getActualDataNodes().contains(new DataNode("dbtbl_0", "t_order_item")));
assertTrue(orderItemRule.getActualDataNodes().contains(new DataNode("dbtbl_1", "t_order_item")));
}
private ShardingRule getShardingRule(final String shardingDataSourceName) {
ShardingDataSource shardingDataSource = this.applicationContext.getBean(shardingDataSourceName, ShardingDataSource.class);
Object shardingContext = FieldValueUtil.getFieldValue(shardingDataSource, "shardingContext", true);
return (ShardingRule) FieldValueUtil.getFieldValue(shardingContext, "shardingRule");
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.algorithm;
import java.util.Collection;
import io.shardingjdbc.core.api.algorithm.sharding.ShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.complex.ComplexKeysShardingAlgorithm;
public class DefaultComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm {
@Override
public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<ShardingValue> shardingValues) {
return availableTargetNames;
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.algorithm;
import java.util.Collection;
import io.shardingjdbc.core.api.algorithm.sharding.ShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.hint.HintShardingAlgorithm;
public class DefaultHintShardingAlgorithm implements HintShardingAlgorithm {
@Override
public Collection<String> doSharding(final Collection<String> availableTargetNames, final ShardingValue shardingValue) {
return availableTargetNames;
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.algorithm;
import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
import java.util.Collection;
public class PreciseModuloDatabaseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
@Override
public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Integer> shardingValue) {
for (String each : availableTargetNames) {
if (each.endsWith(shardingValue.getValue() % 2 + "")) {
return each;
}
}
throw new UnsupportedOperationException();
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.algorithm;
import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
import java.util.Collection;
public class PreciseModuloTableShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
@Override
public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Integer> shardingValue) {
for (String each : availableTargetNames) {
if (each.endsWith(shardingValue.getValue() % 4 + "")) {
return each;
}
}
throw new UnsupportedOperationException();
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.algorithm;
import io.shardingjdbc.core.api.algorithm.sharding.RangeShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.standard.RangeShardingAlgorithm;
import com.google.common.collect.Range;
import java.util.Collection;
import java.util.LinkedHashSet;
public class RangeModuloDatabaseShardingAlgorithm implements RangeShardingAlgorithm<Integer> {
@Override
public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Integer> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
Range<Integer> range = shardingValue.getValueRange();
for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
for (String each : availableTargetNames) {
if (each.endsWith(i % 2 + "")) {
result.add(each);
}
}
}
return result;
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.algorithm;
import io.shardingjdbc.core.api.algorithm.sharding.RangeShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.standard.RangeShardingAlgorithm;
import com.google.common.collect.Range;
import java.util.Collection;
import java.util.LinkedHashSet;
public class RangeModuloTableShardingAlgorithm implements RangeShardingAlgorithm<Integer> {
@Override
public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Integer> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
Range<Integer> range = shardingValue.getValueRange();
for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
for (String each : availableTargetNames) {
if (each.endsWith(i % 4 + "")) {
result.add(each);
}
}
}
return result;
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.cases;
import io.shardingjdbc.spring.AbstractShardingBothDataBasesAndTablesSpringDBUnitTest;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(locations = "classpath:META-INF/rdb/withNamespaceAlgorithmClass.xml")
public final class WithNamespaceAlgorithmClassTest extends AbstractShardingBothDataBasesAndTablesSpringDBUnitTest {
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.cases;
import io.shardingjdbc.spring.AbstractShardingBothDataBasesAndTablesSpringDBUnitTest;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(locations = "classpath:META-INF/rdb/withNamespaceAlgorithmExpression.xml")
public final class WithNamespaceAlgorithmExpressionTest extends AbstractShardingBothDataBasesAndTablesSpringDBUnitTest {
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.cases;
import io.shardingjdbc.spring.AbstractShardingBothDataBasesAndTablesSpringDBUnitTest;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(locations = "classpath:META-INF/rdb/withNamespaceBindingTables.xml")
public final class WithNamespaceBindingTablesTest extends AbstractShardingBothDataBasesAndTablesSpringDBUnitTest {
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.cases;
import io.shardingjdbc.spring.AbstractShardingBothDataBasesAndTablesSpringDBUnitTest;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(locations = "classpath:META-INF/rdb/withNamespaceDefaultStrategy.xml")
public final class WithNamespaceDefaultStrategyTest extends AbstractShardingBothDataBasesAndTablesSpringDBUnitTest {
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.cases;
import io.shardingjdbc.spring.AbstractShardingBothDataBasesAndTablesSpringDBUnitTest;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(locations = "classpath:META-INF/rdb/withNamespaceDifferentTables.xml")
public final class WithNamespaceDifferentTablesTest extends AbstractShardingBothDataBasesAndTablesSpringDBUnitTest {
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.cases;
import io.shardingjdbc.spring.AbstractShardingBothDataBasesAndTablesSpringDBUnitTest;
import java.util.Arrays;
import java.util.List;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration(locations = "classpath:META-INF/rdb/withNamespaceForMasterSlaveWithDefaultStrategy.xml")
public final class WithNamespaceForMasterSlaveWithDefaultStrategyTest extends AbstractShardingBothDataBasesAndTablesSpringDBUnitTest {
@Override
protected List<String> getSchemaFiles() {
return Arrays.asList("schema/dbtbl_0_master.sql", "schema/dbtbl_0_slave_0.sql", "schema/dbtbl_0_slave_1.sql",
"schema/dbtbl_1_master.sql", "schema/dbtbl_1_slave_0.sql", "schema/dbtbl_1_slave_1.sql");
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.cases;
import io.shardingjdbc.spring.AbstractShardingBothDataBasesAndTablesSpringDBUnitTest;
import org.springframework.test.context.ContextConfiguration;
import java.util.Arrays;
import java.util.List;
@ContextConfiguration(locations = "classpath:META-INF/rdb/withNamespaceForMasterSlaveWithStrategyRef.xml")
public final class WithNamespaceForMasterSlaveWithStrategyRefTest extends AbstractShardingBothDataBasesAndTablesSpringDBUnitTest {
@Override
protected List<String> getSchemaFiles() {
return Arrays.asList("schema/dbtbl_0_master.sql", "schema/dbtbl_0_slave_0.sql", "schema/dbtbl_0_slave_1.sql",
"schema/dbtbl_1_master.sql", "schema/dbtbl_1_slave_0.sql", "schema/dbtbl_1_slave_1.sql");
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.cases;
import io.shardingjdbc.spring.AbstractShardingBothDataBasesAndTablesSpringDBUnitTest;
import org.springframework.test.context.ContextConfiguration;
import java.util.Arrays;
import java.util.List;
@ContextConfiguration(locations = "classpath:META-INF/rdb/withNamespaceForMasterSlaveWithStrategyType.xml")
public final class WithNamespaceForMasterSlaveWithStrategyTypeTest extends AbstractShardingBothDataBasesAndTablesSpringDBUnitTest {
@Override
protected List<String> getSchemaFiles() {
return Arrays.asList("schema/dbtbl_0_master.sql", "schema/dbtbl_0_slave_0.sql", "schema/dbtbl_0_slave_1.sql",
"schema/dbtbl_1_master.sql", "schema/dbtbl_1_slave_0.sql", "schema/dbtbl_1_slave_1.sql");
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.fixture;
import io.shardingjdbc.core.keygen.KeyGenerator;
import java.util.concurrent.atomic.AtomicInteger;
public final class DecrementKeyGenerator implements KeyGenerator {
private final AtomicInteger sequence = new AtomicInteger(100);
@Override
public Number generateKey() {
return sequence.decrementAndGet();
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.fixture;
import io.shardingjdbc.core.keygen.KeyGenerator;
import java.util.concurrent.atomic.AtomicInteger;
public final class IncrementKeyGenerator implements KeyGenerator {
private final AtomicInteger sequence = new AtomicInteger(100);
@Override
public Number generateKey() {
return sequence.incrementAndGet();
}
}
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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.
* </p>
*/
package io.shardingjdbc.spring.util;
import com.google.common.base.Strings;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.lang.reflect.Field;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class FieldValueUtil {
private static Object getFieldValue(final Class<?> clazz, final Object obj, final String fieldName) {
try {
Field field = clazz.getDeclaredField(fieldName);
if (!field.isAccessible()) {
field.setAccessible(true);
}
return field.get(obj);
} catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
public static Object getFieldValue(final Object obj, final String fieldName, final boolean fromSuperclass) {
if (null == obj || Strings.isNullOrEmpty(fieldName)) {
return null;
}
Class<?> clazz = fromSuperclass ? obj.getClass().getSuperclass() : obj.getClass();
return getFieldValue(clazz, obj, fieldName);
}
public static Object getFieldValue(final Object obj, final String fieldName) {
return getFieldValue(obj, fieldName, false);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<context:property-placeholder location="classpath:conf/rdb/conf.properties" ignore-unresolvable="true" />
<bean id="dbtbl_0" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${dbtbl_0.driver}" />
<property name="url" value="${dbtbl_0.url}" />
<property name="username" value="${dbtbl_0.username}" />
<property name="password" value="${dbtbl_0.password}" />
</bean>
<bean id="dbtbl_1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${dbtbl_1.driver}" />
<property name="url" value="${dbtbl_1.url}" />
<property name="username" value="${dbtbl_1.username}" />
<property name="password" value="${dbtbl_1.password}" />
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<context:property-placeholder location="classpath:conf/rdb/master_slave_conf.properties" ignore-unresolvable="true"/>
<bean id="dbtbl_0_master" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${dbtbl_0_master.driver}"/>
<property name="url" value="${dbtbl_0_master.url}"/>
<property name="username" value="${dbtbl_0_master.username}"/>
<property name="password" value="${dbtbl_0_master.password}"/>
</bean>
<bean id="dbtbl_0_slave_0" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${dbtbl_0_slave_0.driver}"/>
<property name="url" value="${dbtbl_0_slave_0.url}"/>
<property name="username" value="${dbtbl_0_slave_0.username}"/>
<property name="password" value="${dbtbl_0_slave_0.password}"/>
</bean>
<bean id="dbtbl_0_slave_1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${dbtbl_0_slave_1.driver}"/>
<property name="url" value="${dbtbl_0_slave_1.url}"/>
<property name="username" value="${dbtbl_0_slave_1.username}"/>
<property name="password" value="${dbtbl_0_slave_1.password}"/>
</bean>
<bean id="dbtbl_1_master" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${dbtbl_0_master.driver}"/>
<property name="url" value="${dbtbl_1_master.url}"/>
<property name="username" value="${dbtbl_1_master.username}"/>
<property name="password" value="${dbtbl_1_master.password}"/>
</bean>
<bean id="dbtbl_1_slave_0" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${dbtbl_0_slave_0.driver}"/>
<property name="url" value="${dbtbl_1_slave_0.url}"/>
<property name="username" value="${dbtbl_1_slave_0.username}"/>
<property name="password" value="${dbtbl_1_slave_0.password}"/>
</bean>
<bean id="dbtbl_1_slave_1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${dbtbl_1_slave_1.driver}"/>
<property name="url" value="${dbtbl_1_slave_1.url}"/>
<property name="username" value="${dbtbl_1_slave_1.username}"/>
<property name="password" value="${dbtbl_1_slave_1.password}"/>
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xmlns:master-slave="http://shardingjdbc.io/schema/shardingjdbc/masterslave"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
http://shardingjdbc.io/schema/shardingjdbc/masterslave
http://shardingjdbc.io/schema/shardingjdbc/masterslave/master-slave.xsd
">
<import resource="datasource/masterSlaveDataSource.xml" />
<bean id="randomStrategy" class="io.shardingjdbc.core.api.algorithm.masterslave.RandomMasterSlaveLoadBalanceAlgorithm" />
<master-slave:data-source id="defaultMasterSlaveDataSource" master-data-source-name="dbtbl_0_master" slave-data-source-names="dbtbl_0_slave_0, dbtbl_0_slave_1" />
<master-slave:data-source id="randomMasterSlaveDataSource" master-data-source-name="dbtbl_0_master" slave-data-source-names="dbtbl_0_slave_0, dbtbl_0_slave_1" strategy-type="RANDOM" />
<master-slave:data-source id="roundRobinMasterSlaveDataSource" master-data-source-name="dbtbl_0_master" slave-data-source-names="dbtbl_0_slave_0, dbtbl_0_slave_1" strategy-type="ROUND_ROBIN" />
<master-slave:data-source id="refMasterSlaveDataSource" master-data-source-name="dbtbl_1_master" slave-data-source-names="dbtbl_1_slave_0, dbtbl_1_slave_1" strategy-ref="randomStrategy" />
<sharding:data-source id="defaultShardingDataSource">
<sharding:sharding-rule data-source-names="randomMasterSlaveDataSource,refMasterSlaveDataSource" default-data-source-name="randomMasterSlaveDataSource">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
">
<import resource="datasource/dataSource.xml" />
<sharding:standard-strategy id="standardStrategy" sharding-column="user_id"
precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloDatabaseShardingAlgorithm" />
<sharding:standard-strategy id="rangeStandardStrategy" sharding-column="order_id"
precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloTableShardingAlgorithm"
range-algorithm-class="io.shardingjdbc.spring.algorithm.RangeModuloTableShardingAlgorithm"/>
<sharding:complex-strategy id="complexStrategy" sharding-columns="order_id,user_id"
algorithm-class="io.shardingjdbc.spring.algorithm.DefaultComplexKeysShardingAlgorithm"/>
<sharding:inline-strategy id="inlineStrategy" sharding-column="order_id" algorithm-expression="t_order_${order_id % 4}" />
<sharding:hint-strategy id="hintStrategy" algorithm-class="io.shardingjdbc.spring.algorithm.DefaultHintShardingAlgorithm" />
<sharding:none-strategy id="noneStrategy" />
<sharding:data-source id="simpleShardingDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
<sharding:data-source id="shardingRuleWithAttributesDataSource">
<sharding:sharding-rule
data-source-names="dbtbl_0,dbtbl_1"
default-data-source-name="dbtbl_0"
default-database-strategy-ref="standardStrategy"
default-table-strategy-ref="inlineStrategy"
key-generator-class="io.shardingjdbc.spring.fixture.IncrementKeyGenerator">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
<sharding:data-source id="tableRuleWithAttributesDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_${0..1}.t_order_${0..3}" database-strategy-ref="standardStrategy" table-strategy-ref="inlineStrategy" generate-key-column="order_id" column-key-generator-class="io.shardingjdbc.spring.fixture.IncrementKeyGenerator" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
<sharding:data-source id="multiTableRulesDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" />
<sharding:table-rule logic-table="t_order_item" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
<sharding:data-source id="bindingTableRuleDatasource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" >
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" />
<sharding:table-rule logic-table="t_order_item" />
</sharding:table-rules>
<sharding:binding-table-rules>
<sharding:binding-table-rule logic-tables="t_order, t_order_item" />
</sharding:binding-table-rules>
</sharding:sharding-rule>
</sharding:data-source>
<sharding:data-source id="multiBindingTableRulesDatasource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" >
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" />
<sharding:table-rule logic-table="t_order_item" />
<sharding:table-rule logic-table="t_user" />
<sharding:table-rule logic-table="t_user_detail" />
</sharding:table-rules>
<sharding:binding-table-rules>
<sharding:binding-table-rule logic-tables="t_order, t_order_item" />
<sharding:binding-table-rule logic-tables="t_user, t_user_detail" />
</sharding:binding-table-rules>
</sharding:sharding-rule>
</sharding:data-source>
<sharding:data-source id="propsDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" />
</sharding:table-rules>
</sharding:sharding-rule>
<sharding:props>
<prop key="sql.show">${sql_show}</prop>
<prop key="executor.size">10</prop>
<prop key="foo">bar</prop>
</sharding:props>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
">
<import resource="datasource/dataSource.xml" />
<sharding:standard-strategy id="databaseStrategy" sharding-column="user_id" precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloDatabaseShardingAlgorithm" />
<sharding:standard-strategy id="tableStrategy" sharding-column="order_id" precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloTableShardingAlgorithm" />
<sharding:data-source id="shardingDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" default-data-source-name="dbtbl_0">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_${0..1}.t_order_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="tableStrategy" />
<sharding:table-rule logic-table="t_order_item" actual-data-nodes="dbtbl_${0..1}.t_order_item_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="tableStrategy" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
">
<import resource="datasource/dataSource.xml" />
<sharding:standard-strategy id="databaseStrategy" sharding-column="user_id" precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloDatabaseShardingAlgorithm" />
<sharding:standard-strategy id="tableStrategy" sharding-column="order_id" precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloTableShardingAlgorithm" />
<sharding:data-source id="shardingDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" default-data-source-name="dbtbl_0">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_${0..1}.t_order_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="tableStrategy" />
<sharding:table-rule logic-table="t_order_item" actual-data-nodes="dbtbl_${0..1}.t_order_item_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="tableStrategy" />
</sharding:table-rules>
</sharding:sharding-rule>
<sharding:props>
<prop key="sql.show">${sql_show}</prop>
</sharding:props>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
">
<import resource="datasource/dataSource.xml" />
<sharding:inline-strategy id="databaseStrategy" sharding-column="user_id" algorithm-expression="dbtbl_${user_id % 2}" />
<sharding:inline-strategy id="orderTableStrategy" sharding-column="order_id" algorithm-expression="t_order_${order_id % 4}" />
<sharding:inline-strategy id="orderItemTableStrategy" sharding-column="order_id" algorithm-expression="t_order_item_${order_id % 4}" />
<sharding:data-source id="shardingDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" default-data-source-name="dbtbl_0">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_${0..1}.t_order_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="orderTableStrategy" />
<sharding:table-rule logic-table="t_order_item" actual-data-nodes="dbtbl_${0..1}.t_order_item_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="orderItemTableStrategy" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
">
<import resource="datasource/dataSource.xml" />
<sharding:standard-strategy id="databaseStrategy" sharding-column="user_id" precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloDatabaseShardingAlgorithm" />
<sharding:standard-strategy id="tableStrategy" sharding-column="order_id" precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloTableShardingAlgorithm" />
<sharding:data-source id="shardingDatasource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" default-data-source-name="dbtbl_0">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_${0..1}.t_order_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="tableStrategy" />
<sharding:table-rule logic-table="t_order_item" actual-data-nodes="dbtbl_${0..1}.t_order_item_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="tableStrategy" />
</sharding:table-rules>
<sharding:binding-table-rules>
<sharding:binding-table-rule logic-tables="t_order, t_order_item" />
</sharding:binding-table-rules>
</sharding:sharding-rule>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
">
<import resource="datasource/dataSource.xml" />
<sharding:standard-strategy id="databaseStrategy" sharding-column="user_id" precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloDatabaseShardingAlgorithm" />
<sharding:standard-strategy id="tableStrategy" sharding-column="order_id" precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloTableShardingAlgorithm" />
<sharding:data-source id="shardingDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" default-data-source-name="dbtbl_0" default-database-strategy-ref="databaseStrategy" default-table-strategy-ref="tableStrategy">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_${0..1}.t_order_${0..3}" />
<sharding:table-rule logic-table="t_order_item" actual-data-nodes="dbtbl_${0..1}.t_order_item_${0..3}" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
">
<import resource="datasource/dataSource.xml" />
<sharding:inline-strategy id="databaseStrategy" sharding-column="user_id" algorithm-expression="dbtbl_${user_id % 2}" />
<sharding:inline-strategy id="orderTableStrategy" sharding-column="order_id" algorithm-expression="t_order_${order_id % 4}" />
<sharding:inline-strategy id="orderItemTableStrategy" sharding-column="order_id" algorithm-expression="t_order_item_${order_id % 4}" />
<sharding:data-source id="shardingDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" default-data-source-name="dbtbl_0">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_0.t_order_${0..3}, dbtbl_1.t_order_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="orderTableStrategy" />
<sharding:table-rule logic-table="t_order_item" actual-data-nodes="dbtbl_0.t_order_item_${0..3}, dbtbl_1.t_order_item_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="orderItemTableStrategy" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xmlns:master-slave="http://shardingjdbc.io/schema/shardingjdbc/masterslave"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
http://shardingjdbc.io/schema/shardingjdbc/masterslave
http://shardingjdbc.io/schema/shardingjdbc/masterslave/master-slave.xsd
">
<import resource="datasource/masterSlaveDataSource.xml" />
<master-slave:data-source id="dbtbl_0" master-data-source-name="dbtbl_0_master" slave-data-source-names="dbtbl_0_slave_0, dbtbl_0_slave_1" />
<master-slave:data-source id="dbtbl_1" master-data-source-name="dbtbl_1_master" slave-data-source-names="dbtbl_1_slave_0, dbtbl_1_slave_1" />
<sharding:inline-strategy id="databaseStrategy" sharding-column="user_id" algorithm-expression="dbtbl_${user_id % 2}" />
<sharding:inline-strategy id="orderTableStrategy" sharding-column="order_id" algorithm-expression="t_order_${order_id % 4}" />
<sharding:inline-strategy id="orderItemTableStrategy" sharding-column="order_id" algorithm-expression="t_order_item_${order_id % 4}" />
<sharding:data-source id="shardingDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" default-data-source-name="dbtbl_0">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_${0..1}.t_order_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="orderTableStrategy" />
<sharding:table-rule logic-table="t_order_item" actual-data-nodes="dbtbl_${0..1}.t_order_item_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="orderItemTableStrategy" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xmlns:master-slave="http://shardingjdbc.io/schema/shardingjdbc/masterslave"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
http://shardingjdbc.io/schema/shardingjdbc/masterslave
http://shardingjdbc.io/schema/shardingjdbc/masterslave/master-slave.xsd
">
<import resource="datasource/masterSlaveDataSource.xml" />
<bean id="randomStrategy" class="io.shardingjdbc.core.api.algorithm.masterslave.RandomMasterSlaveLoadBalanceAlgorithm" />
<master-slave:data-source id="dbtbl_0" master-data-source-name="dbtbl_0_master" slave-data-source-names="dbtbl_0_slave_0, dbtbl_0_slave_1" strategy-ref="randomStrategy" />
<master-slave:data-source id="dbtbl_1" master-data-source-name="dbtbl_1_master" slave-data-source-names="dbtbl_1_slave_0, dbtbl_1_slave_1" strategy-ref="randomStrategy" />
<sharding:inline-strategy id="databaseStrategy" sharding-column="user_id" algorithm-expression="dbtbl_${user_id % 2}" />
<sharding:inline-strategy id="orderTableStrategy" sharding-column="order_id" algorithm-expression="t_order_${order_id % 4}" />
<sharding:inline-strategy id="orderItemTableStrategy" sharding-column="order_id" algorithm-expression="t_order_item_${order_id % 4}" />
<sharding:data-source id="shardingDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" default-data-source-name="dbtbl_0">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_${0..1}.t_order_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="orderTableStrategy" />
<sharding:table-rule logic-table="t_order_item" actual-data-nodes="dbtbl_${0..1}.t_order_item_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="orderItemTableStrategy" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xmlns:master-slave="http://shardingjdbc.io/schema/shardingjdbc/masterslave"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
http://shardingjdbc.io/schema/shardingjdbc/masterslave
http://shardingjdbc.io/schema/shardingjdbc/masterslave/master-slave.xsd
">
<import resource="datasource/masterSlaveDataSource.xml" />
<master-slave:data-source id="dbtbl_0" master-data-source-name="dbtbl_0_master" slave-data-source-names="dbtbl_0_slave_0, dbtbl_0_slave_1" strategy-type="RANDOM" />
<master-slave:data-source id="dbtbl_1" master-data-source-name="dbtbl_1_master" slave-data-source-names="dbtbl_1_slave_0, dbtbl_1_slave_1" strategy-type="RANDOM" />
<sharding:inline-strategy id="databaseStrategy" sharding-column="user_id" algorithm-expression="dbtbl_${user_id % 2}" />
<sharding:inline-strategy id="orderTableStrategy" sharding-column="order_id" algorithm-expression="t_order_${order_id % 4}" />
<sharding:inline-strategy id="orderItemTableStrategy" sharding-column="order_id" algorithm-expression="t_order_item_${order_id % 4}" />
<sharding:data-source id="shardingDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" default-data-source-name="dbtbl_0">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_${0..1}.t_order_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="orderTableStrategy" />
<sharding:table-rule logic-table="t_order_item" actual-data-nodes="dbtbl_${0..1}.t_order_item_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="orderItemTableStrategy" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sharding="http://shardingjdbc.io/schema/shardingjdbc/sharding"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://shardingjdbc.io/schema/shardingjdbc/sharding
http://shardingjdbc.io/schema/shardingjdbc/sharding/sharding.xsd
">
<import resource="datasource/dataSource.xml" />
<sharding:standard-strategy id="databaseStrategy" sharding-column="user_id" precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloDatabaseShardingAlgorithm" />
<sharding:standard-strategy id="tableStrategy" sharding-column="order_id" precise-algorithm-class="io.shardingjdbc.spring.algorithm.PreciseModuloTableShardingAlgorithm" />
<sharding:data-source id="shardingDataSource">
<sharding:sharding-rule data-source-names="dbtbl_0,dbtbl_1" default-data-source-name="dbtbl_0" key-generator-class="io.shardingjdbc.spring.fixture.IncrementKeyGenerator">
<sharding:table-rules>
<sharding:table-rule logic-table="t_order" actual-data-nodes="dbtbl_${0..1}.t_order_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="tableStrategy" generate-key-column="order_id" />
<sharding:table-rule logic-table="t_order_item" actual-data-nodes="dbtbl_${0..1}.t_order_item_${0..3}" database-strategy-ref="databaseStrategy" table-strategy-ref="tableStrategy" generate-key-column="order_item_id" column-key-generator-class="io.shardingjdbc.spring.fixture.DecrementKeyGenerator" />
</sharding:table-rules>
</sharding:sharding-rule>
</sharding:data-source>
</beans>
dbtbl_0.driver=org.h2.Driver
dbtbl_0.url=jdbc:h2:mem:dbtbl_0;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
dbtbl_0.username=sa
dbtbl_0.password=
dbtbl_1.driver=org.h2.Driver
dbtbl_1.url=jdbc:h2:mem:dbtbl_1;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
dbtbl_1.username=sa
dbtbl_1.password=
sql_show=true
dbtbl_0_master.driver=org.h2.Driver
dbtbl_0_master.url=jdbc:h2:mem:dbtbl_0_master;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
dbtbl_0_master.username=sa
dbtbl_0_master.password=
dbtbl_0_slave_0.driver=org.h2.Driver
dbtbl_0_slave_0.url=jdbc:h2:mem:dbtbl_0_slave_0;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
dbtbl_0_slave_0.username=sa
dbtbl_0_slave_0.password=
dbtbl_0_slave_1.driver=org.h2.Driver
dbtbl_0_slave_1.url=jdbc:h2:mem:dbtbl_0_slave_1;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
dbtbl_0_slave_1.username=sa
dbtbl_0_slave_1.password=
dbtbl_1_master.driver=org.h2.Driver
dbtbl_1_master.url=jdbc:h2:mem:dbtbl_1_master;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
dbtbl_1_master.username=sa
dbtbl_1_master.password=
dbtbl_1_slave_0.driver=org.h2.Driver
dbtbl_1_slave_0.url=jdbc:h2:mem:dbtbl_1_slave_0;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
dbtbl_1_slave_0.username=sa
dbtbl_1_slave_0.password=
dbtbl_1_slave_1.driver=org.h2.Driver
dbtbl_1_slave_1.url=jdbc:h2:mem:dbtbl_1_slave_1;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MYSQL
dbtbl_1_slave_1.username=sa
dbtbl_1_slave_1.password=
<?xml version="1.0"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%-5level] %d{HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="io.shardingjdbc" level="warn" additivity="false">
<appender-ref ref="console"/>
</logger>
<root>
<level value="error" />
<appender-ref ref="console" />
</root>
</configuration>
DROP SCHEMA IF EXISTS `dbtbl_0`;
CREATE SCHEMA `dbtbl_0`;
DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;
DROP TABLE IF EXISTS `t_order_2`;
DROP TABLE IF EXISTS `t_order_3`;
DROP TABLE IF EXISTS `t_order_item_0`;
DROP TABLE IF EXISTS `t_order_item_1`;
DROP TABLE IF EXISTS `t_order_item_2`;
DROP TABLE IF EXISTS `t_order_item_3`;
DROP TABLE IF EXISTS `t_config`;
CREATE TABLE `t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_2` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_3` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_item_0` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_1` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_2` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_3` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_config` (`id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`id`));
DROP SCHEMA IF EXISTS `dbtbl_0_master`;
CREATE SCHEMA `dbtbl_0_master`;
DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;
DROP TABLE IF EXISTS `t_order_2`;
DROP TABLE IF EXISTS `t_order_3`;
DROP TABLE IF EXISTS `t_order_item_0`;
DROP TABLE IF EXISTS `t_order_item_1`;
DROP TABLE IF EXISTS `t_order_item_2`;
DROP TABLE IF EXISTS `t_order_item_3`;
DROP TABLE IF EXISTS `t_config`;
CREATE TABLE `t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_2` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_3` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_item_0` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_1` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_2` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_3` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_config` (`id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`id`));
DROP SCHEMA IF EXISTS `dbtbl_0_slave_0`;
CREATE SCHEMA `dbtbl_0_slave_0`;
DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;
DROP TABLE IF EXISTS `t_order_2`;
DROP TABLE IF EXISTS `t_order_3`;
DROP TABLE IF EXISTS `t_order_item_0`;
DROP TABLE IF EXISTS `t_order_item_1`;
DROP TABLE IF EXISTS `t_order_item_2`;
DROP TABLE IF EXISTS `t_order_item_3`;
DROP TABLE IF EXISTS `t_config`;
CREATE TABLE `t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_2` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_3` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_item_0` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_1` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_2` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_3` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_config` (`id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`id`));
DROP SCHEMA IF EXISTS `dbtbl_0_slave_1`;
CREATE SCHEMA `dbtbl_0_slave_1`;
DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;
DROP TABLE IF EXISTS `t_order_2`;
DROP TABLE IF EXISTS `t_order_3`;
DROP TABLE IF EXISTS `t_order_item_0`;
DROP TABLE IF EXISTS `t_order_item_1`;
DROP TABLE IF EXISTS `t_order_item_2`;
DROP TABLE IF EXISTS `t_order_item_3`;
DROP TABLE IF EXISTS `t_config`;
CREATE TABLE `t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_2` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_3` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_item_0` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_1` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_2` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_3` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_config` (`id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`id`));
DROP SCHEMA IF EXISTS `dbtbl_1`;
CREATE SCHEMA `dbtbl_1`;
DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;
DROP TABLE IF EXISTS `t_order_2`;
DROP TABLE IF EXISTS `t_order_3`;
DROP TABLE IF EXISTS `t_order_item_0`;
DROP TABLE IF EXISTS `t_order_item_1`;
DROP TABLE IF EXISTS `t_order_item_2`;
DROP TABLE IF EXISTS `t_order_item_3`;
DROP TABLE IF EXISTS `t_config`;
CREATE TABLE `t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_2` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_3` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_item_0` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_1` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_2` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_3` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
DROP SCHEMA IF EXISTS `dbtbl_1_master`;
CREATE SCHEMA `dbtbl_1_master`;
DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;
DROP TABLE IF EXISTS `t_order_2`;
DROP TABLE IF EXISTS `t_order_3`;
DROP TABLE IF EXISTS `t_order_item_0`;
DROP TABLE IF EXISTS `t_order_item_1`;
DROP TABLE IF EXISTS `t_order_item_2`;
DROP TABLE IF EXISTS `t_order_item_3`;
CREATE TABLE `t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_2` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_3` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_item_0` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_1` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_2` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_3` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
DROP SCHEMA IF EXISTS `dbtbl_1_slave_0`;
CREATE SCHEMA `dbtbl_1_slave_0`;
DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;
DROP TABLE IF EXISTS `t_order_2`;
DROP TABLE IF EXISTS `t_order_3`;
DROP TABLE IF EXISTS `t_order_item_0`;
DROP TABLE IF EXISTS `t_order_item_1`;
DROP TABLE IF EXISTS `t_order_item_2`;
DROP TABLE IF EXISTS `t_order_item_3`;
CREATE TABLE `t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_2` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_3` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_item_0` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_1` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_2` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_3` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
DROP SCHEMA IF EXISTS `dbtbl_1_slave_1`;
CREATE SCHEMA `dbtbl_1_slave_1`;
DROP TABLE IF EXISTS `t_order_0`;
DROP TABLE IF EXISTS `t_order_1`;
DROP TABLE IF EXISTS `t_order_2`;
DROP TABLE IF EXISTS `t_order_3`;
DROP TABLE IF EXISTS `t_order_item_0`;
DROP TABLE IF EXISTS `t_order_item_1`;
DROP TABLE IF EXISTS `t_order_item_2`;
DROP TABLE IF EXISTS `t_order_item_3`;
CREATE TABLE `t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_2` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_3` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_id`));
CREATE TABLE `t_order_item_0` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_1` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_2` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
CREATE TABLE `t_order_item_3` (`order_item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(45) NULL, PRIMARY KEY (`order_item_id`));
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册