【发布时间】:2019-09-30 19:40:45
【问题描述】:
我有一个 Spring Data Rest 应用程序,其中包含 Match 和 Round 类型之间的关系
@Entity
public class Match {
@OneToMany
private List<Round> rounds;
...
}
在比赛和回合之间创建链接时,例如像这样
curl -X PUT -d "http://localhost:8080/rounds/2" -H "Content-Type:text/uri-list" http://localhost:8080/matches/1/rounds;
我使用 EventHandler 捕获此内容,以便对我的域模型进行一些更新:
public class MatchEventHandler
@HandleAfterLinkSave
public void handleLinkSave(Match match, List<Round> rounds) {
...
}
我需要访问第二个参数才能进行更新,但这样做,例如使用 rounds.get(0),返回
org.hibernate.LazyInitializationException: 延迟初始化集合失败,无法初始化代理 - 没有会话
阅读有关 Hibernates LazyInitializationExceptions 的其他线程,我主要看到了三种建议的方法:
- 使用 Hibernate.initialize() - 我看不出我可以调用哪个方法,它会给 Hibernate 框架添加一个丑陋的依赖关系
- 将控制器方法放入事务中 - 我知道 Spring Data 已经将所有内容放入事务中。此外,由于这是一个 spring 数据休息应用程序,我没有使用任何控制器或服务层,因此我不知道究竟要在事务中放入什么。
- 在关系上设置 FetchType.EAGER - 虽然不是一个真正有效的解决方案,但我确实尝试过。在这种情况下,@HandleAfterLinkSave 方法的第二个参数是一个空列表,因此它也不会提供预期的结果。
【问题讨论】:
-
选项 1 和 3 是多余的。选项 2 不正确 - spring 数据不会自动放置任何事务,因此您应该将
@Transactional明确放置在控制器(或更好的服务)方法上,并将@EnableTransactionManagement放置在您的 spring 配置类中 -
感谢您对 Nikolay 的评论。这是一个 Spring Data Rest 应用程序,所以我没有控制器或服务类,只有域模型、存储库接口和
@RepositoryEventHandler类。那么我应该在哪里放置@Transactional注释?我试过把它放在 handleLinkSave 方法上,但没有解决问题。
标签: java hibernate spring-data-rest eventhandler lazy-initialization