Upgrade Hibernate support baseline to 5.2+
Closes gh-25533 Closes gh-22326
This commit is contained in:
parent
b6d2a2980d
commit
ba65cef52b
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue