Bootstrap

ShardingSphere问题解决(一)

概要:错误信息 Data sources cannot be empty

  • shardingSphere版本
    shardingshpere_version=4.1.0
    sharding_jdbc_spring_namespace_version=4.1.0
compile("org.apache.shardingsphere:sharding-jdbc-spring-boot-starter:${shardingshpere_version}")
compile("org.apache.shardingsphere:sharding-jdbc-spring-namespace:${sharding_jdbc_spring_namespace_version}")
  • 详细异常明细
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'shardingDataSource' threw exception; nested exception is java.lang.IllegalArgumentException: Data sources cannot be empty.
 at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
 at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:582)
 ... 104 common frames omitted
Caused by: java.lang.IllegalArgumentException: Data sources cannot be empty.
 at com.google.common.base.Preconditions.checkArgument(Preconditions.java:134)
 at org.apache.shardingsphere.core.rule.ShardingRule.<init>(ShardingRule.java:76)
 at org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory.createDataSource(ShardingDataSourceFactory.java:48)
 at org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration.shardingDataSource(SpringBootConfiguration.java:103)
 at org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration$$EnhancerBySpringCGLIB$$a2810b5d.CGLIB$shardingDataSource$1(<generated>)
 at org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration$$EnhancerBySpringCGLIB$$a2810b5d$$FastClassBySpringCGLIB$$b2e37f70.invoke(<generated>)
 at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
 at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:361)
 at org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration$$EnhancerBySpringCGLIB$$a2810b5d.shardingDataSource(<generated>)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:497)
 at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
 ... 105 common frames omitted

  • 查看源码
    ShardingRule.class,发现 dataSourceNames 节点为空
public ShardingRule(final ShardingRuleConfiguration shardingRuleConfig, final Collection<String> dataSourceNames) {
    Preconditions.checkArgument(null != shardingRuleConfig, "ShardingRuleConfig cannot be null.");

	Preconditions.checkArgument(null != dataSourceNames && !dataSourceNames.isEmpty(), "Data sources cannot be empty.");
	    this.ruleConfiguration = shardingRuleConfig;
	
	shardingDataSourceNames = new ShardingDataSourceNames(shardingRuleConfig, dataSourceNames);
	
	tableRules = createTableRules(shardingRuleConfig);
	
	broadcastTables = shardingRuleConfig.getBroadcastTables();
	
	bindingTableRules = createBindingTableRules(shardingRuleConfig.getBindingTableGroups());
	
	defaultDatabaseShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultDatabaseShardingStrategyConfig());
	
	defaultTableShardingStrategy = createDefaultShardingStrategy(shardingRuleConfig.getDefaultTableShardingStrategyConfig());
	
	defaultShardingKeyGenerator = createDefaultKeyGenerator(shardingRuleConfig.getDefaultKeyGeneratorConfig());
	
	masterSlaveRules = createMasterSlaveRules(shardingRuleConfig.getMasterSlaveRuleConfigs());
	
	encryptRule = createEncryptRule(shardingRuleConfig.getEncryptRuleConfig());
}

反调至SpringBootConfiguration.class,发现数据源信息取自dataSourceMap

@Bean
@Conditional(ShardingRuleCondition.class)
public DataSource shardingDataSource() throws SQLException {

	return ShardingDataSourceFactory.createDataSource(dataSourceMap, new ShardingRuleConfigurationYamlSwapper().swap(shardingRule), props.getProps());
}

dataSourceMap赋值逻辑为

@Override
public final void setEnvironment(final Environment environment) {
    String prefix = "spring.shardingsphere.datasource.";
    for (String each : getDataSourceNames(environment, prefix)) {

		try {
		
			dataSourceMap.put(each, getDataSource(environment, prefix, each));
		
		} catch (final ReflectiveOperationException ex) {
		
			throw new ShardingSphereException("Can't find datasource type!", ex);
		
		} catch (final NamingException namingEx) {
		
			throw new ShardingSphereException("Can't find JNDI datasource!", namingEx);
		
		}
	}
}

从而可知数据源yaml配置文件因该为:spring.shardingsphere.datasource.
而自己的项目配置为sharding.dataSource

加载配置文件时没有问题,可以注入数据源和路由规则,当 @Conditional(ShardingRuleCondition.class) 生效时,会在环境中重新加载默认路径数据源,导致启动失败。

  • 解决方案
    配置默认数据源路径即可
;