JPA Annotation ElementCollection 在 Spring Boot 中急切获取

Posted

技术标签:

【中文标题】JPA Annotation ElementCollection 在 Spring Boot 中急切获取【英文标题】:JPA Annotation ElementCollection eager fetching in Spring boot 【发布时间】:2020-07-21 03:00:33 【问题描述】:

我在 spring boot 中急切地获取有一个小问题。基本上,我有一个实体定义为:

@Entity
class EventEntry(
        @ID
        val uid 

        @ElementCollection(fetch = FetchType.EAGER)
        @CollectionTable(name = "event_to_boxes", joinColumns = arrayOf(JoinColumn(name = "event_uid")))
        @Column(name = "box_uid")
        val boxUids: List<Long>
) : EventEntry(userUid, timestamp)

现在,当我插入数据时(来自 graphql,但它是一个细节),一切正常,我可以看到在数据库上的 event_to_boxes 表中正确地保留了多行。 不幸的是,当我检索所有事件时,会弹出一些意想不到的东西。

我看到的是询问所有事件的查询,然后对每个 boxUid 列表询问一次,几乎就像 FetchType.EAGER 被完全忽略一样。

我的理解是,在填充事件实体时,获取类型 Eager 应该已经获得了框 uid 的值。 是我遗漏了什么还是我的理解完全错误?

为了提供更多背景知识,我正在尝试以这种方式建模 N 对 N 关系,这是 N 关系的一半,但我必须在获取事件实体时也提出盒子uids(盒子是关系的另一半)没有任何额外的盒子数据

【问题讨论】:

你为 boxUids 声明了 getter setter 吗? 使用@JoinTable(name="event_to_boxes",joinColumns=@JoinColumn(name="event_uid")) @Curiosity : 在 kotlin 中,getter 是自动生成的,在 val 字段中禁止使用 setter @Curiosity:不幸的是,它仍然会发出很多不必要的调用。似乎没有办法提供急切的加载:/ 【参考方案1】:

正如 hibernate documentation 中所解释的,FetchType.EAGER 仅适用于直接获取实体:

EventEntry eventEntry = entityManager.find(EventEntry.class, 1L);

LEFT JOIN 子句被添加到生成的 SQL 查询中,因为需要立即获取此关联。

另一方面,如果您使用的实体查询不包含JOIN FETCH 指令...

Hibernate 使用辅助选择。这是因为实体查询获取策略不能被覆盖,所以 Hibernate 需要一个辅助选择来确保在将结果返回给用户之前获取到 EAGER 关联。

如果您忘记JOIN FETCH 所有EAGER 关联,Hibernate 将为每一个关联发出辅助选择,这反过来又会导致 N+1 查询问题。

因此,您应该更喜欢 LAZY 关联。

【讨论】:

以上是关于JPA Annotation ElementCollection 在 Spring Boot 中急切获取的主要内容,如果未能解决你的问题,请参考以下文章

2JPA-Annotation

依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true) 使用 JPA、SpringMVC、Spring

为没有 Hibernate Annotations 的 PostgreSQL 文本类型更正 JPA Annotation

JPA Annotation ElementCollection 在 Spring Boot 中急切获取

Hibernate or JPA Annotation中BLOBCLOB注解写法

Spring Annotation @WebMvcTest 在具有 Jpa 存储库的应用程序中不起作用