Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当反向引用只是一个id属性而不是完全引用时,如何执行OneToMany Hibernate映射_Java_Hibernate_Jpa_Annotations_Mapping - Fatal编程技术网

Java 当反向引用只是一个id属性而不是完全引用时,如何执行OneToMany Hibernate映射

Java 当反向引用只是一个id属性而不是完全引用时,如何执行OneToMany Hibernate映射,java,hibernate,jpa,annotations,mapping,Java,Hibernate,Jpa,Annotations,Mapping,让我更具体一点,在标题中很难描述这一点 我有一个名为Bucket的类,它有一个到一系列标签的映射。Bucket类有一个id属性。类标签没有对Bucket的引用,而是有一个bucketId字段,其中包含所属Bucket的id。这对于避免循环引用(Bucket-to-Label和back-Label-to-Bucket)是必要的,以便将Bucket对象转换为JSON符号 我的Bucket类如下所示: @Entity(name="Bucket") @Table(name = "BUCKETS") pu

让我更具体一点,在标题中很难描述这一点

我有一个名为Bucket的类,它有一个到一系列标签的映射。Bucket类有一个id属性。类标签没有对Bucket的引用,而是有一个bucketId字段,其中包含所属Bucket的id。这对于避免循环引用(Bucket-to-Label和back-Label-to-Bucket)是必要的,以便将Bucket对象转换为JSON符号

我的Bucket类如下所示:

@Entity(name="Bucket")
@Table(name = "BUCKETS")
public class Bucket implements Serializable {

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "BUCKET_ID")
    protected long id;

    /*
     * Map of labels indexed by the label name. I'm not sure this mapping is correct!
     */
    @ElementCollection
    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @MapKeyColumn(name="LABEL_NAME")
    private Map<String, Label> labels = new HashMap<String, Label>();

    ...

}
@Entity(name="Label")
@Table(name = "LABELS")
public class Label implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "LABEL_ID")
    protected long id;

    /*
     * How do I map this? It should point to the id of the Bucket instance that has
     * this label in its "labels" map
     */
    protected long bucketId;


    @Column(name = "LABEL_NAME", length=250, nullable=false)
    private String name;

    ...

}
如果我可以在标签中有一个Bucket引用,我会将其映射为@OneToMany,然后在Bucket类中映射为@ManyToOne(mappedBy=“Bucket”),但我没有该引用,只有指向后面的id

有人知道我该如何映射它吗?

谢谢大家!! 爱德华多


但是,请确保不能将Labels类中的bucketId字段设置为错误的值。例如,您可以降低bucketId字段的setter的可见性。

由于某些原因,我无法在George的回答下面进行评论,因此我在这里回答您的第二个问题:

为了在创建Bucket之后在标签中设置bucketId,您需要注册一个EventListener来执行您想要执行的操作,例如(这不一定是工作代码)


Google Hibernate EventListeners有关配置等的详细信息,有许多不同的类型,尽管PostInsertListener应该适合这种情况。

更好的解决方案是找到一个JSON库,让您能够优雅地处理循环路径,而不是破坏hibernate映射;你在为自己设置讨厌的虫子。我不确定你说的是什么循环引用;在我看来,您正在进行标准的一对多映射。循环引用是Bucket-to-Label和Label-to-Bucket。如果不从序列化中排除反向(标签到桶)引用,就无法将其转换为JSON,我必须这样做。我将继续研究Jackson,它可以重建反序列化的双向引用,但出于好奇,我仍然想知道谁来完成这个映射。它可能在将来对我或其他人有用。如果你做标准的一对多映射,你不会得到任何圆。标签中没有对Bucket的引用,Bucket中也没有对Label的引用。标准的一对多映射是通过联接表实现的。正如@Ryan Stewart所提到的,您可能想弄清楚JSON通常是如何处理这一点的(也许您也可以将联接表作为JSON传递?)。将Label类更改为仅保存bucketId而不是bucket是对此类问题的常见反应,但这从来都不是正确的反应。事实上,知道怎么做并不值得,因为这只会把你挖到更深的坑里。了解有关封送处理库以及如何处理此类关系的更多信息。例如,在JSON输出中使用JAXB及其背后的Jackson,只需将关系的一侧注释为@XmlTransient,问题就消失了。我刚刚意识到,Bucket id只有在持久化之后才会被分配。我不能在添加标签时将其设置为labels,因为这发生在Buckets类被持久化之前(当时还没有分配id)。太棒了,应该这样做了!就像我说的,我使用Jackson图书馆是为了避免循环引用,但出于好奇,我想知道如何做到这一点。这就是答案!非常感谢。
@ElementCollection
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@MapKeyColumn(name="LABEL_NAME")
private Map<String, Label> labels = new HashMap<String, Label>();
public void addLabel(Label label) {
    labels.put(label.getName(), label);
    label.setBucketId(this.getId());
}
    public class LabelPostInsertListener implements PostInsertListener {

        public void onPostInsert(PostInsertEvent event)
                throws HibernateException {
            Bucket bucket = (Bucket)event.getEntity();
            for (Label l : bucket.getLabels().values()) {
                l.setBucketId(bucket.getId());
            }

        }
    }