问题
单向和双向关联有什么区别?
由于在db中生成的表都是相同的,因此我发现的唯一区别是双向关联的每一侧都将引用另一方,而单向则不是。
这是一个单向关联
public class User {
private int id;
private String name;
@ManyToOne
@JoinColumn(
name = "groupId")
private Group group;
}
public class Group {
private int id;
private String name;
}
双向关联
public class User {
private int id;
private String name;
@ManyToOne
@JoinColumn(
name = "groupId")
private Group group;
}
public class Group {
private int id;
private String name;
@OneToMany(mappedBy="group")
private List<User> users;
}
不同之处在于该组是否拥有用户的参考。
所以我想知道这是否是唯一的区别?哪个推荐?
#1 热门回答(113 赞)
主要区别在于双向关系提供双向导航访问,因此你可以在没有显式查询的情况下访问另一方。此外,它允许你向两个方向应用级联选项。
请注意,导航访问并不总是好的,特别是对于"一对多"和"多对多"关系。想象一下aGroup
包含数千个User
:
- 你会如何访问它们?有这么多用户,你通常需要应用一些过滤和/或分页,这样你无论如何都需要执行一个查询(除非你使用集合过滤,这看起来像是一个黑客)。在这种情况下,一些开发人员可能倾向于在内存中应用过滤,这显然不利于性能。请注意,拥有这样的关系可以鼓励这种开发人员使用它而不考虑性能影响。
- 你如何向该组添加新用户?幸运的是,Hibernate在持久化时会查看关系的拥有方,因此你只能设置User.group。但是,如果要使内存中的对象保持一致,则还需要将User添加到Group.users。但它会让Hibernate从数据库中获取Group.users的所有元素!
所以,我不同意Best Practices的建议。你需要仔细设计双向关系,考虑用例(你是否需要双向导航访问?)以及可能的性能影响。
另见:-在JPA模型中阻止"ToMany"关系
- Hibernate映射集合性能问题
#2 热门回答(10 赞)
主要有两个不同之处。
##访问关联方
第一个与你将如何访问关系有关。对于单向关联,你只能从一端导航关联。
因此,对于单向@ManyToOne
关联,这意味着你只能从外键所在的子端访问该关系。
如果你具有单向@OneToMany
关联,则表示你只能访问外键所在的父端的关系。
对于bidirectional@OneToMany
关联,你可以从父级或子级两种方式导航关联。
##性能
第二个方面与绩效有关。
- 对于@OneToMany,单向关联的执行效果不如双向关联。
- 对于@OneToOne,如果Hibernate无法判断是否应该分配代理或空值,则双向关联将导致父提取。
- 对于@ManyToMany,集合类型产生了很大的不同,因为集合的性能优于列表。
#3 热门回答(9 赞)
在编码方面,双向关系实现起来更复杂,因为应用程序负责根据JPA规范5(第42页)保持双方同步。不幸的是,规范中给出的例子没有提供更多细节,因此它没有给出复杂程度的概念。
当不使用二级缓存时,没有正确实现关系方法通常不是问题,因为实例在事务结束时被丢弃。
使用二级缓存时,如果由于错误实现的关系处理方法而导致任何内容损坏,这意味着其他事务也将看到损坏的元素(二级缓存是全局的)。
正确实现的双向关系可以使查询和代码更简单,但如果在业务逻辑方面没有真正意义,则不应该使用它。