您在JPA域模型中使用了以下哪些集合类型,为什么?
java.util.Collection
java.util.List
java.util.Set
我想知道这是否有一些基本规则。
UPDATE我知道Set
和List
之间的区别。List
允许重复并且有顺序,而Set
不能包含重复的元素并且不定义顺序。我在JPA的上下文中问这个问题。如果你严格遵循定义,那么你应该总是使用Set
类型,因为您的集合存储在关系数据库中,您不能有重复项,并且您已经自己定义了顺序,即您的Java List
中的顺序不一定保留在DB中。
例如,大多数时候我使用List
类型,不是因为它有顺序或允许重复(无论如何我不能有重复),而是因为我的组件库中的一些组件需要列表。
6条答案
按热度按时间omjgkv6w1#
就像你自己的问题所暗示的,关键是域,而不是JPA。JPA只是一个框架,你可以(也应该)以最适合你的问题的方式使用它。因为框架(或它的局限性)而选择一个次优的解决方案通常是一个警钟。
当我需要一个集合并且从不关心顺序时,我使用
Set
;当出于某种原因顺序很重要时(有序列表、按日期排序等),则使用List
。您似乎很清楚
Collection
、Set
和List
之间的区别。使用其中一个的唯一原因仅取决于您的需要。您可以使用它们向API的用户(或未来的自己)传达集合的属性(可能是微妙的或隐式的)。这与在代码中其他地方使用不同集合类型遵循完全相同的规则,您可以使用
Object
或Collections
作为所有引用,但在大多数情况下,您使用的是更具体的类型。例如,当我看到
List
时,我知道它是以某种方式排序的,重复项是可以接受的,或者与此情况无关;当我看到Set
时,我通常希望它没有重复项,也没有特定的顺序(除非它是SortedSet
);当我看到Collection
时,除了包含一些实体外,我不希望它有任何其他内容。关于列表排序......是的,它可以被保留。即使它不是,你只是使用
@OrderBy
,它仍然是有用的。考虑一下事件日志的例子,默认情况下按时间戳排序。人为地重新排序列表没有什么意义,但它仍然是有用的,它是默认排序的。7kqas0il2#
我认为使用Set或List的问题要困难得多。至少当你使用hib作为JPA实现时是这样。如果你在hib中使用List,它会自动切换到**“Bags”范例,在那里可能存在重复项。
这个决定对Hibernate执行的查询有很大的影响。这里有一个小例子:
有两个实体,employee和company**,这是一个典型的多对多关系。为了将这些实体相互Map,存在一个JoinTable(我们称之为“employeeCompany”)。
在两个实体(公司/员工)上选择数据类型List
因此,如果您现在决定从 CompanyXY 中删除Employee Joe,hib将执行以下查询:
现在的问题是:为什么hib不只是执行那个查询呢
答案很简单(感谢尼拉夫·阿萨的博客):不可以。在一个包的世界里,删除所有并重新插入所有剩余的包是唯一正确的方法!请阅读该内容以了解更多信息。http://assarconsulting.blogspot.fr/2009/08/why-hibernate-does-delete-all-then-re.html
现在得出结论:
如果您在“员工/公司-实体”中选择“集合”而不是“列表”,则不会出现此问题,并且只执行一个查询!
为什么呢?因为Hibernate不再是包的世界(如您所知,Sets不允许重复),现在只执行一个查询是可能的。
因此,在列表和集合之间做出选择并不那么简单,至少在查询和性能方面是这样!
35g0bw713#
我通常使用
List
,我发现List API比Set
更有用,与其他库的兼容性也更好,List更容易迭代,通常对大多数操作和内存更有效。一个关系不能有重复项,并且通常不是有序的,这一事实不应该要求使用Set,您可以使用对应用程序最有用的任何Collection类型。
不过这取决于您的模型,如果您要对它进行大量的包含检查,那么
Set
会更高效。您可以使用
@OrderBy
或@OrderColumn
在JPA中对关系进行排序。请参见http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Ordering
JPA中通常不支持重复,但某些Map(如
ElementCollections
)可能支持重复。lawou6xi4#
我用途:
gg0vcinb5#
https://issues.apache.org/jira/browse/OPENJPA-710
在List和Set之间进行选择应该会影响查询发送到DB的方式。
vhipe2zx6#
我认为在使用Netbeans生成实体时使用Collection作为通用默认值是一个很好的起点,然后当您弄清楚您的模型实际上是什么并需要更多功能时,您可以轻松地更改它并保持向后兼容。