您在JPA域模型中使用以下哪种集合类型以及原因:
java.util.Collection
java.util.List
java.util.Set
我想知道是否有一些基本规则。
更新我知道Set
和List
之间的区别。 List
允许重复并有订单,Set
不能包含重复元素,也不定义订单。我在JPA的背景下问这个问题。如果您严格遵循定义,那么您应该始终使用Set
类型,因为您的集合存储在关系数据库中,您不能拥有重复项以及您自己定义订单的位置,即您的订单Java List
不一定保留在数据库中。
例如,大多数时候我使用List
类型,不是因为它有订单或允许重复(我无论如何都不能),因为我的组件库中有一些组件需要一份清单。
答案 0 :(得分:45)
就像您自己的问题所暗示的那样,关键是域名,而不是JPA 。 JPA只是一个框架,您可以(并且应该)以最适合您的问题的方式使用它。由于框架(或其限制)而选择次优解决方案通常是警告响。
当我需要一套并且从不关心订单时,我使用Set
。由于某种原因,订单很重要(有序列表,按日期排序等),然后是List
。
您似乎很清楚Collection
,Set
和List
之间的区别。使用一个与另一个的唯一原因仅取决于您的需求。您可以使用它们与您的API(或您未来的自己)用户沟通您的集合的属性(可能是微妙的或隐含的)。
这与在整个代码中使用不同集合类型的完全相同的规则。您可以对所有引用使用Object
或Collections
,但在大多数情况下,您可以使用更具体的类型。
例如,当我看到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作为通用默认值是一个很好的起点,然后当您弄清楚您的模型实际是什么并需要更多功能时,您可以轻松地更改它并保持向后兼容。