Revise native Hibernate 5 bootstrapping with JTA transaction manager
Closes gh-25858
This commit is contained in:
parent
2533ba5253
commit
e417318915
|
|
@ -225,6 +225,8 @@ public class LocalSessionFactoryBuilder extends Configuration {
|
||||||
"Unknown transaction manager type: " + jtaTransactionManager.getClass().getName());
|
"Unknown transaction manager type: " + jtaTransactionManager.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getProperties().put(AvailableSettings.TRANSACTION_COORDINATOR_STRATEGY, "jta");
|
||||||
|
|
||||||
// Hibernate 5.1/5.2: manually enforce connection release mode AFTER_STATEMENT (the JTA default)
|
// Hibernate 5.1/5.2: manually enforce connection release mode AFTER_STATEMENT (the JTA default)
|
||||||
try {
|
try {
|
||||||
// Try Hibernate 5.2
|
// Try Hibernate 5.2
|
||||||
|
|
|
||||||
|
|
@ -381,6 +381,19 @@ NOTE: The preceding definition of the `dataSource` bean uses the `<jndi-lookup/>
|
||||||
from the `jee` namespace. For more information see
|
from the `jee` namespace. For more information see
|
||||||
<<integration.adoc#xsd-schemas-jee, The JEE Schema>>.
|
<<integration.adoc#xsd-schemas-jee, The JEE Schema>>.
|
||||||
|
|
||||||
|
NOTE: If you use JTA, your transaction manager definition should look the same, regardless
|
||||||
|
of what data access technology you use, be it JDBC, Hibernate JPA, or any other supported
|
||||||
|
technology. This is due to the fact that JTA transactions are global transactions, which
|
||||||
|
can enlist any transactional resource.
|
||||||
|
|
||||||
|
In all Spring transaction setups, application code does not need to change. You can change
|
||||||
|
how transactions are managed merely by changing configuration, even if that change means
|
||||||
|
moving from local to global transactions or vice versa.
|
||||||
|
|
||||||
|
|
||||||
|
[[transaction-strategies-hibernate]]
|
||||||
|
==== Hibernate Transaction Setup
|
||||||
|
|
||||||
You can also easily use Hibernate local transactions, as shown in the following examples.
|
You can also easily use Hibernate local transactions, as shown in the following examples.
|
||||||
In this case, you need to define a Hibernate `LocalSessionFactoryBean`, which your
|
In this case, you need to define a Hibernate `LocalSessionFactoryBean`, which your
|
||||||
application code can use to obtain Hibernate `Session` instances.
|
application code can use to obtain Hibernate `Session` instances.
|
||||||
|
|
@ -420,21 +433,52 @@ example declares `sessionFactory` and `txManager` beans:
|
||||||
|
|
||||||
If you use Hibernate and Java EE container-managed JTA transactions, you should use the
|
If you use Hibernate and Java EE container-managed JTA transactions, you should use the
|
||||||
same `JtaTransactionManager` as in the previous JTA example for JDBC, as the following
|
same `JtaTransactionManager` as in the previous JTA example for JDBC, as the following
|
||||||
example shows:
|
example shows. Also, it is recommended to make Hibernate aware of JTA through its
|
||||||
|
transaction coordinator and possibly also its connection release mode configuration:
|
||||||
|
|
||||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
|
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
|
||||||
|
<property name="dataSource" ref="dataSource"/>
|
||||||
|
<property name="mappingResources">
|
||||||
|
<list>
|
||||||
|
<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="hibernateProperties">
|
||||||
|
<value>
|
||||||
|
hibernate.dialect=${hibernate.dialect}
|
||||||
|
hibernate.transaction.coordinator_class=jta
|
||||||
|
hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT
|
||||||
|
</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
|
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
|
||||||
----
|
----
|
||||||
|
|
||||||
NOTE: If you use JTA, your transaction manager definition should look the same, regardless
|
Or alternatively, you may pass the `JtaTransactionManager` into your `LocalSessionFactoryBean`
|
||||||
of what data access technology you use, be it JDBC, Hibernate JPA, or any other supported
|
for enforcing the same defaults:
|
||||||
technology. This is due to the fact that JTA transactions are global transactions, which
|
|
||||||
can enlist any transactional resource.
|
|
||||||
|
|
||||||
In all these cases, application code does not need to change. You can change how
|
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||||
transactions are managed merely by changing configuration, even if that change means
|
----
|
||||||
moving from local to global transactions or vice versa.
|
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
|
||||||
|
<property name="dataSource" ref="dataSource"/>
|
||||||
|
<property name="mappingResources">
|
||||||
|
<list>
|
||||||
|
<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
<property name="hibernateProperties">
|
||||||
|
<value>
|
||||||
|
hibernate.dialect=${hibernate.dialect}
|
||||||
|
</value>
|
||||||
|
</property>
|
||||||
|
<property name="jtaTransactionManager" ref="txManager"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3115,8 +3159,8 @@ hierarchy defined in the `org.springframework.dao` package. (See <<dao-exception
|
||||||
|
|
||||||
When you use the `JdbcTemplate` for your code, you need only to implement callback
|
When you use the `JdbcTemplate` for your code, you need only to implement callback
|
||||||
interfaces, giving them a clearly defined contract. Given a `Connection` provided by the
|
interfaces, giving them a clearly defined contract. Given a `Connection` provided by the
|
||||||
`JdbcTemplate` class, the `PreparedStatementCreator`
|
`JdbcTemplate` class, the `PreparedStatementCreator` callback interface creates a prepared
|
||||||
callback interface creates a prepared statement, providing SQL and any necessary parameters. The same is true for the
|
statement, providing SQL and any necessary parameters. The same is true for the
|
||||||
`CallableStatementCreator` interface, which creates callable statements. The
|
`CallableStatementCreator` interface, which creates callable statements. The
|
||||||
`RowCallbackHandler` interface extracts values from each row of a `ResultSet`.
|
`RowCallbackHandler` interface extracts values from each row of a `ResultSet`.
|
||||||
|
|
||||||
|
|
@ -7156,12 +7200,12 @@ conjunction with EJBs.
|
||||||
==== Spurious Application Server Warnings with Hibernate
|
==== Spurious Application Server Warnings with Hibernate
|
||||||
|
|
||||||
In some JTA environments with very strict `XADataSource` implementations (currently
|
In some JTA environments with very strict `XADataSource` implementations (currently
|
||||||
only some WebLogic Server and WebSphere versions), when Hibernate is configured without
|
some WebLogic Server and WebSphere versions), when Hibernate is configured without
|
||||||
regard to the JTA `PlatformTransactionManager` object for that environment,
|
regard to the JTA transaction manager for that environment, spurious warnings or
|
||||||
spurious warning or exceptions can show up in the application server log.
|
exceptions can show up in the application server log. These warnings or exceptions
|
||||||
These warnings or exceptions indicate that the connection being accessed is no longer
|
indicate that the connection being accessed is no longer valid or JDBC access is no
|
||||||
valid or JDBC access is no longer valid, possibly because the transaction is no longer
|
longer valid, possibly because the transaction is no longer active. As an example,
|
||||||
active. As an example, here is an actual exception from WebLogic:
|
here is an actual exception from WebLogic:
|
||||||
|
|
||||||
[literal]
|
[literal]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
|
@ -7170,28 +7214,26 @@ java.sql.SQLException: The transaction is no longer active - status: 'Committed'
|
||||||
further JDBC access is allowed within this transaction.
|
further JDBC access is allowed within this transaction.
|
||||||
----
|
----
|
||||||
|
|
||||||
You can resolve this warning by making Hibernate aware of the JTA
|
Another common problem is a connection leak after JTA transactions, with Hibernate
|
||||||
`PlatformTransactionManager` instance, to which it synchronizes (along with Spring).
|
sessions (and potentially underlying JDBC connections) not getting closed properly.
|
||||||
You have two options for doing this:
|
|
||||||
|
|
||||||
* If, in your application context, you already directly obtain the JTA
|
You can resolve such issues by making Hibernate aware of the JTA transaction manager,
|
||||||
`PlatformTransactionManager` object (presumably from JNDI through
|
to which it synchronizes (along with Spring). You have two options for doing this:
|
||||||
`JndiObjectFactoryBean` or `<jee:jndi-lookup>`) and feed it, for example, to
|
|
||||||
Spring's `JtaTransactionManager`, the easiest way is to specify a reference to
|
* Pass your Spring `JtaTransactionManager` bean to your Hibernate setup. The easiest
|
||||||
the bean that defines this JTA `PlatformTransactionManager` instance as the value of the
|
way is a bean reference into the `jtaTransactionManager` property for your
|
||||||
`jtaTransactionManager` property for `LocalSessionFactoryBean.` Spring then makes the
|
`LocalSessionFactoryBean` bean (see <<transaction-strategies-hibernate>>).
|
||||||
object available to Hibernate.
|
Spring then makes the corresponding JTA strategies available to Hibernate.
|
||||||
* More likely, you do not already have the JTA `PlatformTransactionManager` instance,
|
* You may also configure Hibernate's JTA-related properties explicitly, in particular
|
||||||
because Spring's `JtaTransactionManager` can find it itself. Thus, you need to
|
"hibernate.transaction.coordinator_class", "hibernate.connection.handling_mode"
|
||||||
configure Hibernate to look up JTA `PlatformTransactionManager` directly. You do this
|
and potentially "hibernate.transaction.jta.platform" in your "hibernateProperties"
|
||||||
by configuring an application server-specific `TransactionManagerLookup` class in the
|
on `LocalSessionFactoryBean` (see Hibernate's manual for details on those properties).
|
||||||
Hibernate configuration, as described in the Hibernate manual.
|
|
||||||
|
|
||||||
The remainder of this section describes the sequence of events that occur with and
|
The remainder of this section describes the sequence of events that occur with and
|
||||||
without Hibernate's awareness of the JTA `PlatformTransactionManager`.
|
without Hibernate's awareness of the JTA `PlatformTransactionManager`.
|
||||||
|
|
||||||
When Hibernate is not configured with any awareness of the JTA
|
When Hibernate is not configured with any awareness of the JTA transaction manager,
|
||||||
`PlatformTransactionManager`, the following events occur when a JTA transaction commits:
|
the following events occur when a JTA transaction commits:
|
||||||
|
|
||||||
* The JTA transaction commits.
|
* The JTA transaction commits.
|
||||||
* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so it is
|
* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so it is
|
||||||
|
|
@ -7204,16 +7246,16 @@ When Hibernate is not configured with any awareness of the JTA
|
||||||
error, as the application server no longer considers the `Connection` to be usable,
|
error, as the application server no longer considers the `Connection` to be usable,
|
||||||
because the transaction has already been committed.
|
because the transaction has already been committed.
|
||||||
|
|
||||||
When Hibernate is configured with awareness of the JTA `PlatformTransactionManager`, the
|
When Hibernate is configured with awareness of the JTA transaction manager,
|
||||||
following events occur when a JTA transaction commits:
|
the following events occur when a JTA transaction commits:
|
||||||
|
|
||||||
* The JTA transaction is ready to commit.
|
* The JTA transaction is ready to commit.
|
||||||
* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so the
|
* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so the
|
||||||
transaction is called back through a `beforeCompletion` callback by the JTA
|
transaction is called back through a `beforeCompletion` callback by the JTA
|
||||||
transaction manager.
|
transaction manager.
|
||||||
* Spring is aware that Hibernate itself is synchronized to the JTA transaction and
|
* Spring is aware that Hibernate itself is synchronized to the JTA transaction and
|
||||||
behaves differently than in the previous scenario. Assuming the Hibernate `Session`
|
behaves differently than in the previous scenario. In particular, it aligns with
|
||||||
needs to be closed at all, Spring closes it now.
|
Hibernate's transactional resource management.
|
||||||
* The JTA transaction commits.
|
* The JTA transaction commits.
|
||||||
* Hibernate is synchronized to the JTA transaction, so the transaction is called back
|
* Hibernate is synchronized to the JTA transaction, so the transaction is called back
|
||||||
through an `afterCompletion` callback by the JTA transaction manager and can
|
through an `afterCompletion` callback by the JTA transaction manager and can
|
||||||
|
|
@ -7244,13 +7286,13 @@ that is used by the application to obtain an entity manager.
|
||||||
[[orm-jpa-setup-lemfb]]
|
[[orm-jpa-setup-lemfb]]
|
||||||
===== Using `LocalEntityManagerFactoryBean`
|
===== Using `LocalEntityManagerFactoryBean`
|
||||||
|
|
||||||
You can use this option only in simple deployment environments such as stand-alone applications
|
You can use this option only in simple deployment environments such as stand-alone
|
||||||
and integration tests.
|
applications and integration tests.
|
||||||
|
|
||||||
The `LocalEntityManagerFactoryBean` creates an `EntityManagerFactory` suitable for
|
The `LocalEntityManagerFactoryBean` creates an `EntityManagerFactory` suitable for
|
||||||
simple deployment environments where the application uses only JPA for data access. The
|
simple deployment environments where the application uses only JPA for data access.
|
||||||
factory bean uses the JPA `PersistenceProvider` auto-detection mechanism (according to
|
The factory bean uses the JPA `PersistenceProvider` auto-detection mechanism (according
|
||||||
JPA's Java SE bootstrapping) and, in most cases, requires you to specify only the
|
to JPA's Java SE bootstrapping) and, in most cases, requires you to specify only the
|
||||||
persistence unit name. The following XML example configures such a bean:
|
persistence unit name. The following XML example configures such a bean:
|
||||||
|
|
||||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||||
|
|
@ -7734,7 +7776,7 @@ steps:
|
||||||
your transaction coordinator. This is usually straightforward in a Java EE environment,
|
your transaction coordinator. This is usually straightforward in a Java EE environment,
|
||||||
exposing a different kind of `DataSource` through JNDI. See your application server
|
exposing a different kind of `DataSource` through JNDI. See your application server
|
||||||
documentation for details. Analogously, a standalone transaction coordinator usually
|
documentation for details. Analogously, a standalone transaction coordinator usually
|
||||||
comes with special XA-integrated `DataSource` implementations. Again, check its documentation.
|
comes with special XA-integrated `DataSource` variants. Again, check its documentation.
|
||||||
|
|
||||||
* The JPA `EntityManagerFactory` setup needs to be configured for JTA. This is
|
* The JPA `EntityManagerFactory` setup needs to be configured for JTA. This is
|
||||||
provider-specific, typically through special properties to be specified as `jpaProperties`
|
provider-specific, typically through special properties to be specified as `jpaProperties`
|
||||||
|
|
@ -7743,11 +7785,11 @@ are even version-specific. See your Hibernate documentation for details.
|
||||||
|
|
||||||
* Spring's `HibernateJpaVendorAdapter` enforces certain Spring-oriented defaults, such
|
* Spring's `HibernateJpaVendorAdapter` enforces certain Spring-oriented defaults, such
|
||||||
as the connection release mode, `on-close`, which matches Hibernate's own default in
|
as the connection release mode, `on-close`, which matches Hibernate's own default in
|
||||||
Hibernate 5.0 but not any more in 5.1/5.2. For a JTA setup, either do not declare
|
Hibernate 5.0 but not any more in Hibernate 5.1+. For a JTA setup, make sure to declare
|
||||||
`HibernateJpaVendorAdapter` to begin with or turn off its `prepareConnection` flag.
|
your persistence unit transaction type as "JTA". Alternatively, set Hibernate 5.2's
|
||||||
Alternatively, set Hibernate 5.2's `hibernate.connection.handling_mode` property to
|
`hibernate.connection.handling_mode` property to
|
||||||
`DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT` to restore Hibernate's own default.
|
`DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT` to restore Hibernate's own default.
|
||||||
See <<orm-hibernate-invalid-jdbc-access-error>> for a related note about WebLogic.
|
See <<orm-hibernate-invalid-jdbc-access-error>> for related notes.
|
||||||
|
|
||||||
* Alternatively, consider obtaining the `EntityManagerFactory` from your application
|
* Alternatively, consider obtaining the `EntityManagerFactory` from your application
|
||||||
server itself (that is, through a JNDI lookup instead of a locally declared
|
server itself (that is, through a JNDI lookup instead of a locally declared
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue