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 中急切获取的主要内容,如果未能解决你的问题,请参考以下文章
依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true) 使用 JPA、SpringMVC、Spring
为没有 Hibernate Annotations 的 PostgreSQL 文本类型更正 JPA Annotation
JPA Annotation ElementCollection 在 Spring Boot 中急切获取