我正在使用Spring 3.2.11.RELEASE,JPA 2.1,Hibernate 4.3.6.Final和MySQL 5.5.37。我在JUnit测试中得到以下错误
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)
但是,我不知道这条错误消息应该归咎于哪一行。在我的方法中我有
@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.");
并且两个System.out行都打印数字。在方法中没有其他对这个延迟加载的集合的引用,所以我不知道还有什么可以检查我的数据。任何建议都表示赞赏。
答案 0 :(得分:1)
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