HibernateException:由 jpa 本身调用的共享引用(?)
HibernateException: Shared references invoked by jpa itself (?)
我目前在将对象写入数据库时遇到一些问题。我的问题确实出现在一个非常复杂的数据模型中,但我会尝试将其分解为一个易于理解的示例。
假设有 class A:
@Entity(name = "a")
@Table(schema = "foo")
public class A {
private static final long serialVersionUID = -5305374150112492804L;
logger = LoggerFactory.getLogger(A.class);
@Id
@Column(name = "tid", nullable = false, unique = true)
@SequenceGenerator(name = "globalSequenceGen", schema = "foo", sequenceName = "foo_sequence")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "globalSequenceGen")
private Integer TID;
@Column(name = "b")
private String bId;
@OneToMany(targetEntity = B.class)
@JoinColumn(name = "random_b_attribute", referencedColumnName = "b", updatable = false, insertable = false)
private List<B> b;
@PrePersist
@PreUpdate
public void prePersist() {
bId = b == null || b.isEmpty() ? null : b.get(0).getRandomAttribute();
}
...
}
引用的 class B 非常简单:它只包含 @Column
注释属性。请注意,A 的实例可以并且将在其属性 b
中引用 Bs 的相同 "Set" .
有第三个 class D 引用 A:
@Entity(name = "d")
@Table(schema = "foo")
public class D {
private static final long serialVersionUID = -5305374150112492804L;
logger = LoggerFactory.getLogger(D.class);
@Id
@Column(name = "tid", nullable = false, unique = true)
@SequenceGenerator(name = "globalSequenceGen", schema = "foo", sequenceName = "foo_sequence")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "globalSequenceGen")
private Integer TID;
@Column(name = "a")
private Integer aId;
@ManyToOne(targetEntity = A.class)
@JoinColumn(name = "a", referencedColumnName = "tid", updatable = false, insertable = false)
private A a;
@PrePersist
@PreUpdate
public void prePersist() {
aId = a == null ? null : a.getTID();
}
...
}
问题来了:
- 我确实从数据库中检索了 D 的对象(懒惰)。 None 其中确实引用了 A 的任何对象(例如,数据库中的列 a 是空的)。
- 我使用相同的
EntityManager
从数据库中检索 A 的所有对象,因为我稍后想将它们插入 D 实例(也是懒惰的)。
- 我不触摸任何
D#a
或A#b
属性。
- 尝试
EntityManager#persist
任何新创建的 D 实例最终会出现以下异常:
Caused by: org.hibernate.HibernateException: Found shared references to a collection: random.package.structure.A.b
在我的研究中,我发现错误可能是在提供相同的 Collection
时引起的(不要与具有相同条目的 Collection
混淆)。显然,这源于 jpa 本身对 A 实例的初始化?!似乎,回收相同的对象是个好主意 Collection
,但在更新未更改的对象时显然会导致问题...
在持久化对象之前清除 EntityManager
似乎可以解决问题。但是,由于所有内容都是延迟读取的,之后使用这些对象会导致其他问题。
关于如何为 A 的每个实例创建新的 Collection
或以其他方式防止失败,您有任何提示吗?
非常感谢,如果我遗漏了任何信息,请尽管询问!
非常感谢您的回答! @crizzis 的提示起到了作用。
当然是@ManyToMany
关系。我更改了我的数据模型(以使用映射表)并解决了我的问题!
我目前在将对象写入数据库时遇到一些问题。我的问题确实出现在一个非常复杂的数据模型中,但我会尝试将其分解为一个易于理解的示例。
假设有 class A:
@Entity(name = "a")
@Table(schema = "foo")
public class A {
private static final long serialVersionUID = -5305374150112492804L;
logger = LoggerFactory.getLogger(A.class);
@Id
@Column(name = "tid", nullable = false, unique = true)
@SequenceGenerator(name = "globalSequenceGen", schema = "foo", sequenceName = "foo_sequence")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "globalSequenceGen")
private Integer TID;
@Column(name = "b")
private String bId;
@OneToMany(targetEntity = B.class)
@JoinColumn(name = "random_b_attribute", referencedColumnName = "b", updatable = false, insertable = false)
private List<B> b;
@PrePersist
@PreUpdate
public void prePersist() {
bId = b == null || b.isEmpty() ? null : b.get(0).getRandomAttribute();
}
...
}
引用的 class B 非常简单:它只包含 @Column
注释属性。请注意,A 的实例可以并且将在其属性 b
中引用 Bs 的相同 "Set" .
有第三个 class D 引用 A:
@Entity(name = "d")
@Table(schema = "foo")
public class D {
private static final long serialVersionUID = -5305374150112492804L;
logger = LoggerFactory.getLogger(D.class);
@Id
@Column(name = "tid", nullable = false, unique = true)
@SequenceGenerator(name = "globalSequenceGen", schema = "foo", sequenceName = "foo_sequence")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "globalSequenceGen")
private Integer TID;
@Column(name = "a")
private Integer aId;
@ManyToOne(targetEntity = A.class)
@JoinColumn(name = "a", referencedColumnName = "tid", updatable = false, insertable = false)
private A a;
@PrePersist
@PreUpdate
public void prePersist() {
aId = a == null ? null : a.getTID();
}
...
}
问题来了:
- 我确实从数据库中检索了 D 的对象(懒惰)。 None 其中确实引用了 A 的任何对象(例如,数据库中的列 a 是空的)。
- 我使用相同的
EntityManager
从数据库中检索 A 的所有对象,因为我稍后想将它们插入 D 实例(也是懒惰的)。 - 我不触摸任何
D#a
或A#b
属性。 - 尝试
EntityManager#persist
任何新创建的 D 实例最终会出现以下异常:
Caused by: org.hibernate.HibernateException: Found shared references to a collection: random.package.structure.A.b
在我的研究中,我发现错误可能是在提供相同的 Collection
时引起的(不要与具有相同条目的 Collection
混淆)。显然,这源于 jpa 本身对 A 实例的初始化?!似乎,回收相同的对象是个好主意 Collection
,但在更新未更改的对象时显然会导致问题...
在持久化对象之前清除 EntityManager
似乎可以解决问题。但是,由于所有内容都是延迟读取的,之后使用这些对象会导致其他问题。
关于如何为 A 的每个实例创建新的 Collection
或以其他方式防止失败,您有任何提示吗?
非常感谢,如果我遗漏了任何信息,请尽管询问!
非常感谢您的回答! @crizzis 的提示起到了作用。
当然是@ManyToMany
关系。我更改了我的数据模型(以使用映射表)并解决了我的问题!