休眠集合元素 EAGER 获取重复元素

2022-09-01 01:15:42

我有一个名为DistinyMapping的类,它有一个值的集合,映射为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;
    }
}

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

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

我已经在运行之间清除了数据库,并且可以在急切和懒惰之间重复这个问题。

我认为这与休眠在下面创建的连接有关,但我无法在网上找到明确的答案。

谁能告诉我为什么一个热切的获取是复制对象?

谢谢。


答案 1

我遇到了同样的问题 - 当您为@CollectionOfElements设置FetchType.EAGER时,Hibernate尝试一次性获取所有内容,即对链接到“主”对象的每个元素条目使用一个查询。如果将@Fetch (FetchMode.SELECT) 注释添加到集合中,则可以以 N+1 查询为代价成功解决此问题。在我的情况下,我希望有一个MediaObject实体,其中包含其元数据项(视频编解码器,音频编解码器,大小等)的集合。元数据项集合的映射如下所示:

@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>();

答案 2

在映射中强制执行急切提取通常不是一个好主意 - 最好在适当的查询中指定急切联接(除非您100%确定在任何和所有情况下,您的对象在没有填充该集合的情况下都没有意义/有效)。

您获得重复项的原因是因为 Hibernate 在内部联接您的根表和集合表。请注意,它们实际上是重复的,例如,对于具有3个集合元素的2个同义词映射,每个元素您将获得6个结果(2x3),每个同义词映射实体的3个副本。因此,最简单的解决方法是将结果包装在 Set 中,从而确保它们是唯一的。


推荐