目录
- sharding-jdbc-4.1.1版本启动数据源报错问题
- 现象
- 环境
- 报错原因
- 第一种解决办法
- 第二种解决办法
现象
springboot搭建sharding-jdbc实现分库分表时报错:
*************************** APPLICATION FAILED TO START *************************** Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class Action: Consider the following: If you want an embedded database (H2, HSQL or Derby), please put it on the classpath. If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active). Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [com/alibaba/druid/spring/boot/autoconfigure/DruidDataSourceAutoConfigure.class]: Invocation of init method failed; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class
环境
sharding-jdbc-4.1.1
4.1.1 org.apache.shardingsphere sharding-jdbc-spring-boot-starter ${sharding-jdbc-version} org.apache.shardingsphere sharding-jdbc-spring-namespace ${sharding-jdbc-version}
报错原因
是sharding-jdbc-4.1.1最新版本spring boot配置类识别有点问题导致
org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration
第一种解决办法
把版本改为 4.0.0-RC1
4.0.0-RC1
第二种解决办法
还是保持原先最新版本 4.1.1
重新写一个配置类,在自己工程中,可以跟sharding-jdbc-4.1.1最新版本spring boot配置类内容一致
org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration
比如在自己项目工程下,重新新建一个配置类,内容跟SpringBootConfiguration类一致,如下:
@Configuration
@ComponentScan("org.apache.shardingsphere.spring.boot.converter")
@EnableConfigurationProperties({
SpringBootShardingRuleConfigurationProperties.class,
SpringBootMasterSlaveRuleConfigurationProperties.class,
SpringBootEncryptRuleConfigurationProperties.class,
SpringBootPropertiesConfigurationProperties.class,
SpringBootShadowRuleConfigurationProperties.class})
@ConditionalOnProperty(prefix = "spring.shardingsphere", name = "enabled", havingValue = "true", matchIfMissing = true)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@RequiredArgsConstructor
public class ShardingJdbcConfig implements EnvironmentAware {
private final SpringBootShardingRuleConfigurationProperties shardingRule;
private final SpringBootMasterSlaveRuleConfigurationProperties masterSlaveRule;
private final SpringBootEncryptRuleConfigurationProperties encryptRule;
private final SpringBootShadowRuleConfigurationProperties shadowRule;
private final SpringBootPropertiesConfigurationProperties props;
private final Map dataSourceMap = new linkedHashMap<>();
private final String jndiName = "jndi-name";
@Bean
@ConditionalOnMissingBean(DataSource.class)
@Conditional(ShardingRuleCondition.class)
public DataSource shardingDataSource() throws SQLException {
return ShardingDataSourceFactory.createDataSource(dataSourceMap, new ShardingRuleConfigurationYamlSwapper().swap(shardingRule), props.getProps());
}
@Bean
@Conditional(MasterSlaveRuleCondition.class)
@ConditionalOnMissingBean(DataSource.class)
public DataSource masterSlaveDataSource() throws SQLException {
return MasterSlaveDataSourceFactory.createDataSource(dataSourceMap, new MasterSlaveRuleConfigurationYamlSwapper().swap(masterSlaveRule), props.getProps());
}
@Bean
@Conditional(EncryptRuleCondition.class)
@ConditionalOnMissingBean(DataSource.class)
public DataSource encryptDataSource() throws SQLException {
return EncryptDataSourceFactory.createDataSource(dataSourceMap.values().iterator().next(), new EncryptRuleConfigurationYamlSwapper().swap(encryptRule), props.getProps());
}
@Bean
@Conditional(ShadowRuleCondition.class)
@ConditionalOnMissingBean(DataSource.class)
public DataSource shadowDataSource() throws SQLException {
return ShadowDataSourceFactory.createDataSource(dataSourceMap, new ShadowRuleConfigurationYamlSwapper().swap(shadowRule), props.getProps());
}
@Bean
@ConditionalOnMissingBean(ShardingTransactionTypeScanner.class)
public ShardingTransactionTypeScanner shardingTransactionTypeScanner() {
return new ShardingTransactionTypeScanner();
}
@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);
}
}
}
private List getDataSourceNames(final Environment environment, final String prefix) {
StandardEnvironment standardEnv = (StandardEnvironment) environment;
standardEnv.setIgnoreUnresolvableNestedPlaceholders(true);
return null == standardEnv.getProperty(prefix + "name")
? new InlineexpressionParser(standardEnv.getProperty(prefix + "names")).splitAndevaluate() : Collections.singletonList(standardEnv.getProperty(prefix + "name"));
}
@SuppressWarnings("unchecked")
private DataSource getDataSource(final Environment environment, final String prefix, final String dataSourceName) throws ReflectiveOperationException, NamingException {
Map dataSourceProps = PropertyUtil.handle(environment, prefix + dataSourceName.trim(), Map.class);
Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
if (dataSourceProps.containsKey(jndiName)) {
return getJndiDataSource(dataSourceProps.get(jndiName).toString());
}
DataSource result = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(), dataSourceProps);
DataSourcePropertiesSetterHolder.getDataSourcePropertiesSetterByType(dataSourceProps.get("type").toString()).ifPresent(
dataSourcePropertiesSetter -> dataSourcePropertiesSetter.propertiesSet(environment, prefix, dataSourceName, result));
return result;
}
private DataSource getJndiDataSource(final String jndiName) throws NamingException {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setResourceRef(true);
bean.setJndiName(jndiName);
bean.setProxyInterface(DataSource.class);
bean.afterPropertiesSet();
return (DataSource) bean.getObject();
}
}



