spring-data-jpa :找到对集合 org.hibernate.HibernateException 的共享引用

Posted

技术标签:

【中文标题】spring-data-jpa :找到对集合 org.hibernate.HibernateException 的共享引用【英文标题】:spring-data-jpa : Found shared references to a collection org.hibernate.HibernateException 【发布时间】:2020-07-19 11:38:14 【问题描述】:

我知道这个问题被问过很多次,也有解决方法

喜欢 Found shared references to a collection org.hibernate.HibernateException http://www.java2s.com/Questions_And_Answers/JPA/Collection/HibernateException.htm

但以上都不适合我。

我正在使用SpringBoot, JPA, Hibernate 并具有如下提供的映射。

我正在检索电话列表并使用 for 循环对其进行迭代。 我在遍历电话列表时收到错误 Found shared references to a collection: Phone.person

org.hibernate.HibernateException: Found shared references to a collection: Phone.person
    at org.hibernate.engine.internal.Collections.processReachableCollection(Collections.java:188) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.FlushVisitor.processCollection(FlushVisitor.java:50) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:104) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:65) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:59) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:182) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:232) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:92) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]

映射到Phone 实体

@Entity
@Table(name = "PHONETABLE")
@Data
public class Phone

// other column mapping

    @ManyToMany
    @JoinTable(name = "SomeTable", joinColumns = 
            @JoinColumn(name = "column1", referencedColumnName = "personColumn") , inverseJoinColumns = 
                    @JoinColumn(name = "id", referencedColumnName = "id", unique = true) )
    @JsonIgnore
    private Set<Person> person;


我正在调用findByIdMethod 从存储库中获取数据。 我使用了lombok,因为 getter 是 setter。

如果有人知道解决方案,那就太好了。 谢谢;

【问题讨论】:

你能显示你提到的循环,错误发生在哪里吗? 【参考方案1】:

您似乎有多个Phone 实例与person 的相同Set 实例。当您克隆或复制Phone 或执行phone1.setPerson(phone2.getPerson()) 之类的操作时,可能会发生这种情况。

Persons 可以相同,但Set 本身不同。每部手机都应创建一个仅在实体内使用的 Set 的新实例。

您可以通过在构造函数中实例化集合或在声明之后直接实例化集合,然后从不调用集合的 setter 来确保这一点,例如

private Set<Person> person = new HashSet<Person>();

void addPerson(Person person) 
    this.person.add(person);

并且只使用addPerson,从不使用setPerson(你可以添加类似的辅助方法来添加多个人,或者删除一个人等)。

您还可以在 getPerson getter 中返回集合的副本而不是集合本身,以确保集合实例永远不会泄漏。

【讨论】:

嗨,Dario Seidl,感谢您抽出宝贵时间使用 @Data from lombok 不确定在这种情况下我们如何跳过设置器。我已经尝试过您的解决方案,但没有按预期工作 我正在调用 findByIdMethod 从存储库中获取数据。我使用 lombok 作为 getter 是 setter。 好的,拥有由 Lombok 生成的 setter 和 getter 本身不是问题。您只需要确保您没有将一个实体的集合设置为另一个实体。如果需要,您仍然可以在使用 @Data 时修改 setter 的可见性:projectlombok.org/features/Data

以上是关于spring-data-jpa :找到对集合 org.hibernate.HibernateException 的共享引用的主要内容,如果未能解决你的问题,请参考以下文章

学习Spring-Data-Jpa---可嵌入对象和元素集合的使用

spring-data-jpa动态条件查询

spring-data-jpa一对多多对一多对多关联

学习Spring-Data-Jpa(二十)---@EnableJpaRepositories

Spring-data-Jpa项目搭建

spring-data-jpa操作数据库