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 08f0baa2d0f..bf6fd403ef5 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-2015 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,14 +30,37 @@ import org.springframework.dao.DataAccessException; import org.springframework.lang.Nullable; /** - * Interface that specifies a basic set of Hibernate operations, - * implemented by {@link HibernateTemplate}. Not often used, but a useful - * option to enhance testability, as it can easily be mocked or stubbed. + * Interface that specifies a common set of Hibernate operations as well as + * a general {@link #execute} method for Session-based lambda expressions. + * Implemented by {@link HibernateTemplate}. Not often used, but a useful option + * to enhance testability, as it can easily be mocked or stubbed. * - *
Defines {@code HibernateTemplate}'s data access methods that - * mirror various {@link org.hibernate.Session} methods. Users are - * strongly encouraged to read the Hibernate {@code Session} javadocs - * for details on the semantics of those methods. + *
Defines {@code HibernateTemplate}'s data access methods that mirror various + * {@link org.hibernate.Session} methods. Users are strongly encouraged to read the + * Hibernate {@code Session} javadocs for details on the semantics of those methods. + * + *
A deprecation note: While {@link HibernateTemplate} and this operations + * interface are being kept around for backwards compatibility in terms of the data + * access implementation style in Spring applications, we strongly recommend the use + * of native {@link org.hibernate.Session} access code for non-trivial interactions. + * This in particular affects parameterized queries where - on Java 8+ - a custom + * {@link HibernateCallback} lambda code block with {@code createQuery} and several + * {@code setParameter} calls on the {@link org.hibernate.query.Query} interface + * is an elegant solution, to be executed via the general {@link #execute} method. + * All such operations which benefit from a lambda variant have been marked as + * {@code deprecated} on this interface. + * + *
A Hibernate compatibility note: {@link HibernateTemplate} and the
+ * operations on this interface generally aim to be applicable across all Hibernate
+ * versions. In terms of binary compatibility, Spring ships a variant for each major
+ * generation of Hibernate (in the present case: Hibernate ORM 5.x). However, due to
+ * refactorings and removals in Hibernate ORM 5.3, some variants - in particular
+ * legacy positional parameters starting from index 0 - do not work anymore.
+ * All affected operations are marked as deprecated; please replace them with the
+ * 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.
*
* @author Juergen Hoeller
* @since 4.2
@@ -560,6 +583,94 @@ public interface HibernateOperations {
void clear() throws DataAccessException;
+ //-------------------------------------------------------------------------
+ // Convenience finder methods for detached criteria
+ //-------------------------------------------------------------------------
+
+ /**
+ * Execute a query based on a given Hibernate criteria object.
+ * @param criteria the detached Hibernate criteria object.
+ * Note: Do not reuse criteria objects! They need to recreated per execution,
+ * due to the suboptimal design of Hibernate's criteria facility.
+ * @return a {@link List} containing 0 or more persistent instances
+ * @throws DataAccessException in case of Hibernate errors
+ * @see DetachedCriteria#getExecutableCriteria(org.hibernate.Session)
+ */
+ List> findByCriteria(DetachedCriteria criteria) throws DataAccessException;
+
+ /**
+ * Execute a query based on the given Hibernate criteria object.
+ * @param criteria the detached Hibernate criteria object.
+ * Note: Do not reuse criteria objects! They need to recreated per execution,
+ * due to the suboptimal design of Hibernate's criteria facility.
+ * @param firstResult the index of the first result object to be retrieved
+ * (numbered from 0)
+ * @param maxResults the maximum number of result objects to retrieve
+ * (or <=0 for no limit)
+ * @return a {@link List} containing 0 or more persistent instances
+ * @throws DataAccessException in case of Hibernate errors
+ * @see DetachedCriteria#getExecutableCriteria(org.hibernate.Session)
+ * @see org.hibernate.Criteria#setFirstResult(int)
+ * @see org.hibernate.Criteria#setMaxResults(int)
+ */
+ List> findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) throws DataAccessException;
+
+ /**
+ * Execute a query based on the given example entity object.
+ * @param exampleEntity an instance of the desired entity,
+ * serving as example for "query-by-example"
+ * @return a {@link List} containing 0 or more persistent instances
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.criterion.Example#create(Object)
+ */
+ NOTE: Hibernate access code can also be coded in plain Hibernate style.
- * Hence, for newly started projects, consider adopting the standard Hibernate
- * style of coding data access objects instead, based on
- * {@link SessionFactory#getCurrentSession()}.
- * This HibernateTemplate primarily exists as a migration helper for Hibernate 3
- * based data access code, to benefit from bug fixes in Hibernate 5.x.
+ * NOTE: Hibernate access code can also be coded against the native Hibernate
+ * {@link Session}. Hence, for newly started projects, consider adopting the standard
+ * Hibernate style of coding against {@link SessionFactory#getCurrentSession()}.
+ * Alternatively, use {@link #execute(HibernateCallback)} with Java 8 lambda code blocks
+ * against the callback-provided {@code Session} which results in elegant code as well,
+ * decoupled from the Hibernate Session lifecycle. The remaining operations on this
+ * HibernateTemplate are deprecated in the meantime and primarily exist as a migration
+ * helper for older Hibernate 3.x/4.x data access code in existing applications.
*
* @author Juergen Hoeller
* @since 4.2
@@ -821,10 +823,77 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}
+ //-------------------------------------------------------------------------
+ // Convenience finder methods for detached criteria
+ //-------------------------------------------------------------------------
+
+ @Override
+ public List> findByCriteria(DetachedCriteria criteria) throws DataAccessException {
+ return findByCriteria(criteria, -1, -1);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List> findByCriteria(final DetachedCriteria criteria, final int firstResult, final int maxResults)
+ throws DataAccessException {
+
+ Assert.notNull(criteria, "DetachedCriteria must not be null");
+ return nonNull(executeWithNativeSession((HibernateCallback>) session -> {
+ Criteria executableCriteria = criteria.getExecutableCriteria(session);
+ prepareCriteria(executableCriteria);
+ if (firstResult >= 0) {
+ executableCriteria.setFirstResult(firstResult);
+ }
+ if (maxResults > 0) {
+ executableCriteria.setMaxResults(maxResults);
+ }
+ return executableCriteria.list();
+ }));
+ }
+
+ @Override
+ public
>) session -> {
+ Criteria executableCriteria = (entityName != null ?
+ session.createCriteria(entityName) : session.createCriteria(exampleEntity.getClass()));
+ executableCriteria.add(Example.create(exampleEntity));
+ prepareCriteria(executableCriteria);
+ if (firstResult >= 0) {
+ executableCriteria.setFirstResult(firstResult);
+ }
+ if (maxResults > 0) {
+ executableCriteria.setMaxResults(maxResults);
+ }
+ return executableCriteria.list();
+ }));
+ }
+
+
//-------------------------------------------------------------------------
// Convenience finder methods for HQL strings
//-------------------------------------------------------------------------
+ @Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List> find(final String queryString, @Nullable final Object... values) throws DataAccessException {
@@ -841,6 +910,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}));
}
+ @Deprecated
@Override
public List> findByNamedParam(String queryString, String paramName, Object value)
throws DataAccessException {
@@ -848,6 +918,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
return findByNamedParam(queryString, new String[] {paramName}, new Object[] {value});
}
+ @Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List> findByNamedParam(final String queryString, final String[] paramNames, final Object[] values)
@@ -867,6 +938,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}));
}
+ @Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List> findByValueBean(final String queryString, final Object valueBean)
@@ -886,6 +958,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
// Convenience finder methods for named queries
//-------------------------------------------------------------------------
+ @Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List> findByNamedQuery(final String queryName, @Nullable final Object... values) throws DataAccessException {
@@ -902,6 +975,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}));
}
+ @Deprecated
@Override
public List> findByNamedQueryAndNamedParam(String queryName, String paramName, Object value)
throws DataAccessException {
@@ -909,6 +983,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
return findByNamedQueryAndNamedParam(queryName, new String[] {paramName}, new Object[] {value});
}
+ @Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List> findByNamedQueryAndNamedParam(
@@ -931,6 +1006,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}));
}
+ @Deprecated
@Override
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public List> findByNamedQueryAndValueBean(final String queryName, final Object valueBean)
@@ -946,76 +1022,11 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}
- //-------------------------------------------------------------------------
- // Convenience finder methods for detached criteria
- //-------------------------------------------------------------------------
-
- @Override
- public List> findByCriteria(DetachedCriteria criteria) throws DataAccessException {
- return findByCriteria(criteria, -1, -1);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public List> findByCriteria(final DetachedCriteria criteria, final int firstResult, final int maxResults)
- throws DataAccessException {
-
- Assert.notNull(criteria, "DetachedCriteria must not be null");
- return nonNull(executeWithNativeSession((HibernateCallback
>) session -> {
- Criteria executableCriteria = criteria.getExecutableCriteria(session);
- prepareCriteria(executableCriteria);
- if (firstResult >= 0) {
- executableCriteria.setFirstResult(firstResult);
- }
- if (maxResults > 0) {
- executableCriteria.setMaxResults(maxResults);
- }
- return executableCriteria.list();
- }));
- }
-
- @Override
- public
>) session -> {
- Criteria executableCriteria = (entityName != null ?
- session.createCriteria(entityName) : session.createCriteria(exampleEntity.getClass()));
- executableCriteria.add(Example.create(exampleEntity));
- prepareCriteria(executableCriteria);
- if (firstResult >= 0) {
- executableCriteria.setFirstResult(firstResult);
- }
- if (maxResults > 0) {
- executableCriteria.setMaxResults(maxResults);
- }
- return executableCriteria.list();
- }));
- }
-
-
//-------------------------------------------------------------------------
// Convenience query methods for iteration and bulk updates/deletes
//-------------------------------------------------------------------------
+ @Deprecated
@Override
@SuppressWarnings({"rawtypes", "deprecation"})
public Iterator> iterate(final String queryString, @Nullable final Object... values) throws DataAccessException {
@@ -1032,6 +1043,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}));
}
+ @Deprecated
@Override
public void closeIterator(Iterator> it) throws DataAccessException {
try {
@@ -1042,6 +1054,7 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}
}
+ @Deprecated
@Override
@SuppressWarnings({"rawtypes", "deprecation"})
public int bulkUpdate(final String queryString, @Nullable final Object... values) throws DataAccessException {
@@ -1084,59 +1097,60 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}
/**
- * Prepare the given Query object, applying cache settings and/or
+ * Prepare the given Criteria object, applying cache settings and/or
* a transaction timeout.
- * @param queryObject the Query object to prepare
+ * @param criteria the Criteria object to prepare
* @see #setCacheQueries
* @see #setQueryCacheRegion
*/
- @SuppressWarnings({"rawtypes", "deprecation"})
- protected void prepareQuery(org.hibernate.Query queryObject) {
+ protected void prepareCriteria(Criteria criteria) {
if (isCacheQueries()) {
- queryObject.setCacheable(true);
+ criteria.setCacheable(true);
if (getQueryCacheRegion() != null) {
- queryObject.setCacheRegion(getQueryCacheRegion());
+ criteria.setCacheRegion(getQueryCacheRegion());
}
}
if (getFetchSize() > 0) {
- queryObject.setFetchSize(getFetchSize());
+ criteria.setFetchSize(getFetchSize());
}
if (getMaxResults() > 0) {
- queryObject.setMaxResults(getMaxResults());
+ criteria.setMaxResults(getMaxResults());
}
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(obtainSessionFactory());
if (sessionHolder != null && sessionHolder.hasTimeout()) {
- queryObject.setTimeout(sessionHolder.getTimeToLiveInSeconds());
+ criteria.setTimeout(sessionHolder.getTimeToLiveInSeconds());
}
}
/**
- * Prepare the given Criteria object, applying cache settings and/or
+ * Prepare the given Query object, applying cache settings and/or
* a transaction timeout.
- * @param criteria the Criteria object to prepare
+ * @param queryObject the Query object to prepare
* @see #setCacheQueries
* @see #setQueryCacheRegion
*/
- protected void prepareCriteria(Criteria criteria) {
+ @Deprecated
+ @SuppressWarnings({"rawtypes", "deprecation"})
+ protected void prepareQuery(org.hibernate.Query queryObject) {
if (isCacheQueries()) {
- criteria.setCacheable(true);
+ queryObject.setCacheable(true);
if (getQueryCacheRegion() != null) {
- criteria.setCacheRegion(getQueryCacheRegion());
+ queryObject.setCacheRegion(getQueryCacheRegion());
}
}
if (getFetchSize() > 0) {
- criteria.setFetchSize(getFetchSize());
+ queryObject.setFetchSize(getFetchSize());
}
if (getMaxResults() > 0) {
- criteria.setMaxResults(getMaxResults());
+ queryObject.setMaxResults(getMaxResults());
}
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(obtainSessionFactory());
if (sessionHolder != null && sessionHolder.hasTimeout()) {
- criteria.setTimeout(sessionHolder.getTimeToLiveInSeconds());
+ queryObject.setTimeout(sessionHolder.getTimeToLiveInSeconds());
}
}
@@ -1147,6 +1161,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)
throws HibernateException {
@@ -1163,17 +1178,18 @@ public class HibernateTemplate implements HibernateOperations, InitializingBean
}
- private static