我正在尝试设置一个具有2个数据源的Spring启动应用程序 - 一个用于Sybase,另一个用于oracle。
我在Application.class中将它们设置为这样:
@Primary
@Bean(name="oracleDatasource")
@ConfigurationProperties(prefix="oracle")
public DataSource oracleDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name="oracleJdbcTemplate")
@Autowired
JdbcTemplate oracleJdbcTemplate (@Qualifier("oracleDatasource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean(name="sybaseDatasource")
@ConfigurationProperties(prefix="sybase")
public DataSource sybaseDataSource() {
DataSource ds = DataSourceBuilder.create().build();
try {
DatabaseMetaData meta = ds.getConnection().getMetaData();
System.out.println(meta.getDriverName());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ds;
}
@Bean(name="sybaseJdbcTemplate")
@Autowired
JdbcTemplate sybaseJdbcTemplate (@Qualifier("sybaseDatasource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
我在Sybase中添加了元数据部分,以确认当Spring启动时,它成功获取Connection并打印出驱动程序名称。到目前为止工作良好。
然而,当我从我的控制器调用一个具有@Transaction的方法时,Spring事务拦截器似乎再次尝试为Sybase创建数据源,并且在驱动程序名称上使用空指针失败。它没有任何意义!
java.lang.NullPointerException: null
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:657)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:430)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:204)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:439)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
... rest omitted
为什么会这样做,我该如何解决这个问题?
基本的通话链是:
控制器:
@RestController
public class BlahBlahController {
@Autowired
private BlahBlahDelegate delegate=null;
@RequestMapping("blah")
public Object doBlahBlah() {
return delegate.doBlahBlah();
}
代表:
@Component
public class BlahBlahDelegate {
@Autowired
private BlahBlahDao dao=null;
@Transactional
public Object doBlahBlah() {
// does some other stuff
return dao.doBlahBlah();
}
道:
@Repository
public class BlahBlahDao {
@Autowired
ApplicationContext context;
private JdbcTemplate getJdbcTemplate(String datasourceName) throws IAPBusinessException {
if (datasourceName.equals("oracle")) {
return (JdbcTemplate)context.getBean("oracleJdbcTemplate");
} else if (datasourceName.equals("Sybase")) {
return (JdbcTemplate)context.getBean("sybaseJdbcTemplate");
} else
throw new IAPBusinessException("No datasource with ID "+datasourceName+" exists");
}
@Transactional
public Object doBlahBlah() {
JdbcTemplate jdbc = getJdbcTemplate("oracle");
jdbc.update("blah blah");
return something;
}
总结起来。没有其他自动装配或引用这些数据源或jdbc模板,那么为什么事务拦截器在应用程序启动期间已经完成时似乎试图实现另一个Sybase BasicDataSource?当Sybase数据源甚至没有被要求实际执行任何操作时,它为什么要这样做呢?