为什么我的自定义DataSource getConnection()抛出“SQLException:url不能为null”?

时间:2017-08-03 14:55:50

标签: java spring spring-boot

我正在编写一个Spring Boot(Batch)应用程序,它应该以特定的退出代码退出。当数据库无法连接时,要求是返回退出代码。

我的方法是尽早处理此异常,方法是显式创建DataSource bean,调用getConnection()并捕获并抛出实现ExitCodeGenerator的自定义异常。配置如下:

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
...
@Bean
@Primary
@ConfigurationProperties("spring.datasource")
public DataSourceProperties dataSourceProps() {
    return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("spring.datasource")
public DataSource customDataSource(DataSourceProperties props) {

    DataSource ds = props.initializeDataSourceBuilder().create().build();

    try {
        ds.getConnection();

    } catch (SQLException e) {
        throw new DBConnectionException(e); // implements ExitCodeGenerator interface
    }

    return ds;
}
...
}

我希望重用尽可能多的Spring Boot Autoconfiguration,这就是我使用@ConfigurationProperties的原因。我不知道这是否可行。

DataSourceProperties.getUrl()上的调用会返回已配置的网址(来自我的属性文件):

spring.datasource.url=jdbc:oracle:....

但是当我调用DataSource.getConnection()时,为什么Spring Boot会抛出此异常:

java.sql.SQLException: The url cannot be null
at java.sql.DriverManager.getConnection(DriverManager.java:649) ~[?:1.8.0_141]
at java.sql.DriverManager.getConnection(DriverManager.java:208) ~[?:1.8.0_141]
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:308) ~[tomcat-jdbc-8.5.15.jar:?]
at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.15.jar:?]
at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:735) ~[tomcat-jdbc-8.5.15.jar:?]
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:667) ~[tomcat-jdbc-8.5.15.jar:?]
at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:482) [tomcat-jdbc-8.5.15.jar:?]
at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:154) [tomcat-jdbc-8.5.15.jar:?]
at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) [tomcat-jdbc-8.5.15.jar:?]
at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) [tomcat-jdbc-8.5.15.jar:?]
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) [tomcat-jdbc-8.5.15.jar:?]
at com.foo.bar.BatchConfiguration.customDataSource(BatchConfiguration.java:xxx) [main/:?]
...

或者你知道处理这种情况的一些更清洁的方法吗?

由于

编辑: Spring Boot版本为1.5.4

2 个答案:

答案 0 :(得分:2)

错误很微妙,位于

DataSource ds = props.initializeDataSourceBuilder().create().build();

create()创建一个新的DataSourceBuilder并删除预配置的属性。

props.initializeDataSourceBuilder()已经返回DataSourceBuilder,并设置了所有属性(网址,用户名等)。因此,您只需添加新属性或直接build()即可。所以解决方案是删除create()

DataSource ds = props.initializeDataSourceBuilder().build();

在此上下文中,也可以删除dataSourceProps()方法bean。

答案 1 :(得分:0)

看起来您没有为数据源设置任何值。

props.initializeDataSourceBuilder().create().build();未将属性的值设置为数据源。它只是创建和构建一个。

尝试使用静态DataSourceBuilder手动设置值。您将从dataSourceProps bean中获取值:

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
...
@Bean
@Primary
@ConfigurationProperties("spring.datasource")
public DataSourceProperties dataSourceProps() {
    return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("spring.datasource")
public DataSource customDataSource(DataSourceProperties props) {

      DataSource ds = DataSourceBuilder.create()
            .driverClassName(dataSourceProps().getDriverClassName())
            .url(dataSourceProps().getUrl())
            .username(dataSourceProps().getUsername())
            .password(dataSourceProps().getPassword())
            .build();

    try {
        ds.getConnection();

    } catch (SQLException e) {
        throw new DBConnectionException(e); // implements ExitCodeGenerator interface
    }

    return ds;
}
...
}