I'm new to Spring and having a difficult time figuring out @Transactional. My basic setup:
JPA, Java Configuration, CTW, AnnotationTransactionAspect.aspectOf(), spring-configured, Hibernate, component scan on everything for now.
Test runs with SpringJUnit4ClassRunner. Each Test class is annotated with:
I have a parent entity and a child entity. There is a ONETOMANY relationship between them. Though I don't think this is relevant.Code:@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD )
My test methods are NOT annotated with @Transactional. I want to make sure that my service layer is using flush, et al correctly so I need committed transactions between operations within the test method.
My @Transactional usage is in my service layer. Furthermore, the service layer is injected into a fluent interface that the test uses. This allows me to do things like this:
Here's a brief version of ParentOperations:Code:ParentOperations.id( parent.getId() ).getChildrenNames();
There's a bunch more to it but you get the idea. All the methods in ParentService are @Transactional. The #getChildrenOf method simply populates a HashSet using the result of parent.getChildren() which is using a LAZY fetch but should be fine since it is done within a transaction.Code:@Configurable public class ParentOperations { @AutoWired private ParentService service; private Parent parent; public static ParentOperations id( Long id ) { ParentOperations ops = new ParentOperations(); ops.parent = ops.service.findById( id ); return ops; } public Set<Child> getChildren() { return service.getChildrenOf( this.parent ); } }
So here's the rub. In my test method, if I persist the parent first and then do a ParentOperations.id( parent.getId() ).getChildren() I get an exception in ParentService#getChildrenOf when trying to build the Set of children with Spring saying that during the lazy load that there is "no session or session has been closed".
In the logging I can see that Spring "found a thread-bound entity manager" and is "participating in the current transaction." But I can see after the #persist call that the EntityManager has been closed.
As you might imagine if I annotate the WHOLE test method all is well. But if I do that I cannot ensure that stuff is really happening correctly in the database verses just the cache using object references.
How can I have an active transaction here but no session?
Appreciate any pointers.


Reply With Quote
