Last active
December 4, 2024 12:26
Revisions
-
jelies revised this gist
Mar 17, 2013 . 1 changed file with 0 additions and 17 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,28 +1,11 @@ package com.jelies.spring3tomcat7.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import com.jelies.spring3tomcat7.config.util.hibernate.StatelessSessionFactoryBean; @Configuration -
jelies created this gist
Mar 17, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,35 @@ package com.jelies.spring3tomcat7.repository; import org.hibernate.Criteria; import org.hibernate.ScrollableResults; import org.hibernate.StatelessSession; import org.hibernate.Transaction; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.joda.time.LocalDate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import com.jelies.spring3tomcat7.model.entity.User; public class MyRepositoryImpl implements MyRepositoryCustom { @Autowired private StatelessSession statelessSession; @Override @Transactional public void myBatchStatements() { Criteria c = statelessSession.createCriteria(User.class); ScrollableResults itemCursor = c.scroll(); while (itemCursor.next()) { myUpdate((User) itemCursor.get(0)); } itemCursor.close(); return true; } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,41 @@ package com.jelies.spring3tomcat7.config; import java.util.Properties; import javax.annotation.PostConstruct; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.orm.hibernate3.HibernateExceptionTranslator; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaDialect; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import com.jelies.spring3tomcat7.config.util.ConfigUtils; import com.jelies.spring3tomcat7.config.util.hibernate.StatelessSessionFactoryBean; @Configuration @EnableTransactionManagement @EnableJpaRepositories("com.jelies.spring3tomcat7.repository") public class PersistenceConfig implements TransactionManagementConfigurer { ... @Bean public StatelessSessionFactoryBean statelessSessionFactory() { return new StatelessSessionFactoryBean(); } ... } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,163 @@ package com.jelies.spring3tomcat7.config.spring; import static org.springframework.orm.jpa.EntityManagerFactoryUtils.ENTITY_MANAGER_SYNCHRONIZATION_ORDER; import static org.springframework.util.ReflectionUtils.invokeMethod; import java.sql.Connection; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.hibernate.SessionFactory; import org.hibernate.StatelessSession; import org.hibernate.ejb.HibernateEntityManagerFactory; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.transaction.spi.TransactionContext; import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.orm.jpa.EntityManagerFactoryUtils; import org.springframework.orm.jpa.LocalEntityManagerFactoryBean; import org.springframework.transaction.support.ResourceHolderSynchronization; import org.springframework.transaction.support.TransactionSynchronizationAdapter; import org.springframework.transaction.support.TransactionSynchronizationManager; /** * Hibernate's {@link StatelessSession} factory which will be bound to the * current transaction. This factory returns a Proxy which delegates method * calls to the underlying {@link StatelessSession} bound to transaction. At the * end of the transaction the session is automatically closed. This class * borrows idea's from {@link DataSourceUtils}, * {@link EntityManagerFactoryUtils}, {@link ResourceHolderSynchronization} and * {@link LocalEntityManagerFactoryBean}. */ public class StatelessSessionFactoryBean implements FactoryBean<StatelessSession> { private final HibernateEntityManagerFactory entityManagerFactory; private SessionFactory sessionFactory; @Autowired public StatelessSessionFactoryBean(HibernateEntityManagerFactory entityManagerFactory) { this.entityManagerFactory = entityManagerFactory; this.sessionFactory = entityManagerFactory.getSessionFactory(); } /** * Use this to override the {@link SessionFactory} obtained from the * {@link EntityManagerFactory}. Please note that the connection will still * be used from the {@link EntityManager}. */ public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Override public StatelessSession getObject() throws Exception { StatelessSessionInterceptor statelessSessionInterceptor = new StatelessSessionInterceptor( entityManagerFactory, sessionFactory); return ProxyFactory.getProxy(StatelessSession.class, statelessSessionInterceptor); } @Override public Class<?> getObjectType() { return StatelessSession.class; } @Override public boolean isSingleton() { return true; } private static class StatelessSessionInterceptor implements MethodInterceptor { private final EntityManagerFactory entityManagerFactory; private final SessionFactory sessionFactory; public StatelessSessionInterceptor(EntityManagerFactory entityManagerFactory, SessionFactory sessionFactory) { this.entityManagerFactory = entityManagerFactory; this.sessionFactory = sessionFactory; } @Override public Object invoke(MethodInvocation invocation) throws Throwable { StatelessSession statelessSession = getCurrentSession(); return invokeMethod(invocation.getMethod(), statelessSession, invocation.getArguments()); } private StatelessSession getCurrentSession() { if (!TransactionSynchronizationManager.isActualTransactionActive()) { throw new IllegalStateException( "There should be an active transaction for the current thread."); } StatelessSession statelessSession = (StatelessSession) TransactionSynchronizationManager .getResource(sessionFactory); if (statelessSession == null) { statelessSession = openNewStatelessSession(); bindWithTransaction(statelessSession); } return statelessSession; } private StatelessSession openNewStatelessSession() { Connection connection = obtainPhysicalConnection(); return sessionFactory.openStatelessSession(connection); } /** * It is important we obtain the physical (real) connection otherwise it * will be double proxied and there will be problems releasing the * connection. */ private Connection obtainPhysicalConnection() { EntityManager entityManager = EntityManagerFactoryUtils .getTransactionalEntityManager(entityManagerFactory); SessionImplementor sessionImplementor = (SessionImplementor) entityManager .getDelegate(); return sessionImplementor.getTransactionCoordinator().getJdbcCoordinator() .getLogicalConnection().getConnection(); } private void bindWithTransaction(StatelessSession statelessSession) { TransactionSynchronizationManager .registerSynchronization(new StatelessSessionSynchronization(sessionFactory, statelessSession)); TransactionSynchronizationManager.bindResource(sessionFactory, statelessSession); } } private static class StatelessSessionSynchronization extends TransactionSynchronizationAdapter { private final SessionFactory sessionFactory; private final StatelessSession statelessSession; public StatelessSessionSynchronization(SessionFactory sessionFactory, StatelessSession statelessSession) { this.sessionFactory = sessionFactory; this.statelessSession = statelessSession; } @Override public int getOrder() { return ENTITY_MANAGER_SYNCHRONIZATION_ORDER - 100; } @Override public void beforeCommit(boolean readOnly) { if (!readOnly) { ((TransactionContext) statelessSession).managedFlush(); } } @Override public void beforeCompletion() { TransactionSynchronizationManager.unbindResource(sessionFactory); statelessSession.close(); } } }