【问题标题】:Projections do not load ManyToOne relations lazily投影不会延迟加载多对一关系
【发布时间】:2026-01-26 17:45:01
【问题描述】:

我有一个代表 MySQL 表的实体:

@Entity
@Table(name = "group_")
@Getter
@Setter
@SuppressWarnings("serial")
public class GroupEntity
        implements Serializable {

    @Id
    @GeneratedValue(generator = "uuid2")
    @Column(name = "group_id")
    private UUID groupId;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "owner_account_id")
    @NotNull
    private AccountEntity ownerAccount;

    @Column(name = "value")
    @NotBlank
    private String value;

}

还有一个投影:

public interface GroupBaseProjection {

    UUID getGroupId();

    AccountEntity getOwnerAccount();

}

这是我的仓库:

public interface GroupsRepository extends JpaRepository<GroupEntity, UUID> {

    GroupBaseProjection findBaseByGroupId(UUID groupId);

}

当我检索实体时,ownerAccount 被延迟加载(Hibernate MySQL 查询只选择它的 ID)但是当我检索投影时,它被急切地加载(Hibernate MySQL 查询与所有 @ 987654325@ 列)。所以我无法只检索GroupEntity 的某些列(我必须使用实体检索所有列,或者使用投影检索其中一些加上AccountEntity 的所有列)。

有没有办法让投影延迟加载@ManyToOne 关系?我尝试用@ManyToOne(fetch = FetchType.LAZY, optional = false)@LazyToOne(LazyToOneOption.PROXY) 注释getOwnerAccount() 投影方法,但没有成功。

【问题讨论】:

  • 您不应该使用包含实体的投影。相反,您应该只选择您需要的列
  • 我可以这样做,但是(1)它不会有任何区别,因为嵌套投影选择所有列,而不仅仅是 getter 中定义的列,并且(2)我不想得到account 表中的一些列,我只想要 id(我不想看到内部连接,即使它只有 id 列)

标签: java jpa spring-data lazy-loading projection


【解决方案1】:

所以我无法只检索 GroupEntity 的某些列

当然有,使用嵌套投影即可:

public interface AccountProjection {

    Long getId();

    String getName();

   ... // other columns

} 

public interface GroupBaseProjection {

    UUID getGroupId();

    AccountProjection getOwnerAccount();

}

有没有办法让投影延迟加载@ManyToOne 关系?

我不这么认为,因为投影不是实体,因此它们不受 JPA 管理。

EDIT 无论如何,嵌套投影似乎选择了所有实体属性(参见 cmets)。作为一种解决方法,如果您只对 id 感兴趣,您可以尝试再次将连接列映射为一个简单的属性:

@Column(name = "owner_account_id", insertable = false, updatable = false)
private Long ownerAccountId;

这样,您就可以使其成为投影的一部分。

【讨论】: