diff --git a/build.gradle b/build.gradle
index 6058893b55..d6659037ac 100644
--- a/build.gradle
+++ b/build.gradle
@@ -827,6 +827,21 @@ project("spring-orm-hibernate4") {
}
}
+project("spring-orm-hibernate5") {
+ description = "Spring Object/Relational Mapping - Hibernate 5 support"
+ merge.into = project(":spring-orm")
+
+ dependencies {
+ provided(project(":spring-jdbc"))
+ provided(project(":spring-tx"))
+ optional(project(":spring-web"))
+ optional("org.hibernate:hibernate-core:5.0.0.Beta2")
+ optional("org.hibernate:hibernate-entitymanager:5.0.0.Beta2")
+ optional("javax.servlet:javax.servlet-api:3.0.1")
+ optional("aopalliance:aopalliance:1.0")
+ }
+}
+
project("spring-webmvc") {
description = "Spring Web MVC"
diff --git a/settings.gradle b/settings.gradle
index 8ee1787cd4..aa0763c488 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -15,6 +15,7 @@ include "spring-jms"
include "spring-messaging"
include "spring-orm"
include "spring-orm-hibernate4"
+include "spring-orm-hibernate5"
include "spring-oxm"
include "spring-test"
include "spring-tx"
diff --git a/spring-orm-hibernate4/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateJpaPersistenceProvider.java b/spring-orm-hibernate4/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateJpaPersistenceProvider.java
index a3e147cde5..88e063bfbe 100644
--- a/spring-orm-hibernate4/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateJpaPersistenceProvider.java
+++ b/spring-orm-hibernate4/src/main/java/org/springframework/orm/jpa/vendor/SpringHibernateJpaPersistenceProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2015 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.
@@ -16,6 +16,8 @@
package org.springframework.orm.jpa.vendor;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceUnitInfo;
@@ -24,7 +26,6 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor;
-import org.hibernate.service.ServiceRegistry;
import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo;
@@ -33,7 +34,7 @@ import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo;
* from the {@code org.hibernate.jpa} package, adding support for
* {@link SmartPersistenceUnitInfo#getManagedPackages()}.
*
- *
Compatible with Hibernate 4.3. {@link SpringHibernateEjbPersistenceProvider}
+ *
Compatible with Hibernate 4.3-5.0. {@link SpringHibernateEjbPersistenceProvider}
* is an alternative for compatibility with earlier Hibernate versions (3.6-4.2).
*
* @author Juergen Hoeller
@@ -45,19 +46,18 @@ class SpringHibernateJpaPersistenceProvider extends HibernatePersistenceProvider
@Override
@SuppressWarnings("rawtypes")
- public EntityManagerFactory createContainerEntityManagerFactory(final PersistenceUnitInfo info, Map properties) {
- return new EntityManagerFactoryBuilderImpl(new PersistenceUnitInfoDescriptor(info), properties) {
- @Override
- public Configuration buildHibernateConfiguration(ServiceRegistry serviceRegistry) {
- Configuration configuration = super.buildHibernateConfiguration(serviceRegistry);
- if (info instanceof SmartPersistenceUnitInfo) {
- for (String managedPackage : ((SmartPersistenceUnitInfo) info).getManagedPackages()) {
- configuration.addPackage(managedPackage);
+ public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) {
+ final List mergedClassesAndPackages = new ArrayList(info.getManagedClassNames());
+ if (info instanceof SmartPersistenceUnitInfo) {
+ mergedClassesAndPackages.addAll(((SmartPersistenceUnitInfo) info).getManagedPackages());
+ }
+ return new EntityManagerFactoryBuilderImpl(
+ new PersistenceUnitInfoDescriptor(info) {
+ @Override
+ public List getManagedClassNames() {
+ return mergedClassesAndPackages;
}
- }
- return configuration;
- }
- }.build();
+ }, properties).build();
}
}
diff --git a/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/ConfigurableJtaPlatform.java b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/ConfigurableJtaPlatform.java
new file mode 100644
index 0000000000..e1c74b58ef
--- /dev/null
+++ b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/ConfigurableJtaPlatform.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2002-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.hibernate5;
+
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.UserTransaction;
+
+import org.hibernate.TransactionException;
+import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
+
+import org.springframework.transaction.jta.UserTransactionAdapter;
+import org.springframework.util.Assert;
+
+/**
+ * Implementation of Hibernate 4's JtaPlatform SPI, exposing passed-in {@link TransactionManager},
+ * {@link UserTransaction} and {@link TransactionSynchronizationRegistry} references.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ */
+@SuppressWarnings("serial")
+class ConfigurableJtaPlatform implements JtaPlatform {
+
+ private final TransactionManager transactionManager;
+
+ private final UserTransaction userTransaction;
+
+ private final TransactionSynchronizationRegistry transactionSynchronizationRegistry;
+
+
+ /**
+ * Create a new ConfigurableJtaPlatform instance with the given
+ * JTA TransactionManager and optionally a given UserTransaction.
+ * @param tm the JTA TransactionManager reference (required)
+ * @param ut the JTA UserTransaction reference (optional)
+ * @param tsr the JTA 1.1 TransactionSynchronizationRegistry (optional)
+ */
+ public ConfigurableJtaPlatform(TransactionManager tm, UserTransaction ut, TransactionSynchronizationRegistry tsr) {
+ Assert.notNull(tm, "TransactionManager reference must not be null");
+ this.transactionManager = tm;
+ this.userTransaction = (ut != null ? ut : new UserTransactionAdapter(tm));
+ this.transactionSynchronizationRegistry = tsr;
+ }
+
+
+ @Override
+ public TransactionManager retrieveTransactionManager() {
+ return this.transactionManager;
+ }
+
+ @Override
+ public UserTransaction retrieveUserTransaction() {
+ return this.userTransaction;
+ }
+
+ @Override
+ public Object getTransactionIdentifier(Transaction transaction) {
+ return transaction;
+ }
+
+ @Override
+ public boolean canRegisterSynchronization() {
+ try {
+ return (this.transactionManager.getStatus() == Status.STATUS_ACTIVE);
+ }
+ catch (SystemException ex) {
+ throw new TransactionException("Could not determine JTA transaction status", ex);
+ }
+ }
+
+ @Override
+ public void registerSynchronization(Synchronization synchronization) {
+ if (this.transactionSynchronizationRegistry != null) {
+ this.transactionSynchronizationRegistry.registerInterposedSynchronization(synchronization);
+ }
+ else {
+ try {
+ this.transactionManager.getTransaction().registerSynchronization(synchronization);
+ }
+ catch (Exception ex) {
+ throw new TransactionException("Could not access JTA Transaction to register synchronization", ex);
+ }
+ }
+ }
+
+ @Override
+ public int getCurrentStatus() throws SystemException {
+ return this.transactionManager.getStatus();
+ }
+
+}
diff --git a/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateCallback.java b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateCallback.java
new file mode 100644
index 0000000000..78074360ca
--- /dev/null
+++ b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateCallback.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.hibernate5;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+
+/**
+ * Callback interface for Hibernate code. To be used with {@link HibernateTemplate}'s
+ * execution methods, often as anonymous classes within a method implementation.
+ * A typical implementation will call {@code Session.load/find/update} to perform
+ * some operations on persistent objects.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ * @see HibernateTemplate
+ * @see HibernateTransactionManager
+ */
+public interface HibernateCallback {
+
+ /**
+ * Gets called by {@code HibernateTemplate.execute} with an active
+ * Hibernate {@code Session}. Does not need to care about activating
+ * or closing the {@code Session}, or handling transactions.
+ *
+ *
Allows for returning a result object created within the callback,
+ * i.e. a domain object or a collection of domain objects.
+ * A thrown custom RuntimeException is treated as an application exception:
+ * It gets propagated to the caller of the template.
+ *
+ * @param session active Hibernate session
+ * @return a result object, or {@code null} if none
+ * @throws HibernateException if thrown by the Hibernate API
+ * @see HibernateTemplate#execute
+ */
+ T doInHibernate(Session session) throws HibernateException;
+
+}
diff --git a/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateExceptionTranslator.java b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateExceptionTranslator.java
new file mode 100644
index 0000000000..5e4886f2f8
--- /dev/null
+++ b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateExceptionTranslator.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2002-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.hibernate5;
+
+import org.hibernate.HibernateException;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.support.PersistenceExceptionTranslator;
+
+/**
+ * {@link PersistenceExceptionTranslator} capable of translating {@link HibernateException}
+ * instances to Spring's {@link DataAccessException} hierarchy.
+ *
+ *
Extended by {@link LocalSessionFactoryBean}, so there is no need to declare this
+ * translator in addition to a {@code LocalSessionFactoryBean}.
+ *
+ *
When configuring the container with {@code @Configuration} classes, a {@code @Bean}
+ * of this type must be registered manually.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ * @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
+ * @see SessionFactoryUtils#convertHibernateAccessException(HibernateException)
+ */
+public class HibernateExceptionTranslator implements PersistenceExceptionTranslator {
+
+ @Override
+ public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
+ if (ex instanceof HibernateException) {
+ return convertHibernateAccessException((HibernateException) ex);
+ }
+ return null;
+ }
+
+ /**
+ * Convert the given HibernateException to an appropriate exception from the
+ * {@code org.springframework.dao} hierarchy.
+ * @param ex HibernateException that occured
+ * @return a corresponding DataAccessException
+ * @see SessionFactoryUtils#convertHibernateAccessException
+ */
+ protected DataAccessException convertHibernateAccessException(HibernateException ex) {
+ return SessionFactoryUtils.convertHibernateAccessException(ex);
+ }
+
+}
diff --git a/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateJdbcException.java b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateJdbcException.java
new file mode 100644
index 0000000000..4d0bb9d593
--- /dev/null
+++ b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateJdbcException.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2002-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.hibernate5;
+
+import java.sql.SQLException;
+
+import org.hibernate.JDBCException;
+
+import org.springframework.dao.UncategorizedDataAccessException;
+
+/**
+ * Hibernate-specific subclass of UncategorizedDataAccessException,
+ * for JDBC exceptions that Hibernate wrapped.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ * @see SessionFactoryUtils#convertHibernateAccessException
+ */
+@SuppressWarnings("serial")
+public class HibernateJdbcException extends UncategorizedDataAccessException {
+
+ public HibernateJdbcException(JDBCException ex) {
+ super("JDBC exception on Hibernate data access: SQLException for SQL [" + ex.getSQL() + "]; SQL state [" +
+ ex.getSQLState() + "]; error code [" + ex.getErrorCode() + "]; " + ex.getMessage(), ex);
+ }
+
+ /**
+ * Return the underlying SQLException.
+ */
+ public SQLException getSQLException() {
+ return ((JDBCException) getCause()).getSQLException();
+ }
+
+ /**
+ * Return the SQL that led to the problem.
+ */
+ public String getSql() {
+ return ((JDBCException) getCause()).getSQL();
+ }
+
+}
diff --git a/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateObjectRetrievalFailureException.java b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateObjectRetrievalFailureException.java
new file mode 100644
index 0000000000..f4c96d5f69
--- /dev/null
+++ b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateObjectRetrievalFailureException.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2002-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.hibernate5;
+
+import org.hibernate.UnresolvableObjectException;
+import org.hibernate.WrongClassException;
+
+import org.springframework.orm.ObjectRetrievalFailureException;
+
+/**
+ * Hibernate-specific subclass of ObjectRetrievalFailureException.
+ * Converts Hibernate's UnresolvableObjectException and WrongClassException.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ * @see SessionFactoryUtils#convertHibernateAccessException
+ */
+@SuppressWarnings("serial")
+public class HibernateObjectRetrievalFailureException extends ObjectRetrievalFailureException {
+
+ public HibernateObjectRetrievalFailureException(UnresolvableObjectException ex) {
+ super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
+ }
+
+ public HibernateObjectRetrievalFailureException(WrongClassException ex) {
+ super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
+ }
+
+}
diff --git a/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateOperations.java b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateOperations.java
new file mode 100644
index 0000000000..d3ae8d7f0b
--- /dev/null
+++ b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateOperations.java
@@ -0,0 +1,795 @@
+/*
+ * Copyright 2002-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.hibernate5;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.hibernate.Filter;
+import org.hibernate.LockMode;
+import org.hibernate.ReplicationMode;
+import org.hibernate.criterion.DetachedCriteria;
+
+import org.springframework.dao.DataAccessException;
+
+/**
+ * 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.
+ *
+ *
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.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ * @see HibernateTemplate
+ * @see org.hibernate.Session
+ * @see HibernateTransactionManager
+ */
+public interface HibernateOperations {
+
+ /**
+ * Execute the action specified by the given action object within a
+ * {@link org.hibernate.Session}.
+ *
Application exceptions thrown by the action object get propagated
+ * to the caller (can only be unchecked). Hibernate exceptions are
+ * transformed into appropriate DAO ones. Allows for returning a result
+ * object, that is a domain object or a collection of domain objects.
+ *
Note: Callback code is not supposed to handle transactions itself!
+ * Use an appropriate transaction manager like
+ * {@link HibernateTransactionManager}. Generally, callback code must not
+ * touch any {@code Session} lifecycle methods, like close,
+ * disconnect, or reconnect, to let the template do its work.
+ * @param action callback object that specifies the Hibernate action
+ * @return a result object returned by the action, or {@code null}
+ * @throws DataAccessException in case of Hibernate errors
+ * @see HibernateTransactionManager
+ * @see org.hibernate.Session
+ */
+ T execute(HibernateCallback action) throws DataAccessException;
+
+
+ //-------------------------------------------------------------------------
+ // Convenience methods for loading individual objects
+ //-------------------------------------------------------------------------
+
+ /**
+ * Return the persistent instance of the given entity class
+ * with the given identifier, or {@code null} if not found.
+ *
This method is a thin wrapper around
+ * {@link org.hibernate.Session#get(Class, Serializable)} for convenience.
+ * For an explanation of the exact semantics of this method, please do refer to
+ * the Hibernate API documentation in the first instance.
+ * @param entityClass a persistent class
+ * @param id the identifier of the persistent instance
+ * @return the persistent instance, or {@code null} if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#get(Class, Serializable)
+ */
+ T get(Class entityClass, Serializable id) throws DataAccessException;
+
+ /**
+ * Return the persistent instance of the given entity class
+ * with the given identifier, or {@code null} if not found.
+ *
Obtains the specified lock mode if the instance exists.
+ *
This method is a thin wrapper around
+ * {@link org.hibernate.Session#get(Class, Serializable, LockMode)} for convenience.
+ * For an explanation of the exact semantics of this method, please do refer to
+ * the Hibernate API documentation in the first instance.
+ * @param entityClass a persistent class
+ * @param id the identifier of the persistent instance
+ * @param lockMode the lock mode to obtain
+ * @return the persistent instance, or {@code null} if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#get(Class, Serializable, LockMode)
+ */
+ T get(Class entityClass, Serializable id, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Return the persistent instance of the given entity class
+ * with the given identifier, or {@code null} if not found.
+ *
This method is a thin wrapper around
+ * {@link org.hibernate.Session#get(String, Serializable)} for convenience.
+ * For an explanation of the exact semantics of this method, please do refer to
+ * the Hibernate API documentation in the first instance.
+ * @param entityName the name of the persistent entity
+ * @param id the identifier of the persistent instance
+ * @return the persistent instance, or {@code null} if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#get(Class, Serializable)
+ */
+ Object get(String entityName, Serializable id) throws DataAccessException;
+
+ /**
+ * Return the persistent instance of the given entity class
+ * with the given identifier, or {@code null} if not found.
+ * Obtains the specified lock mode if the instance exists.
+ *
This method is a thin wrapper around
+ * {@link org.hibernate.Session#get(String, Serializable, LockMode)} for convenience.
+ * For an explanation of the exact semantics of this method, please do refer to
+ * the Hibernate API documentation in the first instance.
+ * @param entityName the name of the persistent entity
+ * @param id the identifier of the persistent instance
+ * @param lockMode the lock mode to obtain
+ * @return the persistent instance, or {@code null} if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#get(Class, Serializable, LockMode)
+ */
+ Object get(String entityName, Serializable id, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Return the persistent instance of the given entity class
+ * with the given identifier, throwing an exception if not found.
+ *
This method is a thin wrapper around
+ * {@link org.hibernate.Session#load(Class, Serializable)} for convenience.
+ * For an explanation of the exact semantics of this method, please do refer to
+ * the Hibernate API documentation in the first instance.
+ * @param entityClass a persistent class
+ * @param id the identifier of the persistent instance
+ * @return the persistent instance
+ * @throws org.springframework.orm.ObjectRetrievalFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#load(Class, Serializable)
+ */
+ T load(Class entityClass, Serializable id) throws DataAccessException;
+
+ /**
+ * Return the persistent instance of the given entity class
+ * with the given identifier, throwing an exception if not found.
+ * Obtains the specified lock mode if the instance exists.
+ *
This method is a thin wrapper around
+ * {@link org.hibernate.Session#load(Class, Serializable, LockMode)} for convenience.
+ * For an explanation of the exact semantics of this method, please do refer to
+ * the Hibernate API documentation in the first instance.
+ * @param entityClass a persistent class
+ * @param id the identifier of the persistent instance
+ * @param lockMode the lock mode to obtain
+ * @return the persistent instance
+ * @throws org.springframework.orm.ObjectRetrievalFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#load(Class, Serializable)
+ */
+ T load(Class entityClass, Serializable id, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Return the persistent instance of the given entity class
+ * with the given identifier, throwing an exception if not found.
+ *
This method is a thin wrapper around
+ * {@link org.hibernate.Session#load(String, Serializable)} for convenience.
+ * For an explanation of the exact semantics of this method, please do refer to
+ * the Hibernate API documentation in the first instance.
+ * @param entityName the name of the persistent entity
+ * @param id the identifier of the persistent instance
+ * @return the persistent instance
+ * @throws org.springframework.orm.ObjectRetrievalFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#load(Class, Serializable)
+ */
+ Object load(String entityName, Serializable id) throws DataAccessException;
+
+ /**
+ * Return the persistent instance of the given entity class
+ * with the given identifier, throwing an exception if not found.
+ *
Obtains the specified lock mode if the instance exists.
+ *
This method is a thin wrapper around
+ * {@link org.hibernate.Session#load(String, Serializable, LockMode)} for convenience.
+ * For an explanation of the exact semantics of this method, please do refer to
+ * the Hibernate API documentation in the first instance.
+ * @param entityName the name of the persistent entity
+ * @param id the identifier of the persistent instance
+ * @param lockMode the lock mode to obtain
+ * @return the persistent instance
+ * @throws org.springframework.orm.ObjectRetrievalFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#load(Class, Serializable)
+ */
+ Object load(String entityName, Serializable id, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Return all persistent instances of the given entity class.
+ * Note: Use queries or criteria for retrieving a specific subset.
+ * @param entityClass a persistent class
+ * @return a {@link List} containing 0 or more persistent instances
+ * @throws DataAccessException if there is a Hibernate error
+ * @see org.hibernate.Session#createCriteria
+ */
+ List loadAll(Class entityClass) throws DataAccessException;
+
+ /**
+ * Load the persistent instance with the given identifier
+ * into the given object, throwing an exception if not found.
+ *
This method is a thin wrapper around
+ * {@link org.hibernate.Session#load(Object, Serializable)} for convenience.
+ * For an explanation of the exact semantics of this method, please do refer to
+ * the Hibernate API documentation in the first instance.
+ * @param entity the object (of the target class) to load into
+ * @param id the identifier of the persistent instance
+ * @throws org.springframework.orm.ObjectRetrievalFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#load(Object, Serializable)
+ */
+ void load(Object entity, Serializable id) throws DataAccessException;
+
+ /**
+ * Re-read the state of the given persistent instance.
+ * @param entity the persistent instance to re-read
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#refresh(Object)
+ */
+ void refresh(Object entity) throws DataAccessException;
+
+ /**
+ * Re-read the state of the given persistent instance.
+ * Obtains the specified lock mode for the instance.
+ * @param entity the persistent instance to re-read
+ * @param lockMode the lock mode to obtain
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#refresh(Object, LockMode)
+ */
+ void refresh(Object entity, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Check whether the given object is in the Session cache.
+ * @param entity the persistence instance to check
+ * @return whether the given object is in the Session cache
+ * @throws DataAccessException if there is a Hibernate error
+ * @see org.hibernate.Session#contains
+ */
+ boolean contains(Object entity) throws DataAccessException;
+
+ /**
+ * Remove the given object from the {@link org.hibernate.Session} cache.
+ * @param entity the persistent instance to evict
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#evict
+ */
+ void evict(Object entity) throws DataAccessException;
+
+ /**
+ * Force initialization of a Hibernate proxy or persistent collection.
+ * @param proxy a proxy for a persistent object or a persistent collection
+ * @throws DataAccessException if we can't initialize the proxy, for example
+ * because it is not associated with an active Session
+ * @see org.hibernate.Hibernate#initialize
+ */
+ void initialize(Object proxy) throws DataAccessException;
+
+ /**
+ * Return an enabled Hibernate {@link Filter} for the given filter name.
+ * The returned {@code Filter} instance can be used to set filter parameters.
+ * @param filterName the name of the filter
+ * @return the enabled Hibernate {@code Filter} (either already
+ * enabled or enabled on the fly by this operation)
+ * @throws IllegalStateException if we are not running within a
+ * transactional Session (in which case this operation does not make sense)
+ */
+ Filter enableFilter(String filterName) throws IllegalStateException;
+
+
+ //-------------------------------------------------------------------------
+ // Convenience methods for storing individual objects
+ //-------------------------------------------------------------------------
+
+ /**
+ * Obtain the specified lock level upon the given object, implicitly
+ * checking whether the corresponding database entry still exists.
+ * @param entity the persistent instance to lock
+ * @param lockMode the lock mode to obtain
+ * @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#lock(Object, LockMode)
+ */
+ void lock(Object entity, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Obtain the specified lock level upon the given object, implicitly
+ * checking whether the corresponding database entry still exists.
+ * @param entityName the name of the persistent entity
+ * @param entity the persistent instance to lock
+ * @param lockMode the lock mode to obtain
+ * @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#lock(String, Object, LockMode)
+ */
+ void lock(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Persist the given transient instance.
+ * @param entity the transient instance to persist
+ * @return the generated identifier
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#save(Object)
+ */
+ Serializable save(Object entity) throws DataAccessException;
+
+ /**
+ * Persist the given transient instance.
+ * @param entityName the name of the persistent entity
+ * @param entity the transient instance to persist
+ * @return the generated identifier
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#save(String, Object)
+ */
+ Serializable save(String entityName, Object entity) throws DataAccessException;
+
+ /**
+ * Update the given persistent instance,
+ * associating it with the current Hibernate {@link org.hibernate.Session}.
+ * @param entity the persistent instance to update
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#update(Object)
+ */
+ void update(Object entity) throws DataAccessException;
+
+ /**
+ * Update the given persistent instance,
+ * associating it with the current Hibernate {@link org.hibernate.Session}.
+ *
Obtains the specified lock mode if the instance exists, implicitly
+ * checking whether the corresponding database entry still exists.
+ * @param entity the persistent instance to update
+ * @param lockMode the lock mode to obtain
+ * @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#update(Object)
+ */
+ void update(Object entity, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Update the given persistent instance,
+ * associating it with the current Hibernate {@link org.hibernate.Session}.
+ * @param entityName the name of the persistent entity
+ * @param entity the persistent instance to update
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#update(String, Object)
+ */
+ void update(String entityName, Object entity) throws DataAccessException;
+
+ /**
+ * Update the given persistent instance,
+ * associating it with the current Hibernate {@link org.hibernate.Session}.
+ *
Obtains the specified lock mode if the instance exists, implicitly
+ * checking whether the corresponding database entry still exists.
+ * @param entityName the name of the persistent entity
+ * @param entity the persistent instance to update
+ * @param lockMode the lock mode to obtain
+ * @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#update(String, Object)
+ */
+ void update(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Save or update the given persistent instance,
+ * according to its id (matching the configured "unsaved-value"?).
+ * Associates the instance with the current Hibernate {@link org.hibernate.Session}.
+ * @param entity the persistent instance to save or update
+ * (to be associated with the Hibernate {@code Session})
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#saveOrUpdate(Object)
+ */
+ void saveOrUpdate(Object entity) throws DataAccessException;
+
+ /**
+ * Save or update the given persistent instance,
+ * according to its id (matching the configured "unsaved-value"?).
+ * Associates the instance with the current Hibernate {@code Session}.
+ * @param entityName the name of the persistent entity
+ * @param entity the persistent instance to save or update
+ * (to be associated with the Hibernate {@code Session})
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#saveOrUpdate(String, Object)
+ */
+ void saveOrUpdate(String entityName, Object entity) throws DataAccessException;
+
+ /**
+ * Persist the state of the given detached instance according to the
+ * given replication mode, reusing the current identifier value.
+ * @param entity the persistent object to replicate
+ * @param replicationMode the Hibernate ReplicationMode
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#replicate(Object, ReplicationMode)
+ */
+ void replicate(Object entity, ReplicationMode replicationMode) throws DataAccessException;
+
+ /**
+ * Persist the state of the given detached instance according to the
+ * given replication mode, reusing the current identifier value.
+ * @param entityName the name of the persistent entity
+ * @param entity the persistent object to replicate
+ * @param replicationMode the Hibernate ReplicationMode
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#replicate(String, Object, ReplicationMode)
+ */
+ void replicate(String entityName, Object entity, ReplicationMode replicationMode) throws DataAccessException;
+
+ /**
+ * Persist the given transient instance. Follows JSR-220 semantics.
+ *
Similar to {@code save}, associating the given object
+ * with the current Hibernate {@link org.hibernate.Session}.
+ * @param entity the persistent instance to persist
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#persist(Object)
+ * @see #save
+ */
+ void persist(Object entity) throws DataAccessException;
+
+ /**
+ * Persist the given transient instance. Follows JSR-220 semantics.
+ *
Similar to {@code save}, associating the given object
+ * with the current Hibernate {@link org.hibernate.Session}.
+ * @param entityName the name of the persistent entity
+ * @param entity the persistent instance to persist
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#persist(String, Object)
+ * @see #save
+ */
+ void persist(String entityName, Object entity) throws DataAccessException;
+
+ /**
+ * Copy the state of the given object onto the persistent object
+ * with the same identifier. Follows JSR-220 semantics.
+ *
Similar to {@code saveOrUpdate}, but never associates the given
+ * object with the current Hibernate Session. In case of a new entity,
+ * the state will be copied over as well.
+ *
Note that {@code merge} will not update the identifiers
+ * in the passed-in object graph (in contrast to TopLink)! Consider
+ * registering Spring's {@code IdTransferringMergeEventListener} if
+ * you would like to have newly assigned ids transferred to the original
+ * object graph too.
+ * @param entity the object to merge with the corresponding persistence instance
+ * @return the updated, registered persistent instance
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#merge(Object)
+ * @see #saveOrUpdate
+ */
+ T merge(T entity) throws DataAccessException;
+
+ /**
+ * Copy the state of the given object onto the persistent object
+ * with the same identifier. Follows JSR-220 semantics.
+ *
Similar to {@code saveOrUpdate}, but never associates the given
+ * object with the current Hibernate {@link org.hibernate.Session}. In
+ * the case of a new entity, the state will be copied over as well.
+ *
Note that {@code merge} will not update the identifiers
+ * in the passed-in object graph (in contrast to TopLink)! Consider
+ * registering Spring's {@code IdTransferringMergeEventListener}
+ * if you would like to have newly assigned ids transferred to the
+ * original object graph too.
+ * @param entityName the name of the persistent entity
+ * @param entity the object to merge with the corresponding persistence instance
+ * @return the updated, registered persistent instance
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#merge(String, Object)
+ * @see #saveOrUpdate
+ */
+ T merge(String entityName, T entity) throws DataAccessException;
+
+ /**
+ * Delete the given persistent instance.
+ * @param entity the persistent instance to delete
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#delete(Object)
+ */
+ void delete(Object entity) throws DataAccessException;
+
+ /**
+ * Delete the given persistent instance.
+ *
Obtains the specified lock mode if the instance exists, implicitly
+ * checking whether the corresponding database entry still exists.
+ * @param entity the persistent instance to delete
+ * @param lockMode the lock mode to obtain
+ * @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#delete(Object)
+ */
+ void delete(Object entity, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Delete the given persistent instance.
+ * @param entityName the name of the persistent entity
+ * @param entity the persistent instance to delete
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#delete(Object)
+ */
+ void delete(String entityName, Object entity) throws DataAccessException;
+
+ /**
+ * Delete the given persistent instance.
+ *
Obtains the specified lock mode if the instance exists, implicitly
+ * checking whether the corresponding database entry still exists.
+ * @param entityName the name of the persistent entity
+ * @param entity the persistent instance to delete
+ * @param lockMode the lock mode to obtain
+ * @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#delete(Object)
+ */
+ void delete(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
+
+ /**
+ * Delete all given persistent instances.
+ *
This can be combined with any of the find methods to delete by query
+ * in two lines of code.
+ * @param entities the persistent instances to delete
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#delete(Object)
+ */
+ void deleteAll(Collection> entities) throws DataAccessException;
+
+ /**
+ * Flush all pending saves, updates and deletes to the database.
+ *
Only invoke this for selective eager flushing, for example when
+ * JDBC code needs to see certain changes within the same transaction.
+ * Else, it is preferable to rely on auto-flushing at transaction
+ * completion.
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#flush
+ */
+ void flush() throws DataAccessException;
+
+ /**
+ * Remove all objects from the {@link org.hibernate.Session} cache, and
+ * cancel all pending saves, updates and deletes.
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#clear
+ */
+ void clear() throws DataAccessException;
+
+
+ //-------------------------------------------------------------------------
+ // Convenience finder methods for HQL strings
+ //-------------------------------------------------------------------------
+
+ /**
+ * Execute an HQL query, binding a number of values to "?" parameters
+ * in the query string.
+ * @param queryString a query expressed in Hibernate's query language
+ * @param values the values of the parameters
+ * @return a {@link List} containing the results of the query execution
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#createQuery
+ */
+ List> find(String queryString, Object... values) throws DataAccessException;
+
+ /**
+ * Execute an HQL query, binding one value to a ":" named parameter
+ * in the query string.
+ * @param queryString a query expressed in Hibernate's query language
+ * @param paramName the name of the parameter
+ * @param value the value of the parameter
+ * @return a {@link List} containing the results of the query execution
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#getNamedQuery(String)
+ */
+ List> findByNamedParam(String queryString, String paramName, Object value) throws DataAccessException;
+
+ /**
+ * Execute an HQL query, binding a number of values to ":" named
+ * parameters in the query string.
+ * @param queryString a query expressed in Hibernate's query language
+ * @param paramNames the names of the parameters
+ * @param values the values of the parameters
+ * @return a {@link List} containing the results of the query execution
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#getNamedQuery(String)
+ */
+ List> findByNamedParam(String queryString, String[] paramNames, Object[] values) throws DataAccessException;
+
+ /**
+ * Execute an HQL query, binding the properties of the given bean to
+ * named parameters in the query string.
+ * @param queryString a query expressed in Hibernate's query language
+ * @param valueBean the values of the parameters
+ * @return a {@link List} containing the results of the query execution
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Query#setProperties
+ * @see org.hibernate.Session#createQuery
+ */
+ List> findByValueBean(String queryString, Object valueBean) throws DataAccessException;
+
+
+ //-------------------------------------------------------------------------
+ // Convenience finder methods for named queries
+ //-------------------------------------------------------------------------
+
+ /**
+ * Execute a named query binding a number of values to "?" parameters
+ * in the query string.
+ *
A named query is defined in a Hibernate mapping file.
+ * @param queryName the name of a Hibernate query in a mapping file
+ * @param values the values of the parameters
+ * @return a {@link List} containing the results of the query execution
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#getNamedQuery(String)
+ */
+ List> findByNamedQuery(String queryName, Object... values) throws DataAccessException;
+
+ /**
+ * Execute a named query, binding one value to a ":" named parameter
+ * in the query string.
+ *
A named query is defined in a Hibernate mapping file.
+ * @param queryName the name of a Hibernate query in a mapping file
+ * @param paramName the name of parameter
+ * @param value the value of the parameter
+ * @return a {@link List} containing the results of the query execution
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#getNamedQuery(String)
+ */
+ List> findByNamedQueryAndNamedParam(String queryName, String paramName, Object value)
+ throws DataAccessException;
+
+ /**
+ * Execute a named query, binding a number of values to ":" named
+ * parameters in the query string.
+ *
A named query is defined in a Hibernate mapping file.
+ * @param queryName the name of a Hibernate query in a mapping file
+ * @param paramNames the names of the parameters
+ * @param values the values of the parameters
+ * @return a {@link List} containing the results of the query execution
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#getNamedQuery(String)
+ */
+ List> findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values)
+ throws DataAccessException;
+
+ /**
+ * Execute a named query, binding the properties of the given bean to
+ * ":" named parameters in the query string.
+ *
A named query is defined in a Hibernate mapping file.
+ * @param queryName the name of a Hibernate query in a mapping file
+ * @param valueBean the values of the parameters
+ * @return a {@link List} containing the results of the query execution
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Query#setProperties
+ * @see org.hibernate.Session#getNamedQuery(String)
+ */
+ List> findByNamedQueryAndValueBean(String queryName, Object valueBean) 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)
+ */
+ List findByExample(T exampleEntity) throws DataAccessException;
+
+ /**
+ * Execute a query based on the given example entity object.
+ * @param entityName the name of the persistent entity
+ * @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)
+ */
+ List findByExample(String entityName, T exampleEntity) throws DataAccessException;
+
+ /**
+ * Execute a query based on a given example entity object.
+ * @param exampleEntity an instance of the desired entity,
+ * serving as example for "query-by-example"
+ * @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 org.hibernate.criterion.Example#create(Object)
+ * @see org.hibernate.Criteria#setFirstResult(int)
+ * @see org.hibernate.Criteria#setMaxResults(int)
+ */
+ List findByExample(T exampleEntity, int firstResult, int maxResults) throws DataAccessException;
+
+ /**
+ * Execute a query based on a given example entity object.
+ * @param entityName the name of the persistent entity
+ * @param exampleEntity an instance of the desired entity,
+ * serving as example for "query-by-example"
+ * @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 org.hibernate.criterion.Example#create(Object)
+ * @see org.hibernate.Criteria#setFirstResult(int)
+ * @see org.hibernate.Criteria#setMaxResults(int)
+ */
+ List findByExample(String entityName, T exampleEntity, int firstResult, int maxResults)
+ throws DataAccessException;
+
+
+ //-------------------------------------------------------------------------
+ // Convenience query methods for iteration and bulk updates/deletes
+ //-------------------------------------------------------------------------
+
+ /**
+ * Execute a query for persistent instances, binding a number of
+ * values to "?" parameters in the query string.
+ *
Returns the results as an {@link Iterator}. Entities returned are
+ * initialized on demand. See the Hibernate API documentation for details.
+ * @param queryString a query expressed in Hibernate's query language
+ * @param values the values of the parameters
+ * @return an {@link Iterator} containing 0 or more persistent instances
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#createQuery
+ * @see org.hibernate.Query#iterate
+ */
+ Iterator> iterate(String queryString, Object... values) throws DataAccessException;
+
+ /**
+ * Immediately close an {@link Iterator} created by any of the various
+ * {@code iterate(..)} operations, instead of waiting until the
+ * session is closed or disconnected.
+ * @param it the {@code Iterator} to close
+ * @throws DataAccessException if the {@code Iterator} could not be closed
+ * @see org.hibernate.Hibernate#close
+ */
+ void closeIterator(Iterator> it) throws DataAccessException;
+
+ /**
+ * Update/delete all objects according to the given query, binding a number of
+ * values to "?" parameters in the query string.
+ * @param queryString an update/delete query expressed in Hibernate's query language
+ * @param values the values of the parameters
+ * @return the number of instances updated/deleted
+ * @throws DataAccessException in case of Hibernate errors
+ * @see org.hibernate.Session#createQuery
+ * @see org.hibernate.Query#executeUpdate
+ */
+ int bulkUpdate(String queryString, Object... values) throws DataAccessException;
+
+}
diff --git a/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateOptimisticLockingFailureException.java b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateOptimisticLockingFailureException.java
new file mode 100644
index 0000000000..0d9121f1a7
--- /dev/null
+++ b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateOptimisticLockingFailureException.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2002-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.hibernate5;
+
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.StaleStateException;
+import org.hibernate.dialect.lock.OptimisticEntityLockException;
+
+import org.springframework.orm.ObjectOptimisticLockingFailureException;
+
+/**
+ * Hibernate-specific subclass of ObjectOptimisticLockingFailureException.
+ * Converts Hibernate's StaleObjectStateException, StaleStateException
+ * and OptimisticEntityLockException.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ * @see SessionFactoryUtils#convertHibernateAccessException
+ */
+@SuppressWarnings("serial")
+public class HibernateOptimisticLockingFailureException extends ObjectOptimisticLockingFailureException {
+
+ public HibernateOptimisticLockingFailureException(StaleObjectStateException ex) {
+ super(ex.getEntityName(), ex.getIdentifier(), ex);
+ }
+
+ public HibernateOptimisticLockingFailureException(StaleStateException ex) {
+ super(ex.getMessage(), ex);
+ }
+
+ public HibernateOptimisticLockingFailureException(OptimisticEntityLockException ex) {
+ super(ex.getMessage(), ex);
+ }
+
+}
diff --git a/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateQueryException.java b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateQueryException.java
new file mode 100644
index 0000000000..013c362315
--- /dev/null
+++ b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateQueryException.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2002-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.hibernate5;
+
+import org.hibernate.QueryException;
+
+import org.springframework.dao.InvalidDataAccessResourceUsageException;
+
+/**
+ * Hibernate-specific subclass of InvalidDataAccessResourceUsageException,
+ * thrown on invalid HQL query syntax.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ * @see SessionFactoryUtils#convertHibernateAccessException
+ */
+@SuppressWarnings("serial")
+public class HibernateQueryException extends InvalidDataAccessResourceUsageException {
+
+ public HibernateQueryException(QueryException ex) {
+ super(ex.getMessage(), ex);
+ }
+
+ /**
+ * Return the HQL query string that was invalid.
+ */
+ public String getQueryString() {
+ return ((QueryException) getCause()).getQueryString();
+ }
+
+}
diff --git a/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateSystemException.java b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateSystemException.java
new file mode 100644
index 0000000000..21ef842abe
--- /dev/null
+++ b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateSystemException.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2002-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.hibernate5;
+
+import org.hibernate.HibernateException;
+
+import org.springframework.dao.UncategorizedDataAccessException;
+
+/**
+ * Hibernate-specific subclass of UncategorizedDataAccessException,
+ * for Hibernate system errors that do not match any concrete
+ * {@code org.springframework.dao} exceptions.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ * @see SessionFactoryUtils#convertHibernateAccessException
+ */
+@SuppressWarnings("serial")
+public class HibernateSystemException extends UncategorizedDataAccessException {
+
+ /**
+ * Create a new HibernateSystemException,
+ * wrapping an arbitrary HibernateException.
+ * @param cause the HibernateException thrown
+ */
+ public HibernateSystemException(HibernateException cause) {
+ super(cause != null ? cause.getMessage() : null, cause);
+ }
+
+}
diff --git a/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java
new file mode 100644
index 0000000000..f52d46c1fa
--- /dev/null
+++ b/spring-orm-hibernate5/src/main/java/org/springframework/orm/hibernate5/HibernateTemplate.java
@@ -0,0 +1,1270 @@
+/*
+ * Copyright 2002-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.orm.hibernate5;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.Criteria;
+import org.hibernate.Filter;
+import org.hibernate.FlushMode;
+import org.hibernate.Hibernate;
+import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
+import org.hibernate.LockOptions;
+import org.hibernate.Query;
+import org.hibernate.ReplicationMode;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.criterion.DetachedCriteria;
+import org.hibernate.criterion.Example;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.util.Assert;
+
+/**
+ * Helper class that simplifies Hibernate data access code. Automatically
+ * converts HibernateExceptions into DataAccessExceptions, following the
+ * {@code org.springframework.dao} exception hierarchy.
+ *
+ *
The central method is {@code execute}, supporting Hibernate access code
+ * implementing the {@link HibernateCallback} interface. It provides Hibernate Session
+ * handling such that neither the HibernateCallback implementation nor the calling
+ * code needs to explicitly care about retrieving/closing Hibernate Sessions,
+ * or handling Session lifecycle exceptions. For typical single step actions,
+ * there are various convenience methods (find, load, saveOrUpdate, delete).
+ *
+ *
Can be used within a service implementation via direct instantiation
+ * with a SessionFactory reference, or get prepared in an application context
+ * and given to services as bean reference. Note: The SessionFactory should
+ * always be configured as bean in the application context, in the first case
+ * given to the service directly, in the second case to the prepared template.
+ *
+ *
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 4.x.
+ *
+ * @author Juergen Hoeller
+ * @since 4.2
+ * @see #setSessionFactory
+ * @see HibernateCallback
+ * @see Session
+ * @see LocalSessionFactoryBean
+ * @see HibernateTransactionManager
+ * @see org.springframework.orm.hibernate5.support.OpenSessionInViewFilter
+ * @see org.springframework.orm.hibernate5.support.OpenSessionInViewInterceptor
+ */
+public class HibernateTemplate implements HibernateOperations, InitializingBean {
+
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private SessionFactory sessionFactory;
+
+ private String[] filterNames;
+
+ private boolean exposeNativeSession = false;
+
+ private boolean checkWriteOperations = true;
+
+ private boolean cacheQueries = false;
+
+ private String queryCacheRegion;
+
+ private int fetchSize = 0;
+
+ private int maxResults = 0;
+
+
+ /**
+ * Create a new HibernateTemplate instance.
+ */
+ public HibernateTemplate() {
+ }
+
+ /**
+ * Create a new HibernateTemplate instance.
+ * @param sessionFactory the SessionFactory to create Sessions with
+ */
+ public HibernateTemplate(SessionFactory sessionFactory) {
+ setSessionFactory(sessionFactory);
+ afterPropertiesSet();
+ }
+
+
+ /**
+ * Set the Hibernate SessionFactory that should be used to create
+ * Hibernate Sessions.
+ */
+ public void setSessionFactory(SessionFactory sessionFactory) {
+ this.sessionFactory = sessionFactory;
+ }
+
+ /**
+ * Return the Hibernate SessionFactory that should be used to create
+ * Hibernate Sessions.
+ */
+ public SessionFactory getSessionFactory() {
+ return this.sessionFactory;
+ }
+
+ /**
+ * Set one or more names of Hibernate filters to be activated for all
+ * Sessions that this accessor works with.
+ *
Each of those filters will be enabled at the beginning of each
+ * operation and correspondingly disabled at the end of the operation.
+ * This will work for newly opened Sessions as well as for existing
+ * Sessions (for example, within a transaction).
+ * @see #enableFilters(Session)
+ * @see Session#enableFilter(String)
+ */
+ public void setFilterNames(String... filterNames) {
+ this.filterNames = filterNames;
+ }
+
+ /**
+ * Return the names of Hibernate filters to be activated, if any.
+ */
+ public String[] getFilterNames() {
+ return this.filterNames;
+ }
+
+ /**
+ * Set whether to expose the native Hibernate Session to
+ * HibernateCallback code.
+ *
Default is "false": a Session proxy will be returned, suppressing
+ * {@code close} calls and automatically applying query cache
+ * settings and transaction timeouts.
+ * @see HibernateCallback
+ * @see Session
+ * @see #setCacheQueries
+ * @see #setQueryCacheRegion
+ * @see #prepareQuery
+ * @see #prepareCriteria
+ */
+ public void setExposeNativeSession(boolean exposeNativeSession) {
+ this.exposeNativeSession = exposeNativeSession;
+ }
+
+ /**
+ * Return whether to expose the native Hibernate Session to
+ * HibernateCallback code, or rather a Session proxy.
+ */
+ public boolean isExposeNativeSession() {
+ return this.exposeNativeSession;
+ }
+
+ /**
+ * Set whether to check that the Hibernate Session is not in read-only mode
+ * in case of write operations (save/update/delete).
+ *
Default is "true", for fail-fast behavior when attempting write operations
+ * within a read-only transaction. Turn this off to allow save/update/delete
+ * on a Session with flush mode MANUAL.
+ * @see #checkWriteOperationAllowed
+ * @see org.springframework.transaction.TransactionDefinition#isReadOnly
+ */
+ public void setCheckWriteOperations(boolean checkWriteOperations) {
+ this.checkWriteOperations = checkWriteOperations;
+ }
+
+ /**
+ * Return whether to check that the Hibernate Session is not in read-only
+ * mode in case of write operations (save/update/delete).
+ */
+ public boolean isCheckWriteOperations() {
+ return this.checkWriteOperations;
+ }
+
+ /**
+ * Set whether to cache all queries executed by this template.
+ *
If this is "true", all Query and Criteria objects created by
+ * this template will be marked as cacheable (including all
+ * queries through find methods).
+ *
To specify the query region to be used for queries cached
+ * by this template, set the "queryCacheRegion" property.
+ * @see #setQueryCacheRegion
+ * @see Query#setCacheable
+ * @see Criteria#setCacheable
+ */
+ public void setCacheQueries(boolean cacheQueries) {
+ this.cacheQueries = cacheQueries;
+ }
+
+ /**
+ * Return whether to cache all queries executed by this template.
+ */
+ public boolean isCacheQueries() {
+ return this.cacheQueries;
+ }
+
+ /**
+ * Set the name of the cache region for queries executed by this template.
+ *
If this is specified, it will be applied to all Query and Criteria objects
+ * created by this template (including all queries through find methods).
+ *
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 Query#setCacheRegion
+ * @see Criteria#setCacheRegion
+ */
+ public void setQueryCacheRegion(String queryCacheRegion) {
+ this.queryCacheRegion = queryCacheRegion;
+ }
+
+ /**
+ * Return the name of the cache region for queries executed by this template.
+ */
+ public String getQueryCacheRegion() {
+ return this.queryCacheRegion;
+ }
+
+ /**
+ * Set the fetch size for this HibernateTemplate. This is important for processing
+ * large result sets: Setting this higher than the default value will increase
+ * processing speed at the cost of memory consumption; setting this lower can
+ * avoid transferring row data that will never be read by the application.
+ *
Default is 0, indicating to use the JDBC driver's default.
+ */
+ public void setFetchSize(int fetchSize) {
+ this.fetchSize = fetchSize;
+ }
+
+ /**
+ * Return the fetch size specified for this HibernateTemplate.
+ */
+ public int getFetchSize() {
+ return this.fetchSize;
+ }
+
+ /**
+ * Set the maximum number of rows for this HibernateTemplate. This is important
+ * for processing subsets of large result sets, avoiding to read and hold
+ * the entire result set in the database or in the JDBC driver if we're
+ * never interested in the entire result in the first place (for example,
+ * when performing searches that might return a large number of matches).
+ *
Default is 0, indicating to use the JDBC driver's default.
+ */
+ public void setMaxResults(int maxResults) {
+ this.maxResults = maxResults;
+ }
+
+ /**
+ * Return the maximum number of rows specified for this HibernateTemplate.
+ */
+ public int getMaxResults() {
+ return this.maxResults;
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ if (getSessionFactory() == null) {
+ throw new IllegalArgumentException("Property 'sessionFactory' is required");
+ }
+ }
+
+
+ @Override
+ public T execute(HibernateCallback action) throws DataAccessException {
+ return doExecute(action, false);
+ }
+
+ /**
+ * Execute the action specified by the given action object within a
+ * native {@link Session}.
+ *
This execute variant overrides the template-wide
+ * {@link #isExposeNativeSession() "exposeNativeSession"} setting.
+ * @param action callback object that specifies the Hibernate action
+ * @return a result object returned by the action, or {@code null}
+ * @throws DataAccessException in case of Hibernate errors
+ */
+ public T executeWithNativeSession(HibernateCallback action) {
+ return doExecute(action, true);
+ }
+
+ /**
+ * Execute the action specified by the given action object within a Session.
+ * @param action callback object that specifies the Hibernate action
+ * @param enforceNativeSession whether to enforce exposure of the native
+ * Hibernate Session to callback code
+ * @return a result object returned by the action, or {@code null}
+ * @throws DataAccessException in case of Hibernate errors
+ */
+ protected T doExecute(HibernateCallback action, boolean enforceNativeSession) throws DataAccessException {
+ Assert.notNull(action, "Callback object must not be null");
+
+ Session session = null;
+ boolean isNew = false;
+ try {
+ session = getSessionFactory().getCurrentSession();
+ }
+ catch (HibernateException ex) {
+ logger.debug("Could not retrieve pre-bound Hibernate session", ex);
+ }
+ if (session == null) {
+ session = getSessionFactory().openSession();
+ session.setFlushMode(FlushMode.MANUAL);
+ isNew = true;
+ }
+
+ try {
+ enableFilters(session);
+ Session sessionToExpose =
+ (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));
+ return action.doInHibernate(sessionToExpose);
+ }
+ catch (HibernateException ex) {
+ throw SessionFactoryUtils.convertHibernateAccessException(ex);
+ }
+ catch (RuntimeException ex) {
+ // Callback code threw application exception...
+ throw ex;
+ }
+ finally {
+ if (isNew) {
+ SessionFactoryUtils.closeSession(session);
+ }
+ else {
+ disableFilters(session);
+ }
+ }
+ }
+
+ /**
+ * Create a close-suppressing proxy for the given Hibernate Session.
+ * The proxy also prepares returned Query and Criteria objects.
+ * @param session the Hibernate Session to create a proxy for
+ * @return the Session proxy
+ * @see Session#close()
+ * @see #prepareQuery
+ * @see #prepareCriteria
+ */
+ protected Session createSessionProxy(Session session) {
+ return (Session) Proxy.newProxyInstance(
+ session.getClass().getClassLoader(), new Class>[] {Session.class},
+ new CloseSuppressingInvocationHandler(session));
+ }
+
+ /**
+ * Enable the specified filters on the given Session.
+ * @param session the current Hibernate Session
+ * @see #setFilterNames
+ * @see Session#enableFilter(String)
+ */
+ protected void enableFilters(Session session) {
+ String[] filterNames = getFilterNames();
+ if (filterNames != null) {
+ for (String filterName : filterNames) {
+ session.enableFilter(filterName);
+ }
+ }
+ }
+
+ /**
+ * Disable the specified filters on the given Session.
+ * @param session the current Hibernate Session
+ * @see #setFilterNames
+ * @see Session#disableFilter(String)
+ */
+ protected void disableFilters(Session session) {
+ String[] filterNames = getFilterNames();
+ if (filterNames != null) {
+ for (String filterName : filterNames) {
+ session.disableFilter(filterName);
+ }
+ }
+ }
+
+
+ //-------------------------------------------------------------------------
+ // Convenience methods for loading individual objects
+ //-------------------------------------------------------------------------
+
+ @Override
+ public T get(Class entityClass, Serializable id) throws DataAccessException {
+ return get(entityClass, id, null);
+ }
+
+ @Override
+ public T get(final Class entityClass, final Serializable id, final LockMode lockMode)
+ throws DataAccessException {
+
+ return executeWithNativeSession(new HibernateCallback() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public T doInHibernate(Session session) throws HibernateException {
+ if (lockMode != null) {
+ return (T) session.get(entityClass, id, new LockOptions(lockMode));
+ }
+ else {
+ return (T) session.get(entityClass, id);
+ }
+ }
+ });
+ }
+
+ @Override
+ public Object get(String entityName, Serializable id) throws DataAccessException {
+ return get(entityName, id, null);
+ }
+
+ @Override
+ public Object get(final String entityName, final Serializable id, final LockMode lockMode)
+ throws DataAccessException {
+
+ return executeWithNativeSession(new HibernateCallback