Hi,
thanks for the answer.
So, what I did in order to *not* change a lot my JUnit tests code was:
1) use a single DAO interface (with generic methods) that has the @Transational annotation and proxying its classic HibernateTemplate based implementation by means of the TransactionProxyFactoryBean
Code:
@Transactional
public interface PersistenceManager {
public <T> List<T> findAll(Class<T> entityClass);
public <T> T findById(Class<T> entityClass, Long id);
public <T> void saveOrUpdate(T entity);
public <T> T merge(T entity);
public <T> void remove(T entity);
public <T> void removeAll(Class<T> entityClass);
// ... others
}
Code:
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="persistenceManagerTarget" class="org.mypackage.persistence.hibernate.PersistenceManagerHibernate">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="persistenceManager"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="txManager" />
<property name="target" ref="persistenceManagerTarget" />
<property name="transactionAttributeSource">
<bean
class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource" />
</property>
</bean>
2) adding some boiler plate code in the setUp() method of each TestCase class that is meant to use inside testXxx() methods lazy associations:
Code:
protected void setUp() throws Exception {
super.setUp();
SessionFactory sessionFactory = (SessionFactory) this.ac.getBean("sessionFactory");
session = SessionFactoryUtils.getSession(sessionFactory, true);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
// continue initializing stuff and persist them with the PersistenceManager
// ...
}
3) adding some other boiler plate code to force flushing the commit of the operations before a lazy association is meant to be resolved:
Code:
public void testLazyAssociationDoNotThrowException() {
SessionFactory sessionFactory = (SessionFactory) this.ac.getBean("sessionFactory");
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
// SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory);
Set<TextAnnotation> set = null;
try {
TextDocument textDocumentFromDb = this.persistenceManager.findAll(TextDocument.class).get(0);
// the Set is declared as Lazy
set = textDocumentFromDb.getAnnotations();
}catch(LazyInitializationException e) {
fail(e.getClass() + " should not have been thrown!");
assertEquals("Assert numbers of associations", 1, set.size());
}
Ok, now I wonder if (as in point (3) ) the session has to be explicitly flushed, and the resource unbinded, before I can access the Lazy set (if I don't do that and put the TransactionSynchronizationManager.unbindResource(s essionFactory); only in the tearDown method, then the last assertion on the number of elements in the Set fails: it says that the set is made by 0 elements, wrong!)
Hope I have explained my scenario and I look for some suggestions.