1

我正在使用 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 问题。
4

1 回答 1

0

考虑到在将对象返回到服务器后应该发生一些引用逻辑,是时候使用 DTO 了。

您可以创建 Graph_Model、A_Model 和 B_Model 类(这些是数据传输对象),并在与客户端 GWT 代码对话时使用它们。当 aGraph_Model来到服务器时,您可以Graph从 Graph_Model 创建一个托管对象,并通过查询设置正确的引用。

同样奇怪的是,类 A 和 Graph 根本没有 ID 属性,因此每当您保存 Graph 类型的对象时都会创建它们。我没有足够的信息来建议其他任何事情,不知道您要做什么,目标是什么。

于 2011-05-10T11:43:48.523 回答