【问题标题】:JPA OneToOne bidirectional .JPA OneToOne 双向。
【发布时间】:2013-02-07 07:59:29
【问题描述】:

我有两个实体类在 @OneToOne 关系中。示例代码如下:

public class A {
@Id
private int id;
private String name;
@JoinColumn(name = "B_ID", referencedColumnName = "id")
@OneToOne(cascade=CascadeType.ALL)
private B b;

//setters and getters

}

public class B {
@Id
private int id;
private String name;
@OneToOne(mappedBy="b")
    private A a;
//setter and getters

}

我的问题是“我可以在 B 类中使用 setA(A a) 方法吗?我的意思是这样......

em.getTransaction().begin();
A aa = new A();
aa.setId(1);
aa.setName("JJ");
em.persist(aa);

B bb = new B();
bb.setId(1);
bb.setName("CC");
bb.setA(aa);
em.persist(bb);
em.getTransaction().commit();

当我这样尝试时,表 A (B_ID) 中的 foreign_key 字段被保存为 null。
请帮帮我。

【问题讨论】:

    标签: java jpa jpa-2.0


    【解决方案1】:

    在这里,您在private A a; 上方的B 类中指定了mappedBy。在双向关系中,mappedBy 表示我不是所有者。所以这意味着A是关系的所有者。

    在 A 表中,您将拥有 B 表的外键。由于 A 是所有者,因此假设 A 将操作级联到 B。理想情况下,您应该尝试 a.setB() 然后持久化 a。

    试试下面:

    em.getTransaction().begin();
    //first create B.
    B bb = new B();
    bb.setId(1);
    bb.setName("CC");
    em.persist(bb);
    
    //create A with B set in it.
    A aa = new A();
    aa.setId(1);
    aa.setName("JJ");
    aa.setB(bb);
    em.persist(aa);
    em.getTransaction().commit();
    

    或者

    em.getTransaction().begin();
    //first create B.
    B bb = new B();
    bb.setId(1);
    bb.setName("CC");
    // no need to persist bb.
    
    //create A with B set in it.
    A aa = new A();
    aa.setId(1);
    aa.setName("JJ");
    aa.setB(bb);
    em.persist(aa); // because of cascade all , when you persist A ,
    // B will also be persisted.
    em.getTransaction().commit();
    

    【讨论】:

    • 那么星期五,@OneToOne 关系中的单向和双向之间有什么区别......?谢谢你的回答!
    • 单向意味着您只有一个方向的关系,并且该关系控制着外键。双向有一个单向组件 - 一个控制数据库中外键的关系,以及一个只读的反向指针。标记为 mappedby 的关系实际上是只读的,因为它使用在其他实体上设置的关系,但对该关系的更改不会更改数据库。 JPA 要求您维护双向关系的双方,以保持缓存实体与数据库不同步
    【解决方案2】:

    使用@Cascade({CascadeType.SAVE_UPDATE}) 级联更改

    public class B {
    @Id
    private int id;
    private String name;
    @OneToOne(mappedBy="b")
     @Cascade({CascadeType.SAVE_UPDATE}) 
        private A a;
    //setter and getters
    
    }
    

    【讨论】:

    • @PriyankDoshi 你能详细说明为什么不是吗?
    【解决方案3】:

    需要在em.persist(bb)前加上aa.setB(bb)

    em.getTransaction().begin();
    A aa = new A();
    aa.setId(1);
    aa.setName("JJ");
    em.persist(aa);
    
    B bb = new B();
    bb.setId(1);
    bb.setName("CC");
    
    aa.setB(bb);//this line should be added
    bb.setA(aa);
    
    em.persist(bb);
    em.getTransaction().commit();
    

    【讨论】:

      猜你喜欢
      • 2021-07-14
      • 1970-01-01
      • 1970-01-01
      • 2012-09-28
      • 1970-01-01
      • 2015-04-17
      • 2012-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多