Upgrade Hibernate support baseline to 5.2+

Closes gh-25533
Closes gh-22326
This commit is contained in:
Juergen Hoeller 2020-08-05 14:14:31 +02:00
parent b6d2a2980d
commit ba65cef52b
10 changed files with 50 additions and 183 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 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.
@ -60,7 +60,7 @@ import org.springframework.lang.Nullable;
* general {@link #execute} method and custom lambda blocks creating the queries,
* ideally setting named parameters through {@link org.hibernate.query.Query}.
* <b>Please be aware that deprecated operations are known to work with Hibernate
* ORM 5.0-5.2 but may not work with Hibernate ORM 5.3 and higher anymore.</b>
* ORM 5.2 but may not work with Hibernate ORM 5.3 and higher anymore.</b>
*
* @author Juergen Hoeller
* @since 4.2

View File

@ -41,6 +41,7 @@ import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.hibernate.query.Query;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
@ -49,7 +50,6 @@ 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;
/**
* Helper class that simplifies Hibernate data access code. Automatically
@ -90,23 +90,6 @@ import org.springframework.util.ReflectionUtils;
*/
public class HibernateTemplate implements HibernateOperations, InitializingBean {
private static final Method createQueryMethod;
private static final Method getNamedQueryMethod;
static {
// Hibernate 5.2's createQuery method declares a new subtype as return type,
// so we need to use reflection for binary compatibility with 5.0/5.1 here.
try {
createQueryMethod = Session.class.getMethod("createQuery", String.class);
getNamedQueryMethod = Session.class.getMethod("getNamedQuery", String.class);
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Incompatible Hibernate Session API", ex);
}
}
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
@ -250,7 +233,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
* <p>To specify the query region to be used for queries cached
* by this template, set the "queryCacheRegion" property.
* @see #setQueryCacheRegion
* @see org.hibernate.Query#setCacheable
* @see Query#setCacheable
* @see Criteria#setCacheable
*/
public void setCacheQueries(boolean cacheQueries) {
@ -271,7 +254,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
* <p>The cache region will not take effect unless queries created by this
* template are configured to be cached via the "cacheQueries" property.
* @see #setCacheQueries
* @see org.hibernate.Query#setCacheRegion
* @see Query#setCacheRegion
* @see Criteria#setCacheRegion
*/
public void setQueryCacheRegion(@Nullable String queryCacheRegion) {
@ -359,7 +342,6 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException in case of Hibernate errors
*/
@SuppressWarnings("deprecation")
@Nullable
protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNativeSession) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
@ -374,7 +356,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}
if (session == null) {
session = obtainSessionFactory().openSession();
session.setFlushMode(FlushMode.MANUAL);
session.setHibernateFlushMode(FlushMode.MANUAL);
isNew = true;
}
@ -543,7 +525,6 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}
@Override
@SuppressWarnings({"deprecation"})
public void load(Object entity, Serializable id) throws DataAccessException {
executeWithNativeSession(session -> {
session.load(entity, id);
@ -887,11 +868,9 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
@Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List<?> find(String queryString, @Nullable Object... values) throws DataAccessException {
return nonNull(executeWithNativeSession((HibernateCallback<List<?>>) session -> {
org.hibernate.Query queryObject = queryObject(
ReflectionUtils.invokeMethod(createQueryMethod, session, queryString));
Query<?> queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
@ -912,7 +891,6 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
@Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List<?> findByNamedParam(String queryString, String[] paramNames, Object[] values)
throws DataAccessException {
@ -920,8 +898,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
throw new IllegalArgumentException("Length of paramNames array must match length of values array");
}
return nonNull(executeWithNativeSession((HibernateCallback<List<?>>) session -> {
org.hibernate.Query queryObject = queryObject(
ReflectionUtils.invokeMethod(createQueryMethod, session, queryString));
Query<?> queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
for (int i = 0; i < values.length; i++) {
applyNamedParameterToQuery(queryObject, paramNames[i], values[i]);
@ -932,12 +909,9 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
@Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List<?> findByValueBean(String queryString, Object valueBean) throws DataAccessException {
return nonNull(executeWithNativeSession((HibernateCallback<List<?>>) session -> {
org.hibernate.Query queryObject = queryObject(
ReflectionUtils.invokeMethod(createQueryMethod, session, queryString));
Query<?> queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
queryObject.setProperties(valueBean);
return queryObject.list();
@ -951,11 +925,9 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
@Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List<?> findByNamedQuery(String queryName, @Nullable Object... values) throws DataAccessException {
return nonNull(executeWithNativeSession((HibernateCallback<List<?>>) session -> {
org.hibernate.Query queryObject = queryObject(
ReflectionUtils.invokeMethod(getNamedQueryMethod, session, queryName));
Query<?> queryObject = session.getNamedQuery(queryName);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
@ -976,7 +948,6 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
@Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List<?> findByNamedQueryAndNamedParam(
String queryName, @Nullable String[] paramNames, @Nullable Object[] values)
throws DataAccessException {
@ -985,8 +956,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
throw new IllegalArgumentException("Length of paramNames array must match length of values array");
}
return nonNull(executeWithNativeSession((HibernateCallback<List<?>>) session -> {
org.hibernate.Query queryObject = (org.hibernate.Query)
nonNull(ReflectionUtils.invokeMethod(getNamedQueryMethod, session, queryName));
Query<?> queryObject = session.getNamedQuery(queryName);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
@ -999,12 +969,9 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
@Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List<?> findByNamedQueryAndValueBean(String queryName, Object valueBean) throws DataAccessException {
return nonNull(executeWithNativeSession((HibernateCallback<List<?>>) session -> {
org.hibernate.Query queryObject = queryObject(
ReflectionUtils.invokeMethod(getNamedQueryMethod, session, queryName));
Query<?> queryObject = session.getNamedQuery(queryName);
prepareQuery(queryObject);
queryObject.setProperties(valueBean);
return queryObject.list();
@ -1018,11 +985,9 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
@Deprecated
@Override
@SuppressWarnings({"rawtypes", "deprecation"})
public Iterator<?> iterate(String queryString, @Nullable Object... values) throws DataAccessException {
return nonNull(executeWithNativeSession((HibernateCallback<Iterator<?>>) session -> {
org.hibernate.Query queryObject = queryObject(
ReflectionUtils.invokeMethod(createQueryMethod, session, queryString));
Query<?> queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
@ -1046,11 +1011,9 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
@Deprecated
@Override
@SuppressWarnings({"rawtypes", "deprecation"})
public int bulkUpdate(String queryString, @Nullable Object... values) throws DataAccessException {
Integer result = executeWithNativeSession(session -> {
org.hibernate.Query queryObject = queryObject(
ReflectionUtils.invokeMethod(createQueryMethod, session, queryString));
Query<?> queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
@ -1079,7 +1042,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
* @see FlushMode#MANUAL
*/
protected void checkWriteOperationAllowed(Session session) throws InvalidDataAccessApiUsageException {
if (isCheckWriteOperations() && SessionFactoryUtils.getFlushMode(session).lessThan(FlushMode.COMMIT)) {
if (isCheckWriteOperations() && session.getHibernateFlushMode().lessThan(FlushMode.COMMIT)) {
throw new InvalidDataAccessApiUsageException(
"Write operations are not allowed in read-only mode (FlushMode.MANUAL): "+
"Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.");
@ -1121,8 +1084,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
* @see #setCacheQueries
* @see #setQueryCacheRegion
*/
@SuppressWarnings({"rawtypes", "deprecation"})
protected void prepareQuery(org.hibernate.Query queryObject) {
protected void prepareQuery(Query<?> queryObject) {
if (isCacheQueries()) {
queryObject.setCacheable(true);
if (getQueryCacheRegion() != null) {
@ -1150,9 +1112,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
* @param value the value of the parameter
* @throws HibernateException if thrown by the Query object
*/
@Deprecated
@SuppressWarnings({"rawtypes", "deprecation"})
protected void applyNamedParameterToQuery(org.hibernate.Query queryObject, String paramName, Object value)
protected void applyNamedParameterToQuery(Query<?> queryObject, String paramName, Object value)
throws HibernateException {
if (value instanceof Collection) {
@ -1166,13 +1126,6 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}
}
@Deprecated
@SuppressWarnings({"rawtypes", "deprecation"})
private static org.hibernate.Query queryObject(@Nullable Object result) {
Assert.state(result != null, "No Hibernate Query");
return (org.hibernate.Query) result;
}
private static <T> T nonNull(@Nullable T result) {
Assert.state(result != null, "No result");
return result;
@ -1193,7 +1146,6 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}
@Override
@SuppressWarnings({"rawtypes", "deprecation"})
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on Session interface coming in...
@ -1219,8 +1171,8 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
if (retVal instanceof Criteria) {
prepareCriteria(((Criteria) retVal));
}
else if (retVal instanceof org.hibernate.Query) {
prepareQuery(((org.hibernate.Query) retVal));
else if (retVal instanceof Query) {
prepareQuery(((Query<?>) retVal));
}
return retVal;

View File

@ -533,7 +533,7 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
if (!definition.isReadOnly() && !txObject.isNewSession()) {
// We need AUTO or COMMIT for a non-read-only transaction.
FlushMode flushMode = SessionFactoryUtils.getFlushMode(session);
FlushMode flushMode = session.getHibernateFlushMode();
if (FlushMode.MANUAL.equals(flushMode)) {
session.setFlushMode(FlushMode.AUTO);
txObject.getSessionHolder().setPreviousFlushMode(flushMode);
@ -562,10 +562,7 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
if (getDataSource() != null) {
SessionImplementor sessionImpl = (SessionImplementor) session;
// The following needs to use a lambda expression instead of a method reference
// for compatibility with Hibernate ORM <5.2 where connection() is defined on
// SessionImplementor itself instead of on SharedSessionContractImplementor...
ConnectionHolder conHolder = new ConnectionHolder(() -> sessionImpl.connection());
ConnectionHolder conHolder = new ConnectionHolder(sessionImpl::connection);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
conHolder.setTimeoutInSeconds(timeout);
}

View File

@ -58,8 +58,8 @@ import org.springframework.util.ClassUtils;
* way to set up a shared Hibernate SessionFactory in a Spring application context; the
* SessionFactory can then be passed to data access objects via dependency injection.
*
* <p>Compatible with Hibernate 5.0/5.1 as well as 5.2/5.3/5.4, as of Spring 5.2.
* Set up with Hibernate 5.2+, {@code LocalSessionFactoryBean} is an immediate alternative
* <p>Compatible with Hibernate 5.2/5.3/5.4, as of Spring 5.3.
* This Hibernate-specific {@code LocalSessionFactoryBean} can be an immediate alternative
* to {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean} for common
* JPA purposes: In particular with Hibernate 5.3/5.4, the Hibernate {@code SessionFactory}
* will natively expose the JPA {@code EntityManagerFactory} interface as well, and

View File

@ -47,6 +47,7 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.InfrastructureProxy;
@ -76,8 +77,8 @@ import org.springframework.util.ClassUtils;
* Typically combined with {@link HibernateTransactionManager} for declarative
* transactions against the {@code SessionFactory} and its JDBC {@code DataSource}.
*
* <p>Compatible with Hibernate 5.0/5.1 as well as 5.2/5.3/5.4, as of Spring 5.2.
* Set up with Hibernate 5.2+, this builder is also a convenient way to set up
* <p>Compatible with Hibernate 5.2/5.3/5.4, as of Spring 5.3.
* This Hibernate-specific factory builder can also be a convenient way to set up
* a JPA {@code EntityManagerFactory} since the Hibernate {@code SessionFactory}
* natively exposes the JPA {@code EntityManagerFactory} interface as well now.
*
@ -162,23 +163,8 @@ public class LocalSessionFactoryBuilder extends Configuration {
if (dataSource != null) {
getProperties().put(AvailableSettings.DATASOURCE, dataSource);
}
// Hibernate 5.1/5.2: manually enforce connection release mode ON_CLOSE (the former default)
try {
// Try Hibernate 5.2
AvailableSettings.class.getField("CONNECTION_HANDLING");
getProperties().put("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_HOLD");
}
catch (NoSuchFieldException ex) {
// Try Hibernate 5.1
try {
AvailableSettings.class.getField("ACQUIRE_CONNECTIONS");
getProperties().put("hibernate.connection.release_mode", "ON_CLOSE");
}
catch (NoSuchFieldException ex2) {
// on Hibernate 5.0.x or lower - no need to change the default there
}
}
getProperties().put(AvailableSettings.CONNECTION_HANDLING,
PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_HOLD);
getProperties().put(AvailableSettings.CLASSLOADERS, Collections.singleton(resourceLoader.getClassLoader()));
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
@ -225,22 +211,8 @@ public class LocalSessionFactoryBuilder extends Configuration {
"Unknown transaction manager type: " + jtaTransactionManager.getClass().getName());
}
// Hibernate 5.1/5.2: manually enforce connection release mode AFTER_STATEMENT (the JTA default)
try {
// Try Hibernate 5.2
AvailableSettings.class.getField("CONNECTION_HANDLING");
getProperties().put("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT");
}
catch (NoSuchFieldException ex) {
// Try Hibernate 5.1
try {
AvailableSettings.class.getField("ACQUIRE_CONNECTIONS");
getProperties().put("hibernate.connection.release_mode", "AFTER_STATEMENT");
}
catch (NoSuchFieldException ex2) {
// on Hibernate 5.0.x or lower - no need to change the default there
}
}
getProperties().put(AvailableSettings.CONNECTION_HANDLING,
PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT);
return this;
}

View File

@ -24,7 +24,6 @@ import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.NonUniqueObjectException;
@ -65,7 +64,6 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.dao.PessimisticLockingFailureException;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@ -95,39 +93,6 @@ public abstract class SessionFactoryUtils {
static final Log logger = LogFactory.getLog(SessionFactoryUtils.class);
private static Method getFlushMode;
static {
try {
// Hibernate 5.2+ getHibernateFlushMode()
getFlushMode = Session.class.getMethod("getHibernateFlushMode");
}
catch (NoSuchMethodException ex) {
try {
// Hibernate 5.0/5.1 getFlushMode() with FlushMode return type
getFlushMode = Session.class.getMethod("getFlushMode");
}
catch (NoSuchMethodException ex2) {
throw new IllegalStateException("No compatible Hibernate getFlushMode signature found", ex2);
}
}
// Check that it is the Hibernate FlushMode type, not JPA's...
Assert.state(FlushMode.class == getFlushMode.getReturnType(), "Could not find Hibernate getFlushMode method");
}
/**
* Get the native Hibernate FlushMode, adapting between Hibernate 5.0/5.1 and 5.2+.
* @param session the Hibernate Session to get the flush mode from
* @return the FlushMode (never {@code null})
* @since 4.3
*/
static FlushMode getFlushMode(Session session) {
FlushMode flushMode = (FlushMode) ReflectionUtils.invokeMethod(getFlushMode, session);
Assert.state(flushMode != null, "No FlushMode from Session");
return flushMode;
}
/**
* Trigger a flush on the given Hibernate Session, converting regular
* {@link HibernateException} instances as well as Hibernate 5.2's

View File

@ -16,8 +16,6 @@
package org.springframework.orm.hibernate5;
import javax.persistence.EntityManager;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
@ -40,8 +38,6 @@ import org.springframework.orm.jpa.EntityManagerHolder;
*/
public class SessionHolder extends EntityManagerHolder {
private final Session session;
@Nullable
private Transaction transaction;
@ -49,16 +45,13 @@ public class SessionHolder extends EntityManagerHolder {
private FlushMode previousFlushMode;
@SuppressWarnings("cast")
public SessionHolder(Session session) {
// Check below is always true against Hibernate >= 5.2 but not against 5.0/5.1 at runtime
super(session instanceof EntityManager ? session : null);
this.session = session;
super(session);
}
public Session getSession() {
return this.session;
return (Session) getEntityManager();
}
public void setTransaction(@Nullable Transaction transaction) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 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.
@ -97,7 +97,7 @@ public class SpringSessionContext implements CurrentSessionContext {
sessionHolder.setSynchronizedWithTransaction(true);
// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
// with FlushMode.MANUAL, which needs to allow flushing within the transaction.
FlushMode flushMode = SessionFactoryUtils.getFlushMode(session);
FlushMode flushMode = session.getHibernateFlushMode();
if (flushMode.equals(FlushMode.MANUAL) &&
!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
session.setFlushMode(FlushMode.AUTO);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 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.
@ -91,7 +91,7 @@ public class SpringSessionSynchronization implements TransactionSynchronization,
Session session = getCurrentSession();
// Read-write transaction -> flush the Hibernate Session.
// Further check: only flush when not FlushMode.MANUAL.
if (!FlushMode.MANUAL.equals(SessionFactoryUtils.getFlushMode(session))) {
if (!FlushMode.MANUAL.equals(session.getHibernateFlushMode())) {
SessionFactoryUtils.flush(getCurrentSession(), true);
}
}

View File

@ -25,25 +25,28 @@ import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyTenSevenDialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HANAColumnStoreDialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.InformixDialect;
import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.dialect.Informix10Dialect;
import org.hibernate.dialect.MySQL57Dialect;
import org.hibernate.dialect.Oracle12cDialect;
import org.hibernate.dialect.PostgreSQL95Dialect;
import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.springframework.lang.Nullable;
/**
* {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate
* EntityManager. Developed and tested against Hibernate 5.0, 5.1, 5.2, 5.3, 5.4;
* backwards-compatible with Hibernate 4.3 at runtime on a best-effort basis.
* EntityManager. Developed and tested against Hibernate 5.3 and 5.4;
* backwards-compatible with Hibernate 5.2 at runtime on a best-effort basis.
*
* <p>Exposes Hibernate's persistence provider and EntityManager extension interface,
* and adapts {@link AbstractJpaVendorAdapter}'s common configuration settings.
@ -77,11 +80,10 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
private final Class<? extends EntityManager> entityManagerInterface;
@SuppressWarnings("deprecation")
public HibernateJpaVendorAdapter() {
this.persistenceProvider = new SpringHibernateJpaPersistenceProvider();
this.entityManagerFactoryInterface = org.hibernate.jpa.HibernateEntityManagerFactory.class;
this.entityManagerInterface = org.hibernate.jpa.HibernateEntityManager.class;
this.entityManagerFactoryInterface = SessionFactory.class;
this.entityManagerInterface = Session.class;
}
@ -100,7 +102,7 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
* <p><b>NOTE: For a persistence unit with transaction type JTA e.g. on WebLogic,
* the connection release mode will never be altered from its provider default,
* i.e. not be forced to {@code DELAYED_ACQUISITION_AND_HOLD} by this flag.</b>
* Alternatively, set Hibernate 5.2's "hibernate.connection.handling_mode"
* Alternatively, set Hibernate's "hibernate.connection.handling_mode"
* property to "DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION" or even
* "DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT" in such a scenario.
* @since 4.3.1
@ -155,22 +157,8 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
}
if (connectionReleaseOnClose) {
// Hibernate 5.1+: manually enforce connection release mode ON_CLOSE (the former default)
try {
// Try Hibernate 5.2+
AvailableSettings.class.getField("CONNECTION_HANDLING");
jpaProperties.put("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_HOLD");
}
catch (NoSuchFieldException ex) {
// Try Hibernate 5.1
try {
AvailableSettings.class.getField("ACQUIRE_CONNECTIONS");
jpaProperties.put("hibernate.connection.release_mode", "ON_CLOSE");
}
catch (NoSuchFieldException ex2) {
// on Hibernate 5.0.x or lower - no need to change the default there
}
}
jpaProperties.put(AvailableSettings.CONNECTION_HANDLING,
PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_HOLD);
}
return jpaProperties;
@ -189,8 +177,8 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
case H2: return H2Dialect.class;
case HANA: return HANAColumnStoreDialect.class;
case HSQL: return HSQLDialect.class;
case INFORMIX: return InformixDialect.class;
case MYSQL: return MySQL5Dialect.class;
case INFORMIX: return Informix10Dialect.class;
case MYSQL: return MySQL57Dialect.class;
case ORACLE: return Oracle12cDialect.class;
case POSTGRESQL: return PostgreSQL95Dialect.class;
case SQL_SERVER: return SQLServer2012Dialect.class;