如何解决 Spring 数据 rest @RepositoryEventHandler @HandleAfterLinkSave 中的 LazyInitializationException?
How to resolve LazyInitializationException in Spring data rest @RepositoryEventHandler @HandleAfterLinkSave?
我有一个 spring 数据剩余应用程序,其类型为 Match 和 Round
@Entity
public class Match {
@OneToMany
private List<Round> rounds;
...
}
当在比赛和回合之间创建 link 时,例如像这样
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), returns
org.hibernate.LazyInitializationException: 延迟初始化集合失败,无法初始化代理 - 无会话
阅读有关 Hibernates LazyInitializationExceptions 的其他线程,我主要看到建议的三种方法:
- 使用 Hibernate.initialize() - 我看不出我可以调用哪个方法,它会增加对 Hibernate 框架的丑陋依赖性
- 将控制器方法放入事务中 - 我知道 spring 数据已经将所有内容放入事务中。此外,由于这是一个 spring 数据存储应用程序,我没有使用任何控制器或服务层,因此我不知道要将什么放入事务中。
- 在关系上设置 FetchType.EAGER - 虽然不是真正有效的解决方案,但我确实尝试过。在这种情况下,@HandleAfterLinkSave 方法的第二个参数是一个空列表,因此它也不会提供预期的结果。
属性 引用在下面处理 Spring class:
org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController
虽然它在大多数情况下工作得很好,但还是有很多问题。或者这样说:它有一些有趣的行为......(在过去的两年里,我花了几个月的时间来创建一个 improved version of Spring Data Rest)。
如果请求方法是 POST 或 PATCH,则第二个参数包含更新后的集合。但如果您使用 PUT 方法,它包含 原始 集合。
(此外,如果您的主实体中有多个 property-collections,则无法确定修改了哪个集合。并且 map-type 的结果有问题属性,但那是另一回事了。)
恕我直言,最好的解决方案是在 RoundRepository
中创建存储库方法,并使用它重新加载集合:
@RestResource(exported = false)
List<Round> findAllByMatch(Match match);
顺便说一句!
关于您的选项 2,请阅读 !
我有一个 spring 数据剩余应用程序,其类型为 Match 和 Round
@Entity
public class Match {
@OneToMany
private List<Round> rounds;
...
}
当在比赛和回合之间创建 link 时,例如像这样
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), returns
org.hibernate.LazyInitializationException: 延迟初始化集合失败,无法初始化代理 - 无会话
阅读有关 Hibernates LazyInitializationExceptions 的其他线程,我主要看到建议的三种方法:
- 使用 Hibernate.initialize() - 我看不出我可以调用哪个方法,它会增加对 Hibernate 框架的丑陋依赖性
- 将控制器方法放入事务中 - 我知道 spring 数据已经将所有内容放入事务中。此外,由于这是一个 spring 数据存储应用程序,我没有使用任何控制器或服务层,因此我不知道要将什么放入事务中。
- 在关系上设置 FetchType.EAGER - 虽然不是真正有效的解决方案,但我确实尝试过。在这种情况下,@HandleAfterLinkSave 方法的第二个参数是一个空列表,因此它也不会提供预期的结果。
属性 引用在下面处理 Spring class:
org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController
虽然它在大多数情况下工作得很好,但还是有很多问题。或者这样说:它有一些有趣的行为......(在过去的两年里,我花了几个月的时间来创建一个 improved version of Spring Data Rest)。
如果请求方法是 POST 或 PATCH,则第二个参数包含更新后的集合。但如果您使用 PUT 方法,它包含 原始 集合。
(此外,如果您的主实体中有多个 property-collections,则无法确定修改了哪个集合。并且 map-type 的结果有问题属性,但那是另一回事了。)
恕我直言,最好的解决方案是在 RoundRepository
中创建存储库方法,并使用它重新加载集合:
@RestResource(exported = false)
List<Round> findAllByMatch(Match match);
顺便说一句!
关于您的选项 2,请阅读