如何在Spring Data Rest @RepositoryEventHandler @HandleAfterLinkSave中解决LazyInitializationException?

时间:2019-05-13 20:07:46

标签: java hibernate spring-data-rest eventhandler lazy-initialization

我有一个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的其他线程,我主要看到建议的三种方法:

  1. 使用Hibernate.initialize()-我看不到可以在哪个方法上调用它,这会给Hibernate框架增加一个丑陋的依赖关系
  2. 将控制器方法放入事务中-我知道spring数据已经将所有内容放入事务中。另外,由于这是一个Spring Data Rest应用程序,因此我不使用任何控制器或服务层,因此我不知道要在事务中确切输入什么内容。
  3. 在关系上设置FetchType.EAGER-尽管不是真正有效的解决方案,但我确实尝试过。在这种情况下,@ HandleAfterLinkSave方法的第二个参数是一个空列表,因此它也无法提供预期的结果。

1 个答案:

答案 0 :(得分:0)

在下面的Spring类中处理属性引用:

org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController

尽管大多数情况下效果都很好,但这里或那里的越野车还是有问题的。或这样说:它具有一些有趣的行为……(过去两年来我花了几个月的时间来创建improved version of Spring Data Rest)。

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

(此外,如果您在主实体中有多个属性集合,则无法确定要修改哪个集合。而且,对于地图类型属性有那些可疑的结果,但这是另一回事了。 )

因此,最好的解决方案恕我直言,如果您在RoundRepository中创建存储库方法,然后使用它来重新加载集合:

@RestResource(exported = false)
List<Round> findAllByMatch(Match match);

顺便说一句! 关于选项2,请阅读this topic