gpt4 book ai didi

hibernate - 为什么要在 orm 上区分双向关系的一方作为拥有方?

转载 作者:行者123 更新时间:2023-12-02 03:55:45 24 4
gpt4 key购买 nike

在一对多关系中,通常用@ManyToOne 注释的字段是所有者——另一方具有“mappedBy”属性。但是,如果我跳过'mappedBy'并用@JoinColumn(同一列)注释双方,我可以更新双方 - 更改被传播到db。

我没有两个单向关系而不是一个双向关系——只有一个连接列。

如果不选择一方作为关系所有者,我会遇到什么问题?

我的实体看起来类似于以下内容:

@Entity
public class B {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;


@ManyToOne
@JoinColumn(name = "parent_id")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
private B parent;

@OneToMany()
@JoinColumn(name = "parent_id")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
private List<B> children = new ArrayList<B>();
...
}

它似乎对性能没有任何影响(至少插入看起来不错)
这是一个简单的测试和日志输出:
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
B a = new B("a");
B b = new B("b");
B c = new B("c");
B d = new B("d");
B e = new B("e");
session.save(a);
session.save(b);
session.save(c);
session.save(d);
session.save(e);
session.getTransaction().commit();
System.out.println("all objects saved");
session.beginTransaction();
a.getChildren().add(b);
a.getChildren().add(c);
session.save(a);
session.getTransaction().commit();
System.out.println("b and c added as children");
session.beginTransaction();
a.getChildren().add(d);
a.getChildren().add(e);
session.getTransaction().commit();
System.out.println("e and f added as children");
session.close();

Hibernate: insert into B (fieldInB, parent_id) values (?, ?)
Hibernate: insert into B (fieldInB, parent_id) values (?, ?)
Hibernate: insert into B (fieldInB, parent_id) values (?, ?)
Hibernate: insert into B (fieldInB, parent_id) values (?, ?)
Hibernate: insert into B (fieldInB, parent_id) values (?, ?)
all objects saved
Hibernate: update B set parent_id=? where id=?
Hibernate: update B set parent_id=? where id=?
b and c added as children
Hibernate: update B set parent_id=? where id=?
Hibernate: update B set parent_id=? where id=?
e and f added as children

最佳答案

您看不到额外的 SQL 语句,因为您没有正确设置关联的两侧。例如,你说:

a.getChildren().add( b );

并假设 ab现在是关联的。但是当您调用 b.getParent() 时会发生什么?这里?说这段代码“将 b 作为 child 添加到 a”,然后返回这个新的 child b并且来电者想要导航 b.getParent() ?

相反,您应该做的是:
a.getChildren().add( b );
b.setParent( a );

现在您的惯用 Java 代码继续工作( b.getParent() 行为正常)。现在,在这里,您将看到多个 SQL 语句。这就是为什么您需要选择一方作为“所有者”。

此外,虽然完全是铺位,但请考虑:
a.getChildren().add( b );
b.setParent( c );

什么被写入数据库?双方有效地为 b 命名了不同的父级。 .那么我们相信哪个?

关于hibernate - 为什么要在 orm 上区分双向关系的一方作为拥有方?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12729460/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com