Java 如何解决Spring数据rest@RepositoryEventHandler@HandlefterLinkSave中的LazyInitializationException?
我有一个SpringDataREST应用程序,它具有类型匹配和舍入之间的关系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
@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的其他线程,我主要看到了建议的三种方法:
属性引用在以下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);