Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何解决Spring数据rest@RepositoryEventHandler@HandlefterLinkSave中的LazyInitializationException?_Java_Hibernate_Spring Data Rest_Eventhandler_Lazy Initialization - Fatal编程技术网

Java 如何解决Spring数据rest@RepositoryEventHandler@HandlefterLinkSave中的LazyInitializationException?

Java 如何解决Spring数据rest@RepositoryEventHandler@HandlefterLinkSave中的LazyInitializationException?,java,hibernate,spring-data-rest,eventhandler,lazy-initialization,Java,Hibernate,Spring Data Rest,Eventhandler,Lazy Initialization,我有一个SpringDataREST应用程序,它具有类型匹配和舍入之间的关系 @Entity public class Match { @OneToMany private List<Round> rounds; ... } 我使用EventHandler捕捉到这一点,以便对我的域模型进行一些更新: public class MatchEventHandler @HandleAfterLinkSave public void handle

我有一个SpringDataREST应用程序,它具有类型匹配和舍入之间的关系

@Entity
public class Match {

    @OneToMany
    private List<Round> rounds;
    ...
}
我使用EventHandler捕捉到这一点,以便对我的域模型进行一些更新:

public class MatchEventHandler

    @HandleAfterLinkSave
    public void handleLinkSave(Match match, List<Round> rounds) {
        ...
}
公共类MatchEventHandler
@HandleAfterLinkSave
公共无效handleLinkSave(匹配、列表回合){
...
}
我需要访问第二个参数才能进行更新,但这样做,例如使用rounds.get(0)返回

org.hibernate.LazyInitializationException:延迟初始化集合失败,无法初始化代理-无会话

阅读关于Hibernates LazyInitializationExceptions的其他线程,我主要看到了建议的三种方法:

  • 使用Hibernate.initialize()-我不知道该调用哪个方法,它会给Hibernate框架添加一个丑陋的依赖项
  • 将控制器方法放入事务中——我知道spring数据已经将所有内容放入事务中。此外,由于这是一个SpringDataREST应用程序,我没有使用任何控制器或服务层,因此我不知道将什么放入事务中
  • 在关系上设置FetchType.EAGER-虽然不是一个真正有效的解决方案,但我确实尝试过。在这种情况下,@HandleAfterLinkSave方法的第二个参数是一个空列表,因此它也不会提供预期的结果

  • 属性引用在以下Spring类中处理:

    org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController

    虽然它在大多数情况下工作得很好,但它在这里或那里都有马车。或者让我们这样说:它有一些有趣的行为。。。(在过去两年中,我花了几个月的时间来创建一个新的应用程序)

    如果请求方法是POST或PATCH,则第2个参数包含更新的集合。但是如果使用PUT方法,它将包含原始集合

    (此外,如果您的主实体中有多个属性集合,则无法确定修改了哪个集合。对于映射类型属性,也有一些可疑的结果,但这是另一种情况。)

    因此,如果您在
    RoundRepository
    中创建一个存储库方法,并使用它重新加载集合,那么最好的解决方案是:

    @RestResource(exported = false)
    List<Round> findAllByMatch(Match match);
    
    @RestResource(exported=false)
    列出findAllByMatch(匹配);
    
    顺便说一下!
    关于您的选项2,请阅读

    选项1和3是过度杀伤力。选项2不正确-spring数据不会自动放置任何事务,因此您应该明确地将
    @Transactional
    放在controller(或更好的服务)方法上,并将
    @EnableTransactionManagement
    放在spring配置类上感谢您的评论Nikolay。这是一个SpringDataREST应用程序,因此我没有控制器或服务类,只有域模型、存储库接口和
    @RepositoryEventHandler
    类。那么我应该把
    @Transactional
    注释放在哪里呢?我试着将它放在handleLinkSave方法上,但没有解决问题。非常感谢您澄清这一点。不幸的是,关于LinkEvents处理的文档很差,或者至少我找不到任何东西。所以我现在使用POST或PATCH,这对于我的用例来说已经足够了,因为在这个实体中没有更多的集合属性或映射类型。我仍然不明白为什么使用PUT会导致LazyInitializationException,但我同意这个解决方案。在PUT请求期间,参数包含原始的-未修改的-集合。它是使用LAZYloading加载的,没有修改(SDR创建了一个全新的集合,将所有属性元素放入其中并覆盖原始集合),因此代理对象从未解析。调用事件处理程序时,它发生在事务之外,因此无法在那里自动解析。
    @RestResource(exported = false)
    List<Round> findAllByMatch(Match match);