Merge branch '5.2.x'
# Conflicts: # build.gradle # spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java
This commit is contained in:
commit
b7e1553c9d
|
|
@ -122,8 +122,8 @@ configure(allprojects) { project ->
|
|||
dependency "net.sf.ehcache:ehcache:2.10.6"
|
||||
dependency "org.ehcache:jcache:1.0.1"
|
||||
dependency "org.ehcache:ehcache:3.4.0"
|
||||
dependency "org.hibernate:hibernate-core:5.4.21.Final"
|
||||
dependency "org.hibernate:hibernate-validator:6.1.5.Final"
|
||||
dependency "org.hibernate:hibernate-core:5.4.22.Final"
|
||||
dependency "org.hibernate:hibernate-validator:6.1.6.Final"
|
||||
dependency "org.webjars:webjars-locator-core:0.45"
|
||||
dependency "org.webjars:underscorejs:1.8.3"
|
||||
|
||||
|
|
@ -339,7 +339,7 @@ configure([rootProject] + javaProjects) { project ->
|
|||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "8.36.1"
|
||||
toolVersion = "8.36.2"
|
||||
configDirectory.set(rootProject.file("src/checkstyle"))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -688,6 +688,7 @@ public class GenericConversionService implements ConfigurableConversionService {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -61,12 +61,12 @@ final class MapToMapConverter implements ConditionalGenericConverter {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Object, Object> sourceMap = (Map<Object, Object>) source;
|
||||
|
||||
// Shortcut if possible...
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Converts String to a Boolean.
|
||||
|
|
@ -48,6 +49,7 @@ final class StringToBooleanConverter implements Converter<String, Boolean> {
|
|||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Boolean convert(String source) {
|
||||
String value = source.trim();
|
||||
if (value.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.core.convert.support;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Converts a String to a Character.
|
||||
|
|
@ -27,6 +28,7 @@ import org.springframework.core.convert.converter.Converter;
|
|||
final class StringToCharacterConverter implements Converter<String, Character> {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Character convert(String source) {
|
||||
if (source.isEmpty()) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.springframework.core.convert.support;
|
|||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Converts from a String to a {@link java.lang.Enum} by calling {@link Enum#valueOf(Class, String)}.
|
||||
|
|
@ -44,6 +45,7 @@ final class StringToEnumConverterFactory implements ConverterFactory<String, Enu
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public T convert(String source) {
|
||||
if (source.isEmpty()) {
|
||||
// It's an empty enum identifier: reset the enum value to null.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -18,6 +18,7 @@ package org.springframework.core.convert.support;
|
|||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.NumberUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -55,6 +56,7 @@ final class StringToNumberConverterFactory implements ConverterFactory<String, N
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public T convert(String source) {
|
||||
if (source.isEmpty()) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -272,8 +272,7 @@ public class DefaultStompSession implements ConnectionHandlingStompSession {
|
|||
}
|
||||
|
||||
private boolean isEmpty(@Nullable Object payload) {
|
||||
return payload == null || StringUtils.isEmpty(payload) ||
|
||||
(payload instanceof byte[] && ((byte[]) payload).length == 0);
|
||||
return (StringUtils.isEmpty(payload) || (payload instanceof byte[] && ((byte[]) payload).length == 0));
|
||||
}
|
||||
|
||||
private void execute(Message<byte[]> message) {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor {
|
|||
|
||||
|
||||
/**
|
||||
* Sub-classes can use this method to access the "native" headers sub-map.
|
||||
* Subclasses can use this method to access the "native" headers sub-map.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
|
|
@ -139,6 +139,7 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor {
|
|||
|
||||
/**
|
||||
* Whether the native header map contains the give header name.
|
||||
* @param headerName the name of the header
|
||||
*/
|
||||
public boolean containsNativeHeader(String headerName) {
|
||||
Map<String, List<String>> map = getNativeHeaders();
|
||||
|
|
@ -146,7 +147,9 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the values for the specified native header, if present.
|
||||
* Return all values for the specified native header, if present.
|
||||
* @param headerName the name of the header
|
||||
* @return the associated values, or {@code null} if none
|
||||
*/
|
||||
@Nullable
|
||||
public List<String> getNativeHeader(String headerName) {
|
||||
|
|
@ -156,13 +159,15 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor {
|
|||
|
||||
/**
|
||||
* Return the first value for the specified native header, if present.
|
||||
* @param headerName the name of the header
|
||||
* @return the associated value, or {@code null} if none
|
||||
*/
|
||||
@Nullable
|
||||
public String getFirstNativeHeader(String headerName) {
|
||||
Map<String, List<String>> map = getNativeHeaders();
|
||||
if (map != null) {
|
||||
List<String> values = map.get(headerName);
|
||||
if (values != null) {
|
||||
if (!CollectionUtils.isEmpty(values)) {
|
||||
return values.get(0);
|
||||
}
|
||||
}
|
||||
|
|
@ -200,6 +205,8 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor {
|
|||
* Add the specified native header value to existing values.
|
||||
* <p>In order for this to work, the accessor must be {@link #isMutable()
|
||||
* mutable}. See {@link MessageHeaderAccessor} for details.
|
||||
* @param name the name of the header
|
||||
* @param value the header value to set
|
||||
*/
|
||||
public void addNativeHeader(String name, @Nullable String value) {
|
||||
Assert.state(isMutable(), "Already immutable");
|
||||
|
|
@ -216,6 +223,10 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor {
|
|||
setModified(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the specified native headers to existing values.
|
||||
* @param headers the headers to set
|
||||
*/
|
||||
public void addNativeHeaders(@Nullable MultiValueMap<String, String> headers) {
|
||||
if (headers == null) {
|
||||
return;
|
||||
|
|
@ -227,24 +238,34 @@ public class NativeMessageHeaderAccessor extends MessageHeaderAccessor {
|
|||
* Remove the specified native header value replacing existing values.
|
||||
* <p>In order for this to work, the accessor must be {@link #isMutable()
|
||||
* mutable}. See {@link MessageHeaderAccessor} for details.
|
||||
* @param headerName the name of the header
|
||||
* @return the associated values, or {@code null} if the header was not present
|
||||
*/
|
||||
@Nullable
|
||||
public List<String> removeNativeHeader(String name) {
|
||||
public List<String> removeNativeHeader(String headerName) {
|
||||
Assert.state(isMutable(), "Already immutable");
|
||||
Map<String, List<String>> nativeHeaders = getNativeHeaders();
|
||||
if (nativeHeaders == null) {
|
||||
if (CollectionUtils.isEmpty(nativeHeaders)) {
|
||||
return null;
|
||||
}
|
||||
return nativeHeaders.remove(name);
|
||||
return nativeHeaders.remove(headerName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the first value for the specified native header,
|
||||
* or {@code null} if none.
|
||||
* @param headerName the name of the header
|
||||
* @param headers the headers map to introspect
|
||||
* @return the associated value, or {@code null} if none
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public static String getFirstNativeHeader(String headerName, Map<String, Object> headers) {
|
||||
Map<String, List<String>> map = (Map<String, List<String>>) headers.get(NATIVE_HEADERS);
|
||||
if (map != null) {
|
||||
List<String> values = map.get(headerName);
|
||||
if (values != null) {
|
||||
if (!CollectionUtils.isEmpty(values)) {
|
||||
return values.get(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,6 +211,7 @@ public class LocalSessionFactoryBuilder extends Configuration {
|
|||
"Unknown transaction manager type: " + jtaTransactionManager.getClass().getName());
|
||||
}
|
||||
|
||||
getProperties().put(AvailableSettings.TRANSACTION_COORDINATOR_STRATEGY, "jta");
|
||||
getProperties().put(AvailableSettings.CONNECTION_HANDLING,
|
||||
PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT);
|
||||
|
||||
|
|
|
|||
|
|
@ -700,8 +700,8 @@ public class MockHttpServletRequestBuilder
|
|||
|
||||
String query = this.url.getRawQuery();
|
||||
if (!this.queryParams.isEmpty()) {
|
||||
String s = UriComponentsBuilder.newInstance().queryParams(this.queryParams).build().encode().getQuery();
|
||||
query = StringUtils.isEmpty(query) ? s : query + "&" + s;
|
||||
String str = UriComponentsBuilder.newInstance().queryParams(this.queryParams).build().encode().getQuery();
|
||||
query = StringUtils.hasLength(query) ? (query + "&" + str) : str;
|
||||
}
|
||||
if (query != null) {
|
||||
request.setQueryString(query);
|
||||
|
|
|
|||
|
|
@ -245,10 +245,10 @@ public final class ResponseCookie extends HttpCookie {
|
|||
|
||||
@Nullable
|
||||
private String initDomain(String domain) {
|
||||
if (lenient && !StringUtils.isEmpty(domain)) {
|
||||
String s = domain.trim();
|
||||
if (s.startsWith("\"") && s.endsWith("\"")) {
|
||||
if (s.substring(1, s.length() - 1).trim().isEmpty()) {
|
||||
if (lenient && StringUtils.hasLength(domain)) {
|
||||
String str = domain.trim();
|
||||
if (str.startsWith("\"") && str.endsWith("\"")) {
|
||||
if (str.substring(1, str.length() - 1).trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import org.springframework.core.io.buffer.PooledDataBuffer;
|
|||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ClientHttpRequest} implementation for the Jetty ReactiveStreams HTTP client.
|
||||
|
|
@ -62,9 +61,7 @@ class JettyClientHttpRequest extends AbstractClientHttpRequest {
|
|||
|
||||
@Override
|
||||
public HttpMethod getMethod() {
|
||||
HttpMethod method = HttpMethod.resolve(this.jettyRequest.getMethod());
|
||||
Assert.state(method != null, "Method must not be null");
|
||||
return method;
|
||||
return HttpMethod.valueOf(this.jettyRequest.getMethod());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -122,7 +119,6 @@ class JettyClientHttpRequest extends AbstractClientHttpRequest {
|
|||
public void succeeded() {
|
||||
DataBufferUtils.release(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x) {
|
||||
DataBufferUtils.release(buffer);
|
||||
|
|
|
|||
|
|
@ -381,6 +381,19 @@ NOTE: The preceding definition of the `dataSource` bean uses the `<jndi-lookup/>
|
|||
from the `jee` namespace. For more information see
|
||||
<<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.
|
||||
In this case, you need to define a Hibernate `LocalSessionFactoryBean`, which your
|
||||
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
|
||||
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"]
|
||||
----
|
||||
<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"/>
|
||||
----
|
||||
|
||||
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.
|
||||
Or alternatively, you may pass the `JtaTransactionManager` into your `LocalSessionFactoryBean`
|
||||
for enforcing the same defaults:
|
||||
|
||||
In all these cases, 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.
|
||||
[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}
|
||||
</value>
|
||||
</property>
|
||||
<property name="jtaTransactionManager" ref="txManager"/>
|
||||
</bean>
|
||||
|
||||
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
|
@ -3118,8 +3162,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
|
||||
interfaces, giving them a clearly defined contract. Given a `Connection` provided by the
|
||||
`JdbcTemplate` class, the `PreparedStatementCreator`
|
||||
callback interface creates a prepared statement, providing SQL and any necessary parameters. The same is true for the
|
||||
`JdbcTemplate` class, the `PreparedStatementCreator` callback interface creates a prepared
|
||||
statement, providing SQL and any necessary parameters. The same is true for the
|
||||
`CallableStatementCreator` interface, which creates callable statements. The
|
||||
`RowCallbackHandler` interface extracts values from each row of a `ResultSet`.
|
||||
|
||||
|
|
@ -7800,12 +7844,12 @@ conjunction with EJBs.
|
|||
==== Spurious Application Server Warnings with Hibernate
|
||||
|
||||
In some JTA environments with very strict `XADataSource` implementations (currently
|
||||
only some WebLogic Server and WebSphere versions), when Hibernate is configured without
|
||||
regard to the JTA `PlatformTransactionManager` object for that environment,
|
||||
spurious warning or exceptions can show up in the application server log.
|
||||
These warnings or exceptions indicate that the connection being accessed is no longer
|
||||
valid or JDBC access is no longer valid, possibly because the transaction is no longer
|
||||
active. As an example, here is an actual exception from WebLogic:
|
||||
some WebLogic Server and WebSphere versions), when Hibernate is configured without
|
||||
regard to the JTA transaction manager for that environment, spurious warnings or
|
||||
exceptions can show up in the application server log. These warnings or exceptions
|
||||
indicate that the connection being accessed is no longer valid or JDBC access is no
|
||||
longer valid, possibly because the transaction is no longer active. As an example,
|
||||
here is an actual exception from WebLogic:
|
||||
|
||||
[literal]
|
||||
[subs="verbatim,quotes"]
|
||||
|
|
@ -7814,28 +7858,26 @@ java.sql.SQLException: The transaction is no longer active - status: 'Committed'
|
|||
further JDBC access is allowed within this transaction.
|
||||
----
|
||||
|
||||
You can resolve this warning by making Hibernate aware of the JTA
|
||||
`PlatformTransactionManager` instance, to which it synchronizes (along with Spring).
|
||||
You have two options for doing this:
|
||||
Another common problem is a connection leak after JTA transactions, with Hibernate
|
||||
sessions (and potentially underlying JDBC connections) not getting closed properly.
|
||||
|
||||
* If, in your application context, you already directly obtain the JTA
|
||||
`PlatformTransactionManager` object (presumably from JNDI through
|
||||
`JndiObjectFactoryBean` or `<jee:jndi-lookup>`) and feed it, for example, to
|
||||
Spring's `JtaTransactionManager`, the easiest way is to specify a reference to
|
||||
the bean that defines this JTA `PlatformTransactionManager` instance as the value of the
|
||||
`jtaTransactionManager` property for `LocalSessionFactoryBean.` Spring then makes the
|
||||
object available to Hibernate.
|
||||
* More likely, you do not already have the JTA `PlatformTransactionManager` instance,
|
||||
because Spring's `JtaTransactionManager` can find it itself. Thus, you need to
|
||||
configure Hibernate to look up JTA `PlatformTransactionManager` directly. You do this
|
||||
by configuring an application server-specific `TransactionManagerLookup` class in the
|
||||
Hibernate configuration, as described in the Hibernate manual.
|
||||
You can resolve such issues by making Hibernate aware of the JTA transaction manager,
|
||||
to which it synchronizes (along with Spring). You have two options for doing this:
|
||||
|
||||
* Pass your Spring `JtaTransactionManager` bean to your Hibernate setup. The easiest
|
||||
way is a bean reference into the `jtaTransactionManager` property for your
|
||||
`LocalSessionFactoryBean` bean (see <<transaction-strategies-hibernate>>).
|
||||
Spring then makes the corresponding JTA strategies available to Hibernate.
|
||||
* You may also configure Hibernate's JTA-related properties explicitly, in particular
|
||||
"hibernate.transaction.coordinator_class", "hibernate.connection.handling_mode"
|
||||
and potentially "hibernate.transaction.jta.platform" in your "hibernateProperties"
|
||||
on `LocalSessionFactoryBean` (see Hibernate's manual for details on those properties).
|
||||
|
||||
The remainder of this section describes the sequence of events that occur with and
|
||||
without Hibernate's awareness of the JTA `PlatformTransactionManager`.
|
||||
|
||||
When Hibernate is not configured with any awareness of the JTA
|
||||
`PlatformTransactionManager`, the following events occur when a JTA transaction commits:
|
||||
When Hibernate is not configured with any awareness of the JTA transaction manager,
|
||||
the following events occur when a JTA transaction commits:
|
||||
|
||||
* The JTA transaction commits.
|
||||
* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so it is
|
||||
|
|
@ -7848,16 +7890,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,
|
||||
because the transaction has already been committed.
|
||||
|
||||
When Hibernate is configured with awareness of the JTA `PlatformTransactionManager`, the
|
||||
following events occur when a JTA transaction commits:
|
||||
When Hibernate is configured with awareness of the JTA transaction manager,
|
||||
the following events occur when a JTA transaction commits:
|
||||
|
||||
* The JTA transaction is ready to commit.
|
||||
* Spring's `JtaTransactionManager` is synchronized to the JTA transaction, so the
|
||||
transaction is called back through a `beforeCompletion` callback by the JTA
|
||||
transaction manager.
|
||||
* Spring is aware that Hibernate itself is synchronized to the JTA transaction and
|
||||
behaves differently than in the previous scenario. Assuming the Hibernate `Session`
|
||||
needs to be closed at all, Spring closes it now.
|
||||
behaves differently than in the previous scenario. In particular, it aligns with
|
||||
Hibernate's transactional resource management.
|
||||
* The JTA transaction commits.
|
||||
* Hibernate is synchronized to the JTA transaction, so the transaction is called back
|
||||
through an `afterCompletion` callback by the JTA transaction manager and can
|
||||
|
|
@ -7888,13 +7930,13 @@ that is used by the application to obtain an entity manager.
|
|||
[[orm-jpa-setup-lemfb]]
|
||||
===== Using `LocalEntityManagerFactoryBean`
|
||||
|
||||
You can use this option only in simple deployment environments such as stand-alone applications
|
||||
and integration tests.
|
||||
You can use this option only in simple deployment environments such as stand-alone
|
||||
applications and integration tests.
|
||||
|
||||
The `LocalEntityManagerFactoryBean` creates an `EntityManagerFactory` suitable for
|
||||
simple deployment environments where the application uses only JPA for data access. The
|
||||
factory bean uses the JPA `PersistenceProvider` auto-detection mechanism (according to
|
||||
JPA's Java SE bootstrapping) and, in most cases, requires you to specify only the
|
||||
simple deployment environments where the application uses only JPA for data access.
|
||||
The factory bean uses the JPA `PersistenceProvider` auto-detection mechanism (according
|
||||
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:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
|
|
@ -8378,7 +8420,7 @@ steps:
|
|||
your transaction coordinator. This is usually straightforward in a Java EE environment,
|
||||
exposing a different kind of `DataSource` through JNDI. See your application server
|
||||
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
|
||||
provider-specific, typically through special properties to be specified as `jpaProperties`
|
||||
|
|
@ -8387,11 +8429,11 @@ are even version-specific. See your Hibernate documentation for details.
|
|||
|
||||
* Spring's `HibernateJpaVendorAdapter` enforces certain Spring-oriented defaults, such
|
||||
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
|
||||
`HibernateJpaVendorAdapter` to begin with or turn off its `prepareConnection` flag.
|
||||
Alternatively, set Hibernate 5.2's `hibernate.connection.handling_mode` property to
|
||||
Hibernate 5.0 but not any more in Hibernate 5.1+. For a JTA setup, make sure to declare
|
||||
your persistence unit transaction type as "JTA". Alternatively, set Hibernate 5.2's
|
||||
`hibernate.connection.handling_mode` property to
|
||||
`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
|
||||
server itself (that is, through a JNDI lookup instead of a locally declared
|
||||
|
|
|
|||
Loading…
Reference in New Issue