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

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

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

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

我知道 SetList的区别。List允许重复并且有一个顺序,而 Set不能包含重复的元素并且不定义顺序。我是在 JPA 的背景下提出这个问题的。如果你严格遵循定义,那么你应该总是使用 Set类型,因为你的集合存储在关系数据库中,在那里你不能有重复的,并且你已经自己定义了一个顺序,也就是说,在你的 Java 中的顺序不一定保留在数据库中。

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

43848 次浏览

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

当我需要一套从来不关心顺序,我使用 Set。当出于某种原因顺序很重要(有序列表,按日期排序等) ,那么 List

你似乎很清楚 CollectionSetList之间的区别。使用一种方法和另一种方法的唯一原因只取决于你的需要。您可以使用 使用它们向 API 的用户(或未来的自己)传达集合的属性(它可以是微妙的,也可以是隐式的)。

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

例如,当我看到一个 List时,我知道它以某种方式进行排序,并且对于这种情况,重复的内容要么是可以接受的,要么是不相关的。当我看到一个 Set,我通常希望它没有重复和没有特定的顺序(除非它是一个 SortedSet)。当我看到一个 Collection时,除了包含一些实体之外,我并不期望从中得到更多的东西。

关于清单订购... 是的,它可以保留。即使它不是,你只是使用 @OrderBy,它仍然可以是有用的。考虑一下事件日志的示例,默认情况下按时间戳排序。人为地重新排序列表没有什么意义,但是默认排序仍然很有用。

我用:

  • Set: 当集合中的项目没有顺序且是唯一的时候
  • 列表: 当项目有顺序时

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

事实上,一个关系不能有重复的和不正常排序不应该要求使用一个集合,您可以使用任何 Collection 类型对您的应用程序最有用。

这取决于您的模型,但是,如果您要对它进行大量的包含检查,那么 Set 会更有效率。

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

你看, Http://en.wikibooks.org/wiki/java_persistence/relationships#ordering

在 JPA 中通常不支持重复,但是有些映射,例如 ElementCollections,可能支持重复。

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

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

这个决定对休眠执行的查询有着重要的影响,这里有一个小例子:

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

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

因此,如果您现在决定从 公司 XY中选择 拿开员工 ,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

现在最重要的结论是:

如果在 Employee/Company-Entities 中选择 Set 而不是 List,就不会出现这个问题,只会执行一个查询!

为什么?因为休眠不再是一个袋子的世界(如您所知,设置不允许重复)和执行只有一个查询现在是可能的。

因此,List 和 Set 之间的决定并不那么简单,至少在查询和性能方面是如此!

Https://issues.apache.org/jira/browse/openjpa-710

在 List & Set 之间进行选择应该会对如何将查询发送到 DB 产生影响。