JPA循环参考。 “对象引用未保存的瞬态实例”

时间:2013-02-17 14:13:28

标签: hibernate java-ee jpa orm many-to-one

我正在使用JPA / Hibernate。

假设我有文件夹和文件。 每个文件夹可以包含更多文件夹和文件。 每个文件都知道它的根文件夹是什么(不是父文件夹)。

@Entity
public class Folder{
    ...

    @OneToMany
    @JoinColumn("folder_id")
    private List<Folder> folders;

    @OneToMany
    @JoinColumn("file_id")
    private List<File> files;

    ...
}

@Entity
public class File {
    ...

    @ManyToOne
    private Folder rootFolder;

    ...
}

我创建了一个新文件和一个新文件夹。我把文件放在文件夹中。 现在文件位于文件夹“files”-collection中,文件夹在文件“rootFolder”中被引用 - 变量。

如果我坚持这一点,我会得到“对象引用未保存的瞬态实例”或“在刷新之前保存瞬态实例:entities.file.rootFolder - &gt; entities.Category”(取决于首先保留的内容)。 / p>

有一种方法可以对此进行注释,所以无论我先保存什么都行不通! 我可以通过某种方式以编程方式解决它以插入第一个实体而不引用另一个,然后插入另一个然后放入引用,但我不认为这应该是必要的。

我搜索了这个,但我能找到的只有@OneToMany和@ManyToOne相结合,但在我的情况下我无法使用它。文件夹不应该知道它是否是根文件夹。

我很感激您对教程的任何想法或指示。

2 个答案:

答案 0 :(得分:5)

这些映射或您描述的场景没有问题,假设它们都发生在一个事务中,或者更准确地说,两者之间没有刷新。您描述的错误在刷新时发生,这通常发生在事务提交时。它甚至会在错误中告诉您“在冲洗之前保存瞬态实例”。不允许的是刷新部分保存的对象图。只要图表中的所有对象都在冲洗发生之前保存,你就可以了。

我已根据您的代码在Github上创建了一个工作示例。您可以browse the code和/或克隆项目并使用以下命令运行:

git clone git://github.com/zzantozz/testbed.git tmp
cd tmp/stackoverflow/14921963-hibernate-circular-reference
mvn -q compile exec:java -D exec.mainClass=com.foo.Main

答案 1 :(得分:0)

如果您在同一事务中保留两个对象,那么您的代码应该可以正常工作。

但是,在文件和文件夹之间的关系中,您错误地标记了所有者。多对一方应almost always be the owner of the relationship。因此,正确的方法是:

@Entity
public class File {
  @ManyToOne
  @JoinColumn(name = "folder_id") // this table has a foreign key
  private Folder rootFolder;
}

@Entity
public class Folder {
  @OneToMany(mappedBy = "rootFolder") // 'File' is the owner of this relationship
  private List<File> files;
}

同样,在Folder中,它应该只是:

@OneToMany 
private List<Folder> folders;

或者,你可以选择双向关系:

@Entity
public class Folder {
  @ManyToOne
  private Folder parent;

  @OneToMany(mappedBy = "parent")
  private List<Folder> folders;

我希望这会有所帮助。