Defining a jta Datasource outside of the container

2019-02-20 03:12发布

Our application currently uses a datasource which is defined in the JBoss standalone.xml, and basically we need to have this be defined within the app rather than in the container for a while. Our current setup is;

application-context.xml;

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
        <property name="persistenceUnitName" value="rtsPersistenceUnit" />
        <property name="packagesToScan">
            ...
         </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="ORACLE" />
                <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect"/>
            </bean>
        </property>
</bean>

persistance.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">

    <persistence-unit name="rtsPersistenceUnit" transaction-type="RESOURCE_LOCAL">

        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <jta-data-source>java:/jdbc/RTSdb</jta-data-source>

        <class>...</class>

        <exclude-unlisted-classes>true</exclude-unlisted-classes>

        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="validate" />
            <property name="hibernate.transaction.flush_before_completion" value="true" />
        </properties>

    </persistence-unit>

</persistence>

datasource.xml:

<bean id="rtsDatasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
    <property name="url" value="..."/>
    <property name="username" value="..."/>
    <property name="password" value="..."/>
</bean>

Basically all I want is for the line

<jta-data-source>java:/jdbc/RTSdb</jta-data-source>

to read from datasource.xml rather than go the container (JBoss). It seems like it would be simple but after reading some Spring and Oracle docs I couldn't find an answer.

1条回答
ゆ 、 Hurt°
2楼-- · 2019-02-20 03:56

Yes, you could use a JTA compliant transaction manager like Atomikos or Bitronix. Their respective sites have documentation on how to configure them with Spring. In general, you will have to follow the steps given below (if using Atomikos):

  1. Retain your existing XA data source (rtsDatasource in your case) or create one if not already using (for example, if someone has a non-XA data source, that data source must be converted to an XA data source first).
  2. Wrap the XA data source in an AtomikosDataSourceBean.
  3. Point your EntityManagerFactory at the new AtomikosDataSourceBean instance.
  4. Declare an XA transaction manager and an XA user transaction.
  5. Wrap the XA transaction manager in a Spring JtaTransactionManager.
  6. Use the Spring JtaTransactionManager.

A short configuration snippet using H2 database, Hibernate 4, Spring 4 and Atomikos 4 is shown below.

<bean class="org.h2.jdbcx.JdbcDataSource" id="originalDataStore" lazy-init="true">...</bean>

<bean class="com.atomikos.jdbc.AtomikosDataSourceBean" id="dataSource" init-method="init" destroy-method="close">
  <property name="uniqueResourceName" value="xaDS"/>
  <property name="xaDataSource" ref="originalDataStore"/>
  <property name="poolSize" value="3"/>
</bean>

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
  <property name="dataSource" ref="dataSource"/>
  <property name="jpaProperties">
    <props>
      <prop key="hibernate.transaction.jta.platform">com.atomikos.icatch.jta.hibernate4.AtomikosPlatform</prop>
       ...
    </props>
  </property>
</bean>

<bean class="org.springframework.transaction.jta.JtaTransactionManager" id="transactionManager">
  <property name="transactionManager">
    <bean class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
      <property name="forceShutdown" value="false"/>
    </bean>
  </property>
  <property name="userTransaction">
    <bean class="com.atomikos.icatch.jta.J2eeUserTransaction">
      <property name="transactionTimeout" value="300"/>
    </bean>
  </property>
  <property name="allowCustomIsolationLevels" value="true"/>
</bean>

<transaction:annotation-driven transaction-manager="transactionManager"/>

For details, you can see this app.

查看更多
登录 后发表回答