Hibernate CollectionOfElements EAGER获取重复的元素

我有一个名为SynonymMapping的类,它具有映射为CollectionOfElements的值集合

@Entity(name = "synonymmapping") public class SynonymMapping { @Id private String keyId; //@CollectionOfElements(fetch = FetchType.EAGER) @CollectionOfElements @JoinTable(name="synonymmappingvalues", joinColumns={@JoinColumn(name="keyId")}) @Column(name="value", nullable=false) @Sort(type=SortType.NATURAL) private SortedSet<String> values; public SynonymMapping() { values = new TreeSet<String>(); } public SynonymMapping(String key, SortedSet<String> values) { this(); this.keyId = key; this.values = values; } public String getKeyId() { return keyId; } public Set<String> getValues() { return values; } } 

我有一个testing,我将两个SynonymMapping对象存储到数据库,然后要求数据库返回所有已保存的SynonymMapping对象,期望收到我存储的两个对象。

当我将值的映射更改为渴望(如代码中的注释行所示)并再次运行testing时,我会收到四个匹配项。

我已经清除了运行之间的数据库,我可以复制这个问题在渴望和懒惰之间交换。

我认为这与Hibernate创build的连接有关,但我无法在网上find明确的答案。

任何人都可以告诉我为什么渴望获取是复制对象?

谢谢。

在映射中强制执行提取通常不是一个好主意 – 最好是在适当的查询中指定eager连接(除非你100%确定在任何情况下你的对象在没有这个集合的情况下是没有意义的被填充)。

你得到重复的原因是因为Hibernate内部join你的根和集合表。 请注意,它们实际上是重复的,例如对于3个集合元素的2个SynonymMappings,每个会得到6个结果(2×3),每个SynonymMapping实体有3个副本。 所以最简单的解决方法是将结果包装在一个Set中,从而确保它们是唯一的。

我进入了同样的问题 – 当你设置一个@CollectionOfElements的FetchType.EAGER时,Hibernate试图一次性得到所有东西,例如,对链接到“主”对象的元素的每个条目使用一个查询。 如果您将@Fetch(FetchMode.SELECT)注释添加到您的集合中,则可以以N + 1查询为代价成功解决此问题。 在我的情况下,我想有一个MediaObject实体与其元数据项(video编解码器,audio编解码器,大小等)的集合。 metadataItems集合的映射如下所示:


 @CollectionOfElements(targetElement = String.class,fetch = FetchType.EAGER)
 @JoinTable(name =“mo_metadata_item”,joinColumns = @JoinColumn(name =“media_object_id”))
 @MapKey(columns = @Column(name =“name”))
 @Column(name =“value”)
 @Fetch(FetchMode.SELECT)
 private Map <String,String> metadataItems = new HashMap <String,String>();

我遇到了这个问题,我解决了这个问题

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

这将清除由对子表进行的联接所造成的重复项。

您可以使用SELECT DISTINCT(Hibernate查询语言)子句如下

 SELECT DISTINCT synonym FROM SynonymMapping synonym LEFT JOIN FETCH synonym.values 

DISTINCT子句删除Hibernate中的重复引用。

虽然组件和值types集合的生命周期都绑定到拥有的实体类,但是您应该在select子句中声明它们以检索它们。 (LEFT JOIN FETCH synonym.values)

ChssPly76的答案是另一种方法,但是不要忘记根据Set语义覆盖equals和hashcode方法

问候,

用N + 1查询代替FetchMode.SELECT ,最好使用BatchSize eq @BatchSize(size = 200)

DISTINCTCriteria.DISTINCT_ROOT_ENTITY不起作用,如果您必须获取多个关联。 对于这种情况下,请参阅其他解决scheme: https : //stackoverflow.com/a/46013654/548473