2

我正在使用 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 -> entities.Category”(取决于首先持久化的内容)。

必须有一种方法可以对此进行注释,因此无论我先保存什么,它都会起作用!?我可以以某种方式以编程方式解决它,在不引用另一个实体的情况下插入第一个实体,然后插入另一个实体,然后放入引用,但我认为这里不应该这样做。

我搜索了这个,但我能找到的只是@OneToMany 与@ManyToOne 的结合,但就我而言,我无法使用它。文件夹不应该知道它是否是根文件夹。

我会很感激任何关于教程的想法或方向。

4

2 回答 2

5

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

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

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
于 2013-02-17T15:33:02.780 回答
0

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

但是,在文件和文件夹之间的关系中,您错误地标记了所有者。多对一的一方几乎总是关系的所有者。因此,正确的方法是:

@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;

我希望这有帮助。

于 2013-02-17T15:36:39.287 回答