JPA:了解OneToOne双向关系

时间:2015-07-26 22:18:16

标签: java jpa

我试图理解从反面使用这种关系的可能方式。

我的实体:

@Entity
public class Person {
    @Id @GeneratedValue
    private Long id;
    private String name;

    @OneToOne
    private Dossier dossier;

    //----------------------------------------
    // getters/setters/constructors
}

@Entity
public class Dossier {
    @Id @GeneratedValue
    private Long id;
    private String dossierInfo;

    @OneToOne(mappedBy = "dossier", fetch = FetchType.EAGER)
    private Person person;

    //----------------------------------------
    // getters/setters/constructors
}

主要方法片段:

tx.begin();
{
    // persist
    Dossier d = new Dossier("some info");
    d.setId(1000l);
    em.persist(d);
    em.persist(new Person("Peter", d));

    // find
    Dossier dossier = em.find(Dossier.class, 1000l);
    System.err.println(dossier.getDossierInfo());
    System.err.println(dossier.getPerson().getName());   // <<  NullPointer exception
}
tx.commit();

那么,我们如何从Dossier获取Person对象呢? 或者我应该如何更改我的实体呢?

3 个答案:

答案 0 :(得分:3)

对象 d 没有Person的引用,因此,如果查看表, person 列将设置为null。在双向一对一关系映射中,两个实体,所有者和反面都应该具有另一个实体的引用。所以,你的代码应该是:

Dossier dossier = new Dossier("some info");
dossier.setId(1000L);
Person person = new Person("Peter", dossier);
dossier.setPerson(person);
em.persist(person);
em.persist(dossier);

答案 1 :(得分:0)

您是否在数据库中正确插入了数据?如果你放了 cascade =在人员映射上的Cascade.ALL你不需要坚持第一个Dossier。尝试添加它并告诉我它是否不起作用。

答案 2 :(得分:0)

似乎我发现了我的错误。在事务部分中,在持久化实体之前,我们需要正确设置所有链接(我忘了在档案对象中设置人员链接)。 所以这是有效的代码:

tx.begin();
{
    // persist
    Dossier d = new Dossier("some info");
    d.setId(1000l);

    Person p = new Person("Peter", d);   // set link to dossier

    d.setPerson(p);                      // set link to person

    em.persist(d);
    em.persist(p);

    // find
    Dossier dossier = em.find(Dossier.class, 1000l);
    System.err.println(dossier.getDossierInfo());
    System.err.println(dossier.getPerson().getName());
}
tx.commit();