Skip to content

Commit 9394616

Browse files
committed
Support for Hibernate ORM 5.2
Issue: SPR-14327
1 parent 521c41d commit 9394616

File tree

13 files changed

+134
-63
lines changed

13 files changed

+134
-63
lines changed

build.gradle

+1-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ configure(allprojects) { project ->
4646
ext.hamcrestVersion = "1.3"
4747
ext.hibernate3Version = "3.6.10.Final"
4848
ext.hibernate4Version = "4.3.11.Final"
49-
ext.hibernate5Version = "5.1.0.Final"
49+
ext.hibernate5Version = "5.2.0.Final"
5050
ext.hibval4Version = "4.3.2.Final"
5151
ext.hibval5Version = "5.2.4.Final"
5252
ext.hsqldbVersion = "2.3.4"
@@ -798,7 +798,6 @@ project("spring-orm-hibernate5") {
798798
provided(project(":spring-tx"))
799799
optional(project(":spring-web"))
800800
optional("org.hibernate:hibernate-core:${hibernate5Version}")
801-
optional("org.hibernate:hibernate-entitymanager:${hibernate5Version}")
802801
optional("javax.servlet:javax.servlet-api:3.0.1")
803802
optional("javax.transaction:javax.transaction-api:${jtaVersion}")
804803
}

spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/HibernateTransactionManager.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -480,7 +480,7 @@ protected void doBegin(Object transaction, TransactionDefinition definition) {
480480
if (!definition.isReadOnly() && !txObject.isNewSession()) {
481481
// We need AUTO or COMMIT for a non-read-only transaction.
482482
FlushMode flushMode = session.getFlushMode();
483-
if (session.getFlushMode().equals(FlushMode.MANUAL)) {
483+
if (FlushMode.MANUAL.equals(flushMode)) {
484484
session.setFlushMode(FlushMode.AUTO);
485485
txObject.getSessionHolder().setPreviousFlushMode(flushMode);
486486
}

spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java

+32-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,15 +27,13 @@
2727

2828
import org.apache.commons.logging.Log;
2929
import org.apache.commons.logging.LogFactory;
30-
3130
import org.hibernate.Criteria;
3231
import org.hibernate.Filter;
3332
import org.hibernate.FlushMode;
3433
import org.hibernate.Hibernate;
3534
import org.hibernate.HibernateException;
3635
import org.hibernate.LockMode;
3736
import org.hibernate.LockOptions;
38-
import org.hibernate.Query;
3937
import org.hibernate.ReplicationMode;
4038
import org.hibernate.Session;
4139
import org.hibernate.SessionFactory;
@@ -211,7 +209,7 @@ public boolean isCheckWriteOperations() {
211209
* <p>To specify the query region to be used for queries cached
212210
* by this template, set the "queryCacheRegion" property.
213211
* @see #setQueryCacheRegion
214-
* @see Query#setCacheable
212+
* @see org.hibernate.Query#setCacheable
215213
* @see Criteria#setCacheable
216214
*/
217215
public void setCacheQueries(boolean cacheQueries) {
@@ -232,7 +230,7 @@ public boolean isCacheQueries() {
232230
* <p>The cache region will not take effect unless queries created by this
233231
* template are configured to be cached via the "cacheQueries" property.
234232
* @see #setCacheQueries
235-
* @see Query#setCacheRegion
233+
* @see org.hibernate.Query#setCacheRegion
236234
* @see Criteria#setCacheRegion
237235
*/
238236
public void setQueryCacheRegion(String queryCacheRegion) {
@@ -317,6 +315,7 @@ public <T> T executeWithNativeSession(HibernateCallback<T> action) {
317315
* @return a result object returned by the action, or {@code null}
318316
* @throws DataAccessException in case of Hibernate errors
319317
*/
318+
@SuppressWarnings("deprecation")
320319
protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNativeSession) throws DataAccessException {
321320
Assert.notNull(action, "Callback object must not be null");
322321

@@ -499,7 +498,7 @@ public Object doInHibernate(Session session) throws HibernateException {
499498
public <T> List<T> loadAll(final Class<T> entityClass) throws DataAccessException {
500499
return executeWithNativeSession(new HibernateCallback<List<T>>() {
501500
@Override
502-
@SuppressWarnings("unchecked")
501+
@SuppressWarnings({"unchecked", "deprecation"})
503502
public List<T> doInHibernate(Session session) throws HibernateException {
504503
Criteria criteria = session.createCriteria(entityClass);
505504
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
@@ -862,8 +861,9 @@ public Object doInHibernate(Session session) {
862861
public List<?> find(final String queryString, final Object... values) throws DataAccessException {
863862
return executeWithNativeSession(new HibernateCallback<List<?>>() {
864863
@Override
864+
@SuppressWarnings({"rawtypes", "deprecation"})
865865
public List<?> doInHibernate(Session session) throws HibernateException {
866-
Query queryObject = session.createQuery(queryString);
866+
org.hibernate.Query queryObject = session.createQuery(queryString);
867867
prepareQuery(queryObject);
868868
if (values != null) {
869869
for (int i = 0; i < values.length; i++) {
@@ -891,13 +891,12 @@ public List<?> findByNamedParam(final String queryString, final String[] paramNa
891891
}
892892
return executeWithNativeSession(new HibernateCallback<List<?>>() {
893893
@Override
894+
@SuppressWarnings({"rawtypes", "deprecation"})
894895
public List<?> doInHibernate(Session session) throws HibernateException {
895-
Query queryObject = session.createQuery(queryString);
896+
org.hibernate.Query queryObject = session.createQuery(queryString);
896897
prepareQuery(queryObject);
897-
if (values != null) {
898-
for (int i = 0; i < values.length; i++) {
899-
applyNamedParameterToQuery(queryObject, paramNames[i], values[i]);
900-
}
898+
for (int i = 0; i < values.length; i++) {
899+
applyNamedParameterToQuery(queryObject, paramNames[i], values[i]);
901900
}
902901
return queryObject.list();
903902
}
@@ -910,8 +909,9 @@ public List<?> findByValueBean(final String queryString, final Object valueBean)
910909

911910
return executeWithNativeSession(new HibernateCallback<List<?>>() {
912911
@Override
912+
@SuppressWarnings({"rawtypes", "deprecation"})
913913
public List<?> doInHibernate(Session session) throws HibernateException {
914-
Query queryObject = session.createQuery(queryString);
914+
org.hibernate.Query queryObject = session.createQuery(queryString);
915915
prepareQuery(queryObject);
916916
queryObject.setProperties(valueBean);
917917
return queryObject.list();
@@ -928,8 +928,9 @@ public List<?> doInHibernate(Session session) throws HibernateException {
928928
public List<?> findByNamedQuery(final String queryName, final Object... values) throws DataAccessException {
929929
return executeWithNativeSession(new HibernateCallback<List<?>>() {
930930
@Override
931+
@SuppressWarnings({"rawtypes", "deprecation"})
931932
public List<?> doInHibernate(Session session) throws HibernateException {
932-
Query queryObject = session.getNamedQuery(queryName);
933+
org.hibernate.Query queryObject = session.getNamedQuery(queryName);
933934
prepareQuery(queryObject);
934935
if (values != null) {
935936
for (int i = 0; i < values.length; i++) {
@@ -958,8 +959,9 @@ public List<?> findByNamedQueryAndNamedParam(
958959
}
959960
return executeWithNativeSession(new HibernateCallback<List<?>>() {
960961
@Override
962+
@SuppressWarnings({"rawtypes", "deprecation"})
961963
public List<?> doInHibernate(Session session) throws HibernateException {
962-
Query queryObject = session.getNamedQuery(queryName);
964+
org.hibernate.Query queryObject = session.getNamedQuery(queryName);
963965
prepareQuery(queryObject);
964966
if (values != null) {
965967
for (int i = 0; i < values.length; i++) {
@@ -977,8 +979,9 @@ public List<?> findByNamedQueryAndValueBean(final String queryName, final Object
977979

978980
return executeWithNativeSession(new HibernateCallback<List<?>>() {
979981
@Override
982+
@SuppressWarnings({"rawtypes", "deprecation"})
980983
public List<?> doInHibernate(Session session) throws HibernateException {
981-
Query queryObject = session.getNamedQuery(queryName);
984+
org.hibernate.Query queryObject = session.getNamedQuery(queryName);
982985
prepareQuery(queryObject);
983986
queryObject.setProperties(valueBean);
984987
return queryObject.list();
@@ -1033,6 +1036,7 @@ public <T> List<T> findByExample(T exampleEntity, int firstResult, int maxResult
10331036
}
10341037

10351038
@Override
1039+
@SuppressWarnings("deprecation")
10361040
public <T> List<T> findByExample(
10371041
final String entityName, final T exampleEntity, final int firstResult, final int maxResults)
10381042
throws DataAccessException {
@@ -1066,8 +1070,9 @@ public List<T> doInHibernate(Session session) throws HibernateException {
10661070
public Iterator<?> iterate(final String queryString, final Object... values) throws DataAccessException {
10671071
return executeWithNativeSession(new HibernateCallback<Iterator<?>>() {
10681072
@Override
1073+
@SuppressWarnings({"rawtypes", "deprecation"})
10691074
public Iterator<?> doInHibernate(Session session) throws HibernateException {
1070-
Query queryObject = session.createQuery(queryString);
1075+
org.hibernate.Query queryObject = session.createQuery(queryString);
10711076
prepareQuery(queryObject);
10721077
if (values != null) {
10731078
for (int i = 0; i < values.length; i++) {
@@ -1093,8 +1098,9 @@ public void closeIterator(Iterator<?> it) throws DataAccessException {
10931098
public int bulkUpdate(final String queryString, final Object... values) throws DataAccessException {
10941099
return executeWithNativeSession(new HibernateCallback<Integer>() {
10951100
@Override
1101+
@SuppressWarnings({"rawtypes", "deprecation"})
10961102
public Integer doInHibernate(Session session) throws HibernateException {
1097-
Query queryObject = session.createQuery(queryString);
1103+
org.hibernate.Query queryObject = session.createQuery(queryString);
10981104
prepareQuery(queryObject);
10991105
if (values != null) {
11001106
for (int i = 0; i < values.length; i++) {
@@ -1122,7 +1128,7 @@ public Integer doInHibernate(Session session) throws HibernateException {
11221128
* @see FlushMode#MANUAL
11231129
*/
11241130
protected void checkWriteOperationAllowed(Session session) throws InvalidDataAccessApiUsageException {
1125-
if (isCheckWriteOperations() && session.getFlushMode().lessThan(FlushMode.COMMIT)) {
1131+
if (isCheckWriteOperations() && SessionFactoryUtils.getFlushMode(session).lessThan(FlushMode.COMMIT)) {
11261132
throw new InvalidDataAccessApiUsageException(
11271133
"Write operations are not allowed in read-only mode (FlushMode.MANUAL): "+
11281134
"Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.");
@@ -1136,7 +1142,8 @@ protected void checkWriteOperationAllowed(Session session) throws InvalidDataAcc
11361142
* @see #setCacheQueries
11371143
* @see #setQueryCacheRegion
11381144
*/
1139-
protected void prepareQuery(Query queryObject) {
1145+
@SuppressWarnings({"rawtypes", "deprecation"})
1146+
protected void prepareQuery(org.hibernate.Query queryObject) {
11401147
if (isCacheQueries()) {
11411148
queryObject.setCacheable(true);
11421149
if (getQueryCacheRegion() != null) {
@@ -1192,7 +1199,8 @@ protected void prepareCriteria(Criteria criteria) {
11921199
* @param value the value of the parameter
11931200
* @throws HibernateException if thrown by the Query object
11941201
*/
1195-
protected void applyNamedParameterToQuery(Query queryObject, String paramName, Object value)
1202+
@SuppressWarnings({"rawtypes", "deprecation"})
1203+
protected void applyNamedParameterToQuery(org.hibernate.Query queryObject, String paramName, Object value)
11961204
throws HibernateException {
11971205

11981206
if (value instanceof Collection) {
@@ -1221,6 +1229,7 @@ public CloseSuppressingInvocationHandler(Session target) {
12211229
}
12221230

12231231
@Override
1232+
@SuppressWarnings("deprecation")
12241233
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
12251234
// Invocation on Session interface coming in...
12261235

@@ -1243,8 +1252,8 @@ else if (method.getName().equals("close")) {
12431252

12441253
// If return value is a Query or Criteria, apply transaction timeout.
12451254
// Applies to createQuery, getNamedQuery, createCriteria.
1246-
if (retVal instanceof Query) {
1247-
prepareQuery(((Query) retVal));
1255+
if (retVal instanceof org.hibernate.Query) {
1256+
prepareQuery(((org.hibernate.Query) retVal));
12481257
}
12491258
if (retVal instanceof Criteria) {
12501259
prepareCriteria(((Criteria) retVal));

spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateTransactionManager.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -412,6 +412,7 @@ protected boolean isExistingTransaction(Object transaction) {
412412
}
413413

414414
@Override
415+
@SuppressWarnings("deprecation")
415416
protected void doBegin(Object transaction, TransactionDefinition definition) {
416417
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
417418

@@ -476,8 +477,8 @@ protected void doBegin(Object transaction, TransactionDefinition definition) {
476477

477478
if (!definition.isReadOnly() && !txObject.isNewSession()) {
478479
// We need AUTO or COMMIT for a non-read-only transaction.
479-
FlushMode flushMode = session.getFlushMode();
480-
if (session.getFlushMode().equals(FlushMode.MANUAL)) {
480+
FlushMode flushMode = SessionFactoryUtils.getFlushMode(session);
481+
if (FlushMode.MANUAL.equals(flushMode)) {
481482
session.setFlushMode(FlushMode.AUTO);
482483
txObject.getSessionHolder().setPreviousFlushMode(flushMode);
483484
}
@@ -627,6 +628,7 @@ protected void doSetRollbackOnly(DefaultTransactionStatus status) {
627628
}
628629

629630
@Override
631+
@SuppressWarnings("deprecation")
630632
protected void doCleanupAfterCompletion(Object transaction) {
631633
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
632634

@@ -703,6 +705,7 @@ protected void disconnectOnCompletion(Session session) {
703705
* @param session the Hibernate Session to check
704706
* @see ConnectionReleaseMode#ON_CLOSE
705707
*/
708+
@SuppressWarnings("deprecation")
706709
protected boolean isSameConnectionForEntireSession(Session session) {
707710
if (!(session instanceof SessionImplementor)) {
708711
// The best we can do is to assume we're safe.

spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/SessionFactoryUtils.java

+56-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,10 +16,12 @@
1616

1717
package org.springframework.orm.hibernate5;
1818

19+
import java.lang.reflect.Method;
1920
import javax.sql.DataSource;
2021

2122
import org.apache.commons.logging.Log;
2223
import org.apache.commons.logging.LogFactory;
24+
import org.hibernate.FlushMode;
2325
import org.hibernate.HibernateException;
2426
import org.hibernate.JDBCException;
2527
import org.hibernate.NonUniqueObjectException;
@@ -59,6 +61,8 @@
5961
import org.springframework.dao.InvalidDataAccessResourceUsageException;
6062
import org.springframework.dao.PessimisticLockingFailureException;
6163
import org.springframework.jdbc.datasource.DataSourceUtils;
64+
import org.springframework.util.Assert;
65+
import org.springframework.util.ReflectionUtils;
6266

6367
/**
6468
* Helper class featuring methods for Hibernate Session handling.
@@ -86,6 +90,57 @@ public abstract class SessionFactoryUtils {
8690
static final Log logger = LogFactory.getLog(SessionFactoryUtils.class);
8791

8892

93+
private static Method getFlushMode;
94+
95+
static {
96+
try {
97+
// Hibernate 5.2+ getHibernateFlushMode()
98+
getFlushMode = Session.class.getMethod("getHibernateFlushMode");
99+
}
100+
catch (NoSuchMethodException ex) {
101+
try {
102+
// Hibernate 5.0/5.1 getFlushMode() with FlushMode return type
103+
getFlushMode = Session.class.getMethod("getFlushMode");
104+
}
105+
catch (NoSuchMethodException ex2) {
106+
throw new IllegalStateException("No compatible Hibernate getFlushMode signature found", ex2);
107+
}
108+
}
109+
// Check that it is the Hibernate FlushMode type, not JPA's...
110+
Assert.state(FlushMode.class == getFlushMode.getReturnType());
111+
}
112+
113+
114+
/**
115+
* Get the native Hibernate FlushMode, adapting between Hibernate 5.0/5.1 and 5.2+.
116+
* @param session the Hibernate Session to get the flush mode from
117+
* @return the FlushMode (never {@code null})
118+
* @since 4.3
119+
*/
120+
static FlushMode getFlushMode(Session session) {
121+
return (FlushMode) ReflectionUtils.invokeMethod(getFlushMode, session);
122+
}
123+
124+
/**
125+
* Perform actual closing of the Hibernate Session,
126+
* catching and logging any cleanup exceptions thrown.
127+
* @param session the Hibernate Session to close (may be {@code null})
128+
* @see Session#close()
129+
*/
130+
public static void closeSession(Session session) {
131+
if (session != null) {
132+
try {
133+
session.close();
134+
}
135+
catch (HibernateException ex) {
136+
logger.debug("Could not close Hibernate Session", ex);
137+
}
138+
catch (Throwable ex) {
139+
logger.debug("Unexpected exception on closing Hibernate Session", ex);
140+
}
141+
}
142+
}
143+
89144
/**
90145
* Determine the DataSource of the given SessionFactory.
91146
* @param sessionFactory the SessionFactory to check
@@ -114,26 +169,6 @@ public static DataSource getDataSource(SessionFactory sessionFactory) {
114169
return null;
115170
}
116171

117-
/**
118-
* Perform actual closing of the Hibernate Session,
119-
* catching and logging any cleanup exceptions thrown.
120-
* @param session the Hibernate Session to close (may be {@code null})
121-
* @see Session#close()
122-
*/
123-
public static void closeSession(Session session) {
124-
if (session != null) {
125-
try {
126-
session.close();
127-
}
128-
catch (HibernateException ex) {
129-
logger.debug("Could not close Hibernate Session", ex);
130-
}
131-
catch (Throwable ex) {
132-
logger.debug("Unexpected exception on closing Hibernate Session", ex);
133-
}
134-
}
135-
}
136-
137172
/**
138173
* Convert the given HibernateException to an appropriate exception
139174
* from the {@code org.springframework.dao} hierarchy.

0 commit comments

Comments
 (0)