HibernateTransactionManager for Hibernate 4 supports "entityInterceptor(BeanName)" property
Issue: SPR-10301
This commit is contained in:
parent
0d69a630ad
commit
096972d2b1
|
|
@ -22,12 +22,16 @@ import javax.sql.DataSource;
|
|||
import org.hibernate.ConnectionReleaseMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.transaction.spi.TransactionContext;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
|
|
@ -100,7 +104,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
|||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class HibernateTransactionManager extends AbstractPlatformTransactionManager
|
||||
implements ResourceTransactionManager, InitializingBean {
|
||||
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
|
|
@ -112,6 +116,14 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
|
|||
|
||||
private boolean hibernateManagedSession = false;
|
||||
|
||||
private Object entityInterceptor;
|
||||
|
||||
/**
|
||||
* Just needed for entityInterceptorBeanName.
|
||||
* @see #setEntityInterceptorBeanName
|
||||
*/
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new HibernateTransactionManager instance.
|
||||
|
|
@ -229,7 +241,7 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
|
|||
* to always return a proper Session when called for a Spring-managed transaction;
|
||||
* transaction begin will fail if the {@code getCurrentSession()} call fails.
|
||||
* <p>This mode will typically be used in combination with a custom Hibernate
|
||||
* {@link org.hibernate.context.CurrentSessionContext} implementation that stores
|
||||
* {@link org.hibernate.context.spi.CurrentSessionContext} implementation that stores
|
||||
* Sessions in a place other than Spring's TransactionSynchronizationManager.
|
||||
* It may also be used in combination with Spring's Open-Session-in-View support
|
||||
* (using Spring's default {@link SpringSessionContext}), in which case it subtly
|
||||
|
|
@ -242,10 +254,81 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
|
|||
this.hibernateManagedSession = hibernateManagedSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean name of a Hibernate entity interceptor that allows to inspect
|
||||
* and change property values before writing to and reading from the database.
|
||||
* Will get applied to any new Session created by this transaction manager.
|
||||
* <p>Requires the bean factory to be known, to be able to resolve the bean
|
||||
* name to an interceptor instance on session creation. Typically used for
|
||||
* prototype interceptors, i.e. a new interceptor instance per session.
|
||||
* <p>Can also be used for shared interceptor instances, but it is recommended
|
||||
* to set the interceptor reference directly in such a scenario.
|
||||
* @param entityInterceptorBeanName the name of the entity interceptor in
|
||||
* the bean factory
|
||||
* @see #setBeanFactory
|
||||
* @see #setEntityInterceptor
|
||||
*/
|
||||
public void setEntityInterceptorBeanName(String entityInterceptorBeanName) {
|
||||
this.entityInterceptor = entityInterceptorBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Hibernate entity interceptor that allows to inspect and change
|
||||
* property values before writing to and reading from the database.
|
||||
* Will get applied to any new Session created by this transaction manager.
|
||||
* <p>Such an interceptor can either be set at the SessionFactory level,
|
||||
* i.e. on LocalSessionFactoryBean, or at the Session level, i.e. on
|
||||
* HibernateTemplate, HibernateInterceptor, and HibernateTransactionManager.
|
||||
* It's preferable to set it on LocalSessionFactoryBean or HibernateTransactionManager
|
||||
* to avoid repeated configuration and guarantee consistent behavior in transactions.
|
||||
* @see LocalSessionFactoryBean#setEntityInterceptor
|
||||
*/
|
||||
public void setEntityInterceptor(Interceptor entityInterceptor) {
|
||||
this.entityInterceptor = entityInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current Hibernate entity interceptor, or {@code null} if none.
|
||||
* Resolves an entity interceptor bean name via the bean factory,
|
||||
* if necessary.
|
||||
* @throws IllegalStateException if bean name specified but no bean factory set
|
||||
* @throws BeansException if bean name resolution via the bean factory failed
|
||||
* @see #setEntityInterceptor
|
||||
* @see #setEntityInterceptorBeanName
|
||||
* @see #setBeanFactory
|
||||
*/
|
||||
public Interceptor getEntityInterceptor() throws IllegalStateException, BeansException {
|
||||
if (this.entityInterceptor instanceof Interceptor) {
|
||||
return (Interceptor) entityInterceptor;
|
||||
}
|
||||
else if (this.entityInterceptor instanceof String) {
|
||||
if (this.beanFactory == null) {
|
||||
throw new IllegalStateException("Cannot get entity interceptor via bean name if no bean factory set");
|
||||
}
|
||||
String beanName = (String) this.entityInterceptor;
|
||||
return this.beanFactory.getBean(beanName, Interceptor.class);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The bean factory just needs to be known for resolving entity interceptor
|
||||
* bean names. It does not need to be set for any other mode of operation.
|
||||
* @see #setEntityInterceptorBeanName
|
||||
*/
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
if (getSessionFactory() == null) {
|
||||
throw new IllegalArgumentException("Property 'sessionFactory' is required");
|
||||
}
|
||||
if (this.entityInterceptor instanceof String && this.beanFactory == null) {
|
||||
throw new IllegalArgumentException("Property 'beanFactory' is required for 'entityInterceptorBeanName'");
|
||||
}
|
||||
|
||||
// Check for SessionFactory's DataSource.
|
||||
if (this.autodetectDataSource && getDataSource() == null) {
|
||||
|
|
@ -325,7 +408,10 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
|
|||
|
||||
try {
|
||||
if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
|
||||
Session newSession = getSessionFactory().openSession();
|
||||
Interceptor entityInterceptor = getEntityInterceptor();
|
||||
Session newSession = (entityInterceptor != null ?
|
||||
getSessionFactory().withOptions().interceptor(entityInterceptor).openSession() :
|
||||
getSessionFactory().openSession());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Opened new Session [" + newSession + "] for Hibernate transaction");
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue