单向和双向 JPA 和 Hibernate 关联之间有什么区别?
单向关联和双向关联有什么区别?
由于数据库中生成的表都是相同的,所以我发现的唯一区别是双向关联的每一侧都会有对另一侧的引用,而单向关联则不会。
这是单向关联
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;
}
区别在于组是否持有用户的引用。
所以我想知道这是否是唯一的区别?推荐哪个?
What is the difference between Unidirectional and Bidirectional associations?
Since the table generated in the db are all the same,so the only difference I found is that each side of the bidiretional assocations will have a refer to the other,and the unidirectional not.
This is a Unidirectional association
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;
}
The Bidirectional association
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;
}
The difference is whether the group holds a reference of the user.
So I wonder if this is the only difference? which is recommended?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
主要区别在于双向关系提供两个方向的导航访问,以便您无需显式查询即可访问另一端。它还允许您将级联选项应用于两个方向。
请注意,导航访问并不总是好的,特别是对于“一对多”和“多对多”关系。想象一个包含数千个
用户
的组
:您将如何访问它们?对于如此多的用户,您通常需要应用一些过滤和/或分页,以便您无论如何都需要执行查询(除非您使用集合过滤,这对我来说看起来像是一个黑客)。在这种情况下,一些开发人员可能倾向于在内存中应用过滤,这显然不利于性能。请注意,拥有这样的关系可以鼓励此类开发人员使用它而不考虑性能影响。
如何将新的
用户
添加到组
?幸运的是,Hibernate 在持久化关系时会查看关系的所属方,因此您只能设置User.group
。但是,如果要保持内存中的对象一致,还需要将User
添加到Group.users
中。但它会让 Hibernate 从数据库中获取Group.users
的所有元素!所以,我不同意 最佳实践。您需要仔细设计双向关系,考虑用例(您是否需要双向导航访问?)以及可能的性能影响。
另请参阅:
The main difference is that bidirectional relationship provides navigational access in both directions, so that you can access the other side without explicit queries. Also it allows you to apply cascading options to both directions.
Note that navigational access is not always good, especially for "one-to-very-many" and "many-to-very-many" relationships. Imagine a
Group
that contains thousands ofUser
s:How would you access them? With so many
User
s, you usually need to apply some filtering and/or pagination, so that you need to execute a query anyway (unless you use collection filtering, which looks like a hack for me). Some developers may tend to apply filtering in memory in such cases, which is obviously not good for performance. Note that having such a relationship can encourage this kind of developers to use it without considering performance implications.How would you add new
User
s to theGroup
? Fortunately, Hibernate looks at the owning side of relationship when persisting it, so you can only setUser.group
. However, if you want to keep objects in memory consistent, you also need to addUser
toGroup.users
. But it would make Hibernate to fetch all elements ofGroup.users
from the database!So, I can't agree with the recommendation from the Best Practices. You need to design bidirectional relationships carefully, considering use cases (do you need navigational access in both directions?) and possible performance implications.
See also:
有两个主要区别。
访问关联方
第一个与您将如何访问关系有关。对于单向关联,您只能从一端导航关联。
因此,对于单向
@ManyToOne
关联,这意味着您只能从外键所在的子端访问该关系。如果您有单向
@OneToMany
关联,则意味着您只能从管理外键的父端访问该关系。对于双向
@OneToMany
关联,您可以从父端或从子端以两种方式导航关联。您还需要使用添加/删除实用程序方法进行双向关联以确保双方正确同步。
性能
第二个方面与性能有关。
@OneToMany
,单向关联的性能不如双向关联。@OneToOne
,如果 Hibernate 无法判断应该分配 Proxy 还是空值,则双向关联将导致急切地获取父级。@ManyToMany
,集合类型有很大不同,因为Set
的性能比List
更好。There are two main differences.
Accessing the association sides
The first one is related to how you will access the relationship. For a unidirectional association, you can navigate the association from one end only.
So, for a unidirectional
@ManyToOne
association, it means you can only access the relationship from the child side where the foreign key resides.If you have a unidirectional
@OneToMany
association, it means you can only access the relationship from the parent side which manages the foreign key.For the bidirectional
@OneToMany
association, you can navigate the association in both ways, either from the parent or from the child side.You also need to use add/remove utility methods for bidirectional associations to make sure that both sides are properly synchronized.
Performance
The second aspect is related to performance.
@OneToMany
, unidirectional associations don't perform as well as bidirectional ones.@OneToOne
, a bidirectional association will cause the parent to be fetched eagerly if Hibernate cannot tell whether the Proxy should be assigned or a null value.@ManyToMany
, the collection type makes quite a difference asSets
perform better thanLists
.我不能 100% 确定这是唯一差异,但这是主要差异。 Hibernate 文档还建议进行双向关联:
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/best-practices.html
具体来说:
我个人对这个一揽子建议有一个小问题——在我看来,在某些情况下,孩子没有任何实际理由了解其父母(例如,为什么订单项目需要了解它所关联的顺序?),但我确实在合理的时间内看到了它的价值。而且由于双向性并没有真正伤害任何东西,所以我觉得坚持它并没有太令人反感。
I'm not 100% sure this is the only difference, but it is the main difference. It is also recommended to have bi-directional associations by the Hibernate docs:
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/best-practices.html
Specifically:
I personally have a slight problem with this blanket recommendation -- it seems to me there are cases where a child doesn't have any practical reason to know about its parent (e.g., why does an order item need to know about the order it is associated with?), but I do see value in it a reasonable portion of the time as well. And since the bi-directionality doesn't really hurt anything, I don't find it too objectionable to adhere to.
在编码方面,双向关系的实现更加复杂,因为应用程序负责根据 JPA 规范 5(第 42 页)保持双方同步。不幸的是,规范中给出的示例没有提供更多细节,因此它没有给出复杂程度的想法。
当不使用二级缓存时,没有正确实现关系方法通常不是问题,因为实例在事务结束时被丢弃。
当使用二级缓存时,如果由于错误地实现关系处理方法而导致任何内容被损坏,这意味着其他事务也将看到损坏的元素(二级缓存是全局的)。
正确实现的双向关系可以使查询和代码更简单,但如果它在业务逻辑方面没有真正意义,则不应使用。
In terms of coding, a bidirectional relationship is more complex to implement because the application is responsible for keeping both sides in synch according to JPA specification 5 (on page 42). Unfortunately the example given in the specification does not give more details, so it does not give an idea of the level of complexity.
When not using a second level cache it is usually not a problem to do not have the relationship methods correctly implemented because the instances get discarded at the end of the transaction.
When using second level cache, if anything gets corrupted because of wrongly implemented relationship handling methods, this means that other transactions will also see the corrupted elements (the second level cache is global).
A correctly implemented bi-directional relationship can make queries and the code simpler, but should not be used if it does not really make sense in terms of business logic.