diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java
index 975eec6925e..65a8bb43c78 100644
--- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java
+++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java
@@ -45,6 +45,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.lang.Nullable;
+import org.springframework.transaction.support.ResourceHolderSupport;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@@ -1117,8 +1118,8 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
criteria.setMaxResults(getMaxResults());
}
- SessionHolder sessionHolder =
- (SessionHolder) TransactionSynchronizationManager.getResource(obtainSessionFactory());
+ ResourceHolderSupport sessionHolder =
+ (ResourceHolderSupport) TransactionSynchronizationManager.getResource(obtainSessionFactory());
if (sessionHolder != null && sessionHolder.hasTimeout()) {
criteria.setTimeout(sessionHolder.getTimeToLiveInSeconds());
}
@@ -1146,8 +1147,8 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
queryObject.setMaxResults(getMaxResults());
}
- SessionHolder sessionHolder =
- (SessionHolder) TransactionSynchronizationManager.getResource(obtainSessionFactory());
+ ResourceHolderSupport sessionHolder =
+ (ResourceHolderSupport) TransactionSynchronizationManager.getResource(obtainSessionFactory());
if (sessionHolder != null && sessionHolder.hasTimeout()) {
queryObject.setTimeout(sessionHolder.getTimeToLiveInSeconds());
}
diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SessionHolder.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SessionHolder.java
index 591a19fad2e..556f58c9a3c 100644
--- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SessionHolder.java
+++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SessionHolder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -16,18 +16,20 @@
package org.springframework.orm.hibernate5;
+import javax.persistence.EntityManager;
+
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.lang.Nullable;
-import org.springframework.transaction.support.ResourceHolderSupport;
-import org.springframework.util.Assert;
+import org.springframework.orm.jpa.EntityManagerHolder;
/**
- * Session holder, wrapping a Hibernate Session and a Hibernate Transaction.
- * HibernateTransactionManager binds instances of this class to the thread,
- * for a given SessionFactory.
+ * Resource holder wrapping a Hibernate {@link Session} (plus an optional {@link Transaction}).
+ * {@link HibernateTransactionManager} binds instances of this class to the thread,
+ * for a given {@link org.hibernate.SessionFactory}. Extends {@link EntityManagerHolder}
+ * as of 5.1, automatically exposing an {@code EntityManager} handle on Hibernate 5.2+.
*
*
Note: This is an SPI class, not intended to be used by applications.
*
@@ -36,7 +38,7 @@ import org.springframework.util.Assert;
* @see HibernateTransactionManager
* @see SessionFactoryUtils
*/
-public class SessionHolder extends ResourceHolderSupport {
+public class SessionHolder extends EntityManagerHolder {
private final Session session;
@@ -48,7 +50,7 @@ public class SessionHolder extends ResourceHolderSupport {
public SessionHolder(Session session) {
- Assert.notNull(session, "Session must not be null");
+ super(EntityManager.class.isInstance(session) ? session : null);
this.session = session;
}
@@ -59,6 +61,7 @@ public class SessionHolder extends ResourceHolderSupport {
public void setTransaction(@Nullable Transaction transaction) {
this.transaction = transaction;
+ setTransactionActive(transaction != null);
}
@Nullable
diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringSessionContext.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringSessionContext.java
index df7dd0cb5f1..1b7b6d89bf0 100644
--- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringSessionContext.java
+++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringSessionContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -29,12 +29,13 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.springframework.lang.Nullable;
+import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
- * Implementation of Hibernate 3.1's CurrentSessionContext interface
- * that delegates to Spring's SessionFactoryUtils for providing a
- * Spring-managed current Session.
+ * Implementation of Hibernate 3.1's {@link CurrentSessionContext} interface
+ * that delegates to Spring's {@link SessionFactoryUtils} for providing a
+ * Spring-managed current {@link Session}.
*
*
This CurrentSessionContext implementation can also be specified in custom
* SessionFactory setup through the "hibernate.current_session_context_class"
@@ -86,6 +87,7 @@ public class SpringSessionContext implements CurrentSessionContext {
return (Session) value;
}
else if (value instanceof SessionHolder) {
+ // HibernateTransactionManager
SessionHolder sessionHolder = (SessionHolder) value;
Session session = sessionHolder.getSession();
if (!sessionHolder.isSynchronizedWithTransaction() &&
@@ -104,13 +106,18 @@ public class SpringSessionContext implements CurrentSessionContext {
}
return session;
}
+ else if (value instanceof EntityManagerHolder) {
+ // JpaTransactionManager
+ return ((EntityManagerHolder) value).getEntityManager().unwrap(Session.class);
+ }
if (this.transactionManager != null && this.jtaSessionContext != null) {
try {
if (this.transactionManager.getStatus() == Status.STATUS_ACTIVE) {
Session session = this.jtaSessionContext.currentSession();
if (TransactionSynchronizationManager.isSynchronizationActive()) {
- TransactionSynchronizationManager.registerSynchronization(new SpringFlushSynchronization(session));
+ TransactionSynchronizationManager.registerSynchronization(
+ new SpringFlushSynchronization(session));
}
return session;
}
diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerHolder.java b/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerHolder.java
index 9dcb4094126..0f8fbd7f424 100644
--- a/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerHolder.java
+++ b/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerHolder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -24,9 +24,12 @@ import org.springframework.transaction.support.ResourceHolderSupport;
import org.springframework.util.Assert;
/**
- * Holder wrapping a JPA EntityManager.
- * JpaTransactionManager binds instances of this class to the thread,
- * for a given EntityManagerFactory.
+ * Resource holder wrapping a JPA {@link EntityManager}.
+ * {@link JpaTransactionManager} binds instances of this class to the thread,
+ * for a given {@link javax.persistence.EntityManagerFactory}.
+ *
+ *
Also serves as a base class for {@link org.springframework.orm.hibernate5.SessionHolder},
+ * as of 5.1.
*
*
Note: This is an SPI class, not intended to be used by applications.
*
@@ -37,6 +40,7 @@ import org.springframework.util.Assert;
*/
public class EntityManagerHolder extends ResourceHolderSupport {
+ @Nullable
private final EntityManager entityManager;
private boolean transactionActive;
@@ -45,13 +49,13 @@ public class EntityManagerHolder extends ResourceHolderSupport {
private SavepointManager savepointManager;
- public EntityManagerHolder(EntityManager entityManager) {
- Assert.notNull(entityManager, "EntityManager must not be null");
+ public EntityManagerHolder(@Nullable EntityManager entityManager) {
this.entityManager = entityManager;
}
public EntityManager getEntityManager() {
+ Assert.state(this.entityManager != null, "No EntityManager available");
return this.entityManager;
}
diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/AbstractContainerEntityManagerFactoryIntegrationTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/AbstractContainerEntityManagerFactoryIntegrationTests.java
index cd249657ef7..6c74ded9627 100644
--- a/spring-orm/src/test/java/org/springframework/orm/jpa/AbstractContainerEntityManagerFactoryIntegrationTests.java
+++ b/spring-orm/src/test/java/org/springframework/orm/jpa/AbstractContainerEntityManagerFactoryIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -19,7 +19,6 @@ package org.springframework.orm.jpa;
import java.lang.reflect.Proxy;
import java.util.List;
import javax.persistence.EntityManager;
-import javax.persistence.EntityNotFoundException;
import javax.persistence.FlushModeType;
import javax.persistence.NoResultException;
import javax.persistence.Query;
@@ -39,14 +38,14 @@ import static org.junit.Assert.*;
* @author Rod Johnson
* @author Juergen Hoeller
*/
-public abstract class AbstractContainerEntityManagerFactoryIntegrationTests extends AbstractEntityManagerFactoryIntegrationTests {
+public abstract class AbstractContainerEntityManagerFactoryIntegrationTests
+ extends AbstractEntityManagerFactoryIntegrationTests {
@Test
public void testEntityManagerFactoryImplementsEntityManagerFactoryInfo() {
- assertTrue(Proxy.isProxyClass(entityManagerFactory.getClass()));
assertTrue("Must have introduced config interface", entityManagerFactory instanceof EntityManagerFactoryInfo);
EntityManagerFactoryInfo emfi = (EntityManagerFactoryInfo) entityManagerFactory;
- // assertEquals("Person", emfi.getPersistenceUnitName());
+ assertEquals("Person", emfi.getPersistenceUnitName());
assertNotNull("PersistenceUnitInfo must be available", emfi.getPersistenceUnitInfo());
assertNotNull("Raw EntityManagerFactory must be available", emfi.getNativeEntityManagerFactory());
}
@@ -78,7 +77,7 @@ public abstract class AbstractContainerEntityManagerFactoryIntegrationTests exte
}
@Test
- @SuppressWarnings({ "unused", "unchecked" })
+ @SuppressWarnings("unchecked")
public void testEntityManagerProxyIsProxy() {
assertTrue(Proxy.isProxyClass(sharedEntityManager.getClass()));
Query q = sharedEntityManager.createQuery("select p from Person as p");
@@ -107,14 +106,13 @@ public abstract class AbstractContainerEntityManagerFactoryIntegrationTests exte
try {
Person notThere = sharedEntityManager.getReference(Person.class, 666);
- // We may get here (as with Hibernate).
- // Either behaviour is valid: throw exception on first access
- // or on getReference itself.
+ // We may get here (as with Hibernate). Either behaviour is valid:
+ // throw exception on first access or on getReference itself.
notThere.getFirstName();
- fail("Should have thrown an EntityNotFoundException");
+ fail("Should have thrown an EntityNotFoundException or ObjectNotFoundException");
}
- catch (EntityNotFoundException ex) {
- // expected
+ catch (Exception ex) {
+ assertTrue(ex.getClass().getName().endsWith("NotFoundException"));
}
}
@@ -209,6 +207,8 @@ public abstract class AbstractContainerEntityManagerFactoryIntegrationTests exte
@Test
@SuppressWarnings("unchecked")
public void testQueryNoPersonsNotTransactional() {
+ endTransaction();
+
EntityManager em = entityManagerFactory.createEntityManager();
Query q = em.createQuery("select p from Person as p");
List people = q.getResultList();
@@ -223,12 +223,12 @@ public abstract class AbstractContainerEntityManagerFactoryIntegrationTests exte
}
@Test
- @SuppressWarnings({ "unused", "unchecked" })
+ @SuppressWarnings("unchecked")
public void testQueryNoPersonsShared() {
- EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory);
- Query q = em.createQuery("select p from Person as p");
+ Query q = this.sharedEntityManager.createQuery("select p from Person as p");
q.setFlushMode(FlushModeType.AUTO);
List people = q.getResultList();
+ assertEquals(0, people.size());
try {
assertNull(q.getSingleResult());
fail("Should have thrown NoResultException");
@@ -243,7 +243,7 @@ public abstract class AbstractContainerEntityManagerFactoryIntegrationTests exte
public void testQueryNoPersonsSharedNotTransactional() {
endTransaction();
- EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory);
+ EntityManager em = this.sharedEntityManager;
Query q = em.createQuery("select p from Person as p");
q.setFlushMode(FlushModeType.AUTO);
List people = q.getResultList();
diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryIntegrationTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryIntegrationTests.java
index 7848387adfe..4c2a1d0d69e 100644
--- a/spring-orm/src/test/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryIntegrationTests.java
+++ b/spring-orm/src/test/java/org/springframework/orm/jpa/AbstractEntityManagerFactoryIntegrationTests.java
@@ -48,12 +48,8 @@ import static org.junit.Assert.*;
public abstract class AbstractEntityManagerFactoryIntegrationTests {
protected static final String[] ECLIPSELINK_CONFIG_LOCATIONS = new String[] {
- "/org/springframework/orm/jpa/eclipselink/eclipselink-manager.xml", "/org/springframework/orm/jpa/memdb.xml",
- "/org/springframework/orm/jpa/inject.xml"};
-
- protected static final String[] HIBERNATE_CONFIG_LOCATIONS = new String[] {
- "/org/springframework/orm/jpa/hibernate/hibernate-manager.xml", "/org/springframework/orm/jpa/memdb.xml",
- "/org/springframework/orm/jpa/inject.xml"};
+ "/org/springframework/orm/jpa/eclipselink/eclipselink-manager.xml",
+ "/org/springframework/orm/jpa/memdb.xml", "/org/springframework/orm/jpa/inject.xml"};
private static ConfigurableApplicationContext applicationContext;
diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/eclipselink/EclipseLinkEntityManagerFactoryIntegrationTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/eclipselink/EclipseLinkEntityManagerFactoryIntegrationTests.java
index b01afaa547a..7324d348528 100644
--- a/spring-orm/src/test/java/org/springframework/orm/jpa/eclipselink/EclipseLinkEntityManagerFactoryIntegrationTests.java
+++ b/spring-orm/src/test/java/org/springframework/orm/jpa/eclipselink/EclipseLinkEntityManagerFactoryIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -31,12 +31,6 @@ import static org.junit.Assert.*;
*/
public class EclipseLinkEntityManagerFactoryIntegrationTests extends AbstractContainerEntityManagerFactoryIntegrationTests {
- @Override
- protected String[] getConfigLocations() {
- return ECLIPSELINK_CONFIG_LOCATIONS;
- }
-
-
@Test
public void testCanCastNativeEntityManagerFactoryToEclipseLinkEntityManagerFactoryImpl() {
EntityManagerFactoryInfo emfi = (EntityManagerFactoryInfo) entityManagerFactory;
diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateEntityManagerFactoryIntegrationTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateEntityManagerFactoryIntegrationTests.java
index c1e7d6f4bf5..85bea60131f 100644
--- a/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateEntityManagerFactoryIntegrationTests.java
+++ b/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateEntityManagerFactoryIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2017 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -41,7 +41,8 @@ public class HibernateEntityManagerFactoryIntegrationTests extends AbstractConta
@Override
protected String[] getConfigLocations() {
- return HIBERNATE_CONFIG_LOCATIONS;
+ return new String[] {"/org/springframework/orm/jpa/hibernate/hibernate-manager.xml",
+ "/org/springframework/orm/jpa/memdb.xml", "/org/springframework/orm/jpa/inject.xml"};
}
diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateMultiEntityManagerFactoryIntegrationTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateMultiEntityManagerFactoryIntegrationTests.java
index a30127ef1de..c6765eb47dc 100644
--- a/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateMultiEntityManagerFactoryIntegrationTests.java
+++ b/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateMultiEntityManagerFactoryIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2018 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.
@@ -23,6 +23,7 @@ import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.jpa.AbstractContainerEntityManagerFactoryIntegrationTests;
+import org.springframework.orm.jpa.EntityManagerFactoryInfo;
import static org.junit.Assert.*;
@@ -44,6 +45,15 @@ public class HibernateMultiEntityManagerFactoryIntegrationTests extends Abstract
}
+ @Test
+ public void testEntityManagerFactoryImplementsEntityManagerFactoryInfo() {
+ assertTrue("Must have introduced config interface", this.entityManagerFactory instanceof EntityManagerFactoryInfo);
+ EntityManagerFactoryInfo emfi = (EntityManagerFactoryInfo) this.entityManagerFactory;
+ assertEquals("Drivers", emfi.getPersistenceUnitName());
+ assertNotNull("PersistenceUnitInfo must be available", emfi.getPersistenceUnitInfo());
+ assertNotNull("Raw EntityManagerFactory must be available", emfi.getNativeEntityManagerFactory());
+ }
+
@Test
public void testEntityManagerFactory2() {
EntityManager em = this.entityManagerFactory2.createEntityManager();
diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateNativeEntityManagerFactoryIntegrationTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateNativeEntityManagerFactoryIntegrationTests.java
new file mode 100644
index 00000000000..b623363f223
--- /dev/null
+++ b/spring-orm/src/test/java/org/springframework/orm/jpa/hibernate/HibernateNativeEntityManagerFactoryIntegrationTests.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2002-2018 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.jpa.hibernate;
+
+import java.util.List;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.query.Query;
+import org.junit.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.orm.jpa.AbstractContainerEntityManagerFactoryIntegrationTests;
+import org.springframework.orm.jpa.EntityManagerFactoryInfo;
+import org.springframework.orm.jpa.domain.Person;
+
+import static org.junit.Assert.*;
+
+/**
+ * Hibernate-specific JPA tests with native SessionFactory setup and getCurrentSession interaction.
+ *
+ * @author Juergen Hoeller
+ * @since 5.1
+ */
+public class HibernateNativeEntityManagerFactoryIntegrationTests extends AbstractContainerEntityManagerFactoryIntegrationTests {
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+
+ @Override
+ protected String[] getConfigLocations() {
+ return new String[] {"/org/springframework/orm/jpa/hibernate/hibernate-manager-native.xml",
+ "/org/springframework/orm/jpa/memdb.xml", "/org/springframework/orm/jpa/inject.xml"};
+ }
+
+
+ @Test
+ public void testEntityManagerFactoryImplementsEntityManagerFactoryInfo() {
+ assertFalse("Must not have introduced config interface", entityManagerFactory instanceof EntityManagerFactoryInfo);
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testCurrentSession() {
+ // Add with JDBC
+ String firstName = "Tony";
+ insertPerson(firstName);
+
+ Query q = sessionFactory.getCurrentSession().createQuery("select p from Person as p");
+ List people = q.getResultList();
+
+ assertEquals(1, people.size());
+ assertEquals(firstName, people.get(0).getFirstName());
+ }
+
+}
diff --git a/spring-orm/src/test/resources/org/springframework/orm/jpa/eclipselink/eclipselink-manager.xml b/spring-orm/src/test/resources/org/springframework/orm/jpa/eclipselink/eclipselink-manager.xml
index ecc5a2b6747..7eeffe60a21 100644
--- a/spring-orm/src/test/resources/org/springframework/orm/jpa/eclipselink/eclipselink-manager.xml
+++ b/spring-orm/src/test/resources/org/springframework/orm/jpa/eclipselink/eclipselink-manager.xml
@@ -24,4 +24,8 @@
+
+
+
+
diff --git a/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager-multi.xml b/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager-multi.xml
index 0f626d29547..0338b85d4d3 100644
--- a/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager-multi.xml
+++ b/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager-multi.xml
@@ -22,5 +22,9 @@
-
+
+
+
+
+
diff --git a/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager-native.xml b/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager-native.xml
new file mode 100644
index 00000000000..8944d5adaeb
--- /dev/null
+++ b/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager-native.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ org.springframework.orm.jpa.domain.DriversLicense
+ org.springframework.orm.jpa.domain.Person
+
+
+
+
+
+ org.hibernate.dialect.HSQLDialect
+ update
+ org.hibernate.cache.HashtableCacheProvider
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager.xml b/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager.xml
index bafddcbd5c2..0e763eeb747 100644
--- a/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager.xml
+++ b/spring-orm/src/test/resources/org/springframework/orm/jpa/hibernate/hibernate-manager.xml
@@ -15,6 +15,7 @@
+ org.springframework.orm.hibernate5.SpringSessionContext
org.hibernate.cache.HashtableCacheProvider
@@ -23,6 +24,10 @@
+
+
+
+
diff --git a/spring-orm/src/test/resources/org/springframework/orm/jpa/memdb.xml b/spring-orm/src/test/resources/org/springframework/orm/jpa/memdb.xml
index 247c28f7f6e..8b720dc3e34 100644
--- a/spring-orm/src/test/resources/org/springframework/orm/jpa/memdb.xml
+++ b/spring-orm/src/test/resources/org/springframework/orm/jpa/memdb.xml
@@ -7,10 +7,6 @@
-
-
-
-
@@ -18,14 +14,4 @@
-
-
diff --git a/src/docs/asciidoc/data-access.adoc b/src/docs/asciidoc/data-access.adoc
index b09a8840fca..59add5267ed 100644
--- a/src/docs/asciidoc/data-access.adoc
+++ b/src/docs/asciidoc/data-access.adoc
@@ -5649,6 +5649,12 @@ application uses to refer to them, for example, in `@PersistenceUnit` and
Use this option for full JPA capabilities in a Spring-based application environment.
This includes web containers such as Tomcat as well as stand-alone applications and
integration tests with sophisticated persistence requirements.
+
+If you'd like to specifically configure a Hibernate setup, an immediate alternative is
+to go with Hibernate 5.2/5.3 and set up a native Hibernate `LocalSessionFactoryBean`
+instead of a plain JPA `LocalContainerEntityManagerFactoryBean`, letting it interact
+with JPA access code as well as native Hibernate access code.
+See <> for details.
====
The `LocalContainerEntityManagerFactoryBean` gives full control over
@@ -5979,6 +5985,15 @@ to JDBC access code that accesses the same `DataSource`, provided that the regis
Spring provides dialects for the EclipseLink and Hibernate JPA implementations.
See the next section for details on the `JpaDialect` mechanism.
+[NOTE]
+====
+As an immediate alternative, Spring's native `HibernateTransactionManager` is capable
+of interacting with JPA access code as of Spring Framework 5.1 and Hibernate 5.2/5.3,
+adapting to several Hibernate specifics and providing JDBC interaction out of the box.
+This makes particular sense in combination with `LocalSessionFactoryBean` setup.
+See <> for details.
+====
+
[[orm-jpa-dialect]]
==== JpaDialect and JpaVendorAdapter
@@ -6048,6 +6063,31 @@ might require special definitions in your server configuration, making the deplo
less portable, but will be set up for the server's JTA environment out of the box.
+[[orm-jpa-hibernate]]
+==== Native Hibernate setup and native Hibernate transactions for JPA interaction
+
+As of Spring Framework 5.1 and Hibernate 5.2/5.3, a native `LocalSessionFactoryBean`
+setup in combination with `HibernateTransactionManager` allows for interaction with
+`@PersistenceContext` and other JPA access code out of the box. A Hibernate
+`SessionFactory` natively implements JPA's `EntityManagerFactory` interface now,
+and a Hibernate `Session` handle natively is a JPA `EntityManager` as well.
+Spring's JPA support facilities automatically detect native Hibernate Sessions.
+
+Such native Hibernate setup can therefore serve as a replacement for a standard JPA
+`LocalContainerEntityManagerFactoryBean` and `JpaTransactionManager` combination
+in many scenarios, allowing for interaction with `SessionFactory.getCurrentSession()`
+(and also `HibernateTemplate`) next to `@PersistenceContext EntityManager` within
+the same local transaction. Such a setup also provides stronger Hibernate integration
+and more configuration flexibility, not being constrained by JPA bootstrap contracts.
+
+There is no need for `HibernateJpaVendorAdapter` configuration in such a scenario
+since Spring's native Hibernate setup provides even more features out of the box:
+e.g. custom Hibernate Integrator setup, Hibernate 5.3 bean container integration,
+as well as stronger optimizations for read-only transactions. Last but not least,
+native Hibernate setup can also be expressed through `LocalSessionFactoryBuilder`,
+seamlessly integrating with `@Bean` style configuration (no `FactoryBean` involved).
+
+
[[oxm]]