【问题标题】:Getting LazyInitializationException despite being in @Transactional and having no detached entities尽管处于 @Transactional 并且没有分离实体,但仍获得 LazyInitializationException
【发布时间】:2015-10-02 06:02:04
【问题描述】:

我正在使用 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 行都打印数字。该方法中没有对这个延迟加载的集合的其他引用,所以我不知道还有什么要检查我的数据。任何建议表示赞赏。

【问题讨论】:

  • 尝试使用@Transactional 注解:)
  • 是你的testSendValidAssignment@Transactional吗?然后检查您的 m_lessonPlanDao 类使用 getCurrentSession 即它本身不管理事务
  • 我编辑了我的问题以声明 @Service 注释,其中我有 Transactional 注释。据我了解,声明类 Transactional 会使每个方法都成为 Transactional。

标签: spring hibernate lazy-loading transactional lazy-initialization


【解决方案1】:

您的服务方法是事务性的,但您的整个测试方法不是。元素的大小检查是在 JUnit 测试的断言语句中执行的,并且是在服务的事务范围之外完成的,因此会导致延迟初始化异常。你可以选择三种方式

  • 你可以尝试在你的dao方法中调用size()方法来制作 size() 方法的外部调用安全。
  • 您可以强制使用您的方法的用户 打开事务(记录哪些对象被分离并使其成为 合约/或使用臭名昭著的open session in view 模式)
  • 您可以创建一个 DTO 层并将大小作为 DTO 的一部分返回

这三种解决方案各有利弊:

对于代码的支持者来说,第一个解决方案看起来很奇怪,因为他们会发现您调用 getter 没有明显的原因 - 它需要注释。

第二个让界面用户的生活更加艰难

第三种违反 DRY 原则

附言当然你也可以禁用延迟初始化

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 2012-09-03
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多