I’m using Spring 3.2.11.RELEASE, JPA 2.1, Hibernate 4.3.6.Final, and MySQL 5.5.37. I’m getting the below error in a JUnit test
testSendValidAssignment(org.mainco.subco.thirdParty.service.ThirdPartyServiceIT) Time elapsed: 13.366 sec <<< ERROR!
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.mainco.subco.lessonplan.domain.LessonPlan.classrooms, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:155)
at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:278)
at org.mainco.subco.ThirdParty.service.ThirdPartyServiceIT.testSendValidAssignment(ThirdPartyServiceIT.java:102)
However, I don’t know what line is to blame for this error message. In my method I have
@Service
@Transactional
public class MyServiceImpl implements MyService
{
....
@Override
public void sendAssignment(final String assignmentId)
{
final Assignment assignment = m_lessonPlanDao.getAssignment(assignmentId);
if (processData(assignment))
{
// Gather the students who have been assigned this assignment
final List<Classroom> classes = lessonPlan.getClassrooms();
System.out.println("got " + classes.size() + " classes.");
// Send one request for each class assignment
for (final Classroom classroom : classes)
{
final List<User> classStudents = m_classroomSvc.findClassStudents(classroom.getId());
System.out.println("got " + classStudents.size() + " students.");
and both System.out lines print numbers. There are no other references to this lazily-loaded collection in the method so I don’t know what else to check in my data. Any advice is appreciated.
Your service method is transactional, but your entire test method is not. The size checking of the element is performed in an assertion statement in your JUnit test and is done outside of the transaction scope of the service, so it causes lazy initialization exception. There are three ways you can go
size()
method inside your dao method to make
outside call of the size()
method safe. open session in view
pattern) all three solutions have pros and cons:
the first solution will look weird for the supporters of the code when they'll find that you call a getter for no obvious reson - it needs commenting.
the second makes life harder to the users of the interface
the third violates DRY principle
p.s. you can also disable lazy initialization of course