带Sybase和Linux的Spring Boot事务神谕

时间:2016-08-31 00:17:51

标签: java spring spring-boot

我正在尝试设置一个具有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数据源甚至没有被要求实际执行任何操作时,它为什么要这样做呢?

0 个答案:

没有答案