2013-02-17 59 views
2

我正在使用JPA/Hibernate。JPA循环引用。 “对象引用未保存的瞬态实例”

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

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

    ... 
} 

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

如果我坚持这一点,我得到“对象引用一个未保存的瞬态实例”或“在冲洗之前保存瞬态实例:entities.file.rootFolder - > entities.Category”(取决于先保存的内容)。

有一种方法我可以注释这个,所以它会工作不管我先保存什么!? 我可以以某种方式通过编程方式解决问题,插入第一个实体而不引用其他实体,然后插入另一个实体,然后放入参考中,但我认为这不是必需的。

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

我会很感激任何想法或指导教程。

回答

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 
+0

感谢您的帮助! 另一个问题是,我已经有模块来保存这些对象(我需要使用它们)。有没有办法在他们周围手动包装一个事务? – fancy 2013-02-18 14:35:58

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;

我希望这有助于。

+0

OP已经声明文件的根文件夹不是它的父文件夹。因此,Folder.files未由File映射。根文件夹。 – 2013-02-17 15:39:01

相关问题