为 Spring-Boot 配置 XADataSource

Configuring a XADataSource for Spring-Boot

我正在对 11G Oracle 数据库进行集成测试。我收到一条错误消息:

Caused by: java.lang.NoClassDefFoundError: com/arjuna/ats/jbossatx/jta/RecoveryManagerService

所以我补充说:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-narayana</artifactId>
            <version>1.4.1.RELEASE</version>
        </dependency>

我的 pom 文件,错误消失了,但现在我收到一条错误消息:

  Caused by: java.lang.NoSuchFieldError: XADataSource
    at org.springframework.boot.jta.narayana.NarayanaDataSourceBean.getConnection(NarayanaDataSourceBean.java:58) ~[spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE]
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362) ~[spring-orm-4.3.3.RELEASE.jar:4.3.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1642) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
    ... 44 common frames omitted

当我转到 class (NarayanaDataSourceBean.java:58) 时,我看到这两种方法无法解析 XADataSource。

@Override
    public Connection getConnection() throws SQLException {
        Properties properties = new Properties();
        properties.put(TransactionalDriver.XADataSource, this.xaDataSource); //cannot resolve XADataSource
        return ConnectionManager.create(null, properties);
    }

    @Override
    public Connection getConnection(String username, String password)
            throws SQLException {
        Properties properties = new Properties();
        properties.put(TransactionalDriver.XADataSource, this.xaDataSource); //cannot resolve XADataSource
        properties.put(TransactionalDriver.userName, username);
        properties.put(TransactionalDriver.password, password);
        return ConnectionManager.create(null, properties);
    }

根据我的理解,这 class 是事务管理所必需的。但这是我第一次需要使用这种依赖。

我在 application.properties 中设置了我的数据源,如下所示:

#Oracle database setup
spring.datasource.url=jdbc:oracle:thin:@999.999.999.999:1521:d9rty
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.profiles.active=oracle

#JPA setup
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect

spring.datasource.max-active=5

server.port = 4000

如有任何建议,我们将不胜感激。

你的XADataSource是用来测试的,所以你需要创建一个。

@Configuration
@EnableTransactionManagement
public class AppConfig {


    @Value("${statdb.driverClassName}")
    private String statdbDriverClassName;

    @Value("${statdb.url}")
    private String statdbUrl;

    @Value("${statdb.id}")
    private String statdbId;

    @Value("${statdb.pw}")
    private String statdbPw;

    @Value("${statdb.validationQuery}")
    private String statdbValidationQuery;

    @Bean
    public DataSource dataSourceStatdb() {
        XADataSource dataSource = new XADataSource();
        dataSource.setDriverClassName(statdbDriverClassName);
        dataSource.setUrl(statdbUrl);
        dataSource.setUsername(statdbId);
        dataSource.setPassword(statdbPw);
        dataSource.setValidationQuery(statdbValidationQuery);
        return dataSource;
    }