我正在使用 OpenJPA 来持久化对象。我最初使用的是 OpenJPA 1.2,但后来升级到了 OpenJPA 2.1。对象保存在服务器的内存中,它们被序列化到客户端,并且可以作为未管理的对象被接收回来。推土机用于移除 JPA 的东西,并且一直都有。它以前没有引起任何问题。我依赖于 JPA 在保存推土机映射的 JPA 对象时能够识别 @Id。
所以基本上我有一个大型的嵌套对象图,其中一些带有双向(循环)引用。此结构具有已更改的数据和未由客户端更改的数据。它被发送给客户端,它可能之前也可能没有被持久化。只有当它至少被发送回服务器一次时,它才会被持久化。我有一个对象引用 OneToOne 关系中的另一个对象:
class A {
@Column("b_id")
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
int id;
@OneToOne
@JoinColumn(name="b_id")
B something
@OneToOne
Graph owner;
}
class B {
@Column("b_id")
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
int id;
}
class Graph {
@Column("graph_id")
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
int id;
@OneToOne
@Column
A item;
}
问题是,当我收到返回的对象*时,它是存储在服务器上的另一个实例,并且不受管理。如果我添加 cascade = CascadeStrategy.ALL 我会得到重复的插入,因为它将对象再次添加到数据库中。如果我不使用它,我会收到 JPA 尝试持久化非托管对象的异常,请添加注释。总之:
Graph 还没有持久化,A 或 B 也没有。一旦 Graph 被发送到服务器,它们都被持久化了。一个新的图被持久化,它具有不同的 A 但相同的 B。它没有意识到 B 已经被持久化并重新创建它,即使它具有相同的@Id。
我有一种感觉,JPA 认为对象与内存中的对象不同。
我确信 OpenJPA 1.2 似乎基于 @Id 注释将对象识别为等效的。我尝试手动修复引用,并尝试将引用从非托管对象更改为加载到服务器内存中的托管对象。不幸的是,这在我重新启动服务器之前有效,并且它不会修复之前所做的引用。我知道这不是正确的解决方案。
我该如何解决这个问题?
- 我正在使用 GWT 的序列化,效果很好。GWT 会导致这种情况吗?我认为这是一个 JPA 问题。