您为JPA集合使用哪种Java类型?为什么?

时间:2011-01-11 07:58:30

标签: java jpa jpa-2.0

您在JPA域模型中使用以下哪种集合类型以及原因:

  • java.util.Collection
  • java.util.List
  • java.util.Set

我想知道是否有一些基本规则。

更新我知道SetList之间的区别。 List允许重复并有订单,Set不能包含重复元素,也不定义订单。我在JPA的背景下问这个问题。如果您严格遵循定义,那么您应该始终使用Set类型,因为您的集合存储在关系数据库中,您不能拥有重复项以及您自己定义订单的位置,即您的订单Java List不一定保留在数据库中。

例如,大多数时候我使用List类型,不是因为它有订单或允许重复(我无论如何都不能),因为我的组件库中有一些组件需要一份清单。

6 个答案:

答案 0 :(得分:45)

就像您自己的问题所暗示的那样,关键是域名,而不是JPA 。 JPA只是一个框架,您可以(并且应该)以最适合您的问题的方式使用它。由于框架(或其限制)而选择次优解决方案通常是警告响。

当我需要一套并且从不关心订单时,我使用Set。由于某种原因,订单很重要(有序列表,按日期排序等),然后是List

您似乎很清楚CollectionSetList之间的区别。使用一个与另一个的唯一原因仅取决于您的需求。您可以使用它们与您的API(或您未来的自己)用户沟通您的集合的属性(可能是微妙的或隐含的)。

这与在整个代码中使用不同集合类型的完全相同的规则。您可以对所有引用使用ObjectCollections,但在大多数情况下,您可以使用更具体的类型。

例如,当我看到List时,我知道它以某种方式排序,并且重复项对于这种情况是可接受的或不相关的。当我看到Set时,我通常希望它没有重复且没有特定的顺序(除非它是SortedSet)。当我看到Collection时,我不希望它包含更多内容而不是包含某些实体。

关于列表排序......是的,可以保留。即使它不是,你只使用@OrderBy,它仍然有用。想一想默认情况下按时间戳排序的事件日志示例。人为地对列表进行重新排序没有多大意义,但是默认情况下对它进行排序仍然很有用。

答案 1 :(得分:25)

我认为使用Set或List的问题要困难得多。至少当您使用 hibernate 作为JPA实现时。如果你在休眠中使用List,它会自动切换到“Bags”范例,其中存在重复的CAN。

该决定对hibernate执行的查询有重大影响。这是一个小例子:

有两个实体,员工公司,这是一种典型的多对多关系。为了将这些实体映射到彼此,JoinTable(让我们称之为“employeeCompany”)存在。

您在两个实体(公司/员工)上选择数据类型列表

因此,如果您现在决定从 CompanyXY 删除 Employee Joe ,hibernate会执行以下查询:

delete from employeeCompany where employeeId = Joe;
insert into employeeCompany(employeeId,companyId) values (Joe,CompanyXA);
insert into employeeCompany(employeeId,companyId) values (Joe,CompanyXB);
insert into employeeCompany(employeeId,companyId) values (Joe,CompanyXC);
insert into employeeCompany(employeeId,companyId) values (Joe,CompanyXD);
insert into employeeCompany(employeeId,companyId) values (Joe,CompanyXE);

现在问题是:为什么地狱会休眠不仅执行该查询?

delete from employeeCompany where employeeId = Joe AND company = companyXY;

答案很简单(Nirav Assar对他的博客帖子很多):它不能。在包袋的世界里,删除所有&重新插入所有剩余的是唯一正确的方法!阅读该内容以获得更多说明。 http://assarconsulting.blogspot.fr/2009/08/why-hibernate-does-delete-all-then-re.html

现在得出一个重大结论:

如果您在“员工/公司 - 实体”中选择“设置”而不是“列表”,则表示您没有该问题,只执行了一个查询!

为什么?因为hibernate不再是一个袋子世界(如你所知,集合不允许重复),现在只能执行一个查询。

所以列表和集合之间的决定并不那么简单,至少在查询时是这样的。性能!

答案 2 :(得分:7)

我通常使用List。我发现List API比Set更有用并且与其他库兼容。列表更易于迭代,并且通常对大多数操作和内存更有效。

关系不能重复且通常不会被订购的事实不应该要求使用Set,您可以使用对您的应用程序最有用的任何Collection类型。

这取决于你的模型,如果你要做很多包含检查的东西,那么Set会更有效率。

您可以使用@OrderBy或@OrderColumn在JPA中订购关系。

请参阅, http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Ordering

JPA通常不支持重复项,但某些映射(如ElementCollections)可能支持重复项。

答案 3 :(得分:3)

我用:

  • 设置:当集合中的项目没有订单且是唯一的
  • 列表:当项目有订单时

答案 4 :(得分:1)

https://issues.apache.org/jira/browse/OPENJPA-710

在 List 和 Set 之间进行选择应该会对查询发送到 DB 的方式产生影响。

答案 5 :(得分:0)

我认为在使用Netbeans生成实体时使用Collection作为通用默认值是一个很好的起点,然后当您弄清楚您的模型实际是什么并需要更多功能时,您可以轻松地更改它并保持向后兼容。