diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateOperations.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateOperations.java index e190ca19416..fe2fd028b3c 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateOperations.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateOperations.java @@ -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}. * 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. + * ORM 5.2 but may not work with Hibernate ORM 5.3 and higher anymore. * * @author Juergen Hoeller * @since 4.2 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 75978df75c3..e624fca329a 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 @@ -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 *

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 *

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 doExecute(HibernateCallback 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>) 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>) 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>) 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>) 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>) 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>) 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>) 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 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; diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTransactionManager.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTransactionManager.java index e34eeab30c5..8bf3241ce3c 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTransactionManager.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateTransactionManager.java @@ -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); } diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java index f17b82d5f17..dc840bdfdc5 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBean.java @@ -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. * - *

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 + *

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 diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java index 7d07b5c1177..f18bc07a6f5 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/LocalSessionFactoryBuilder.java @@ -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}. * - *

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 + *

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; } diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SessionFactoryUtils.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SessionFactoryUtils.java index 87ba5cc2a07..d3b61969aac 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SessionFactoryUtils.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SessionFactoryUtils.java @@ -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 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 6353ed33a0b..261035a45da 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 @@ -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) { 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 b8bc7fa2e2a..1704b04957c 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-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); diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringSessionSynchronization.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringSessionSynchronization.java index e7014c38427..374110f39c9 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringSessionSynchronization.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringSessionSynchronization.java @@ -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); } } diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java index c57cb7865fd..9de9c87dec3 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java @@ -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. * *

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 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 { *

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. - * 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;