提问者:小点点

JPA单向@OneToOne关系总是触发辅助查询,即使fetchType是急切的


我正在建立一个博客系统,并喜欢为博客提供上投/下投功能。 由于博客的票数应该被持久化,所以我选择使用MySQL作为数据存储。 我使用spring JPA(Hibernate)来完成ORM工作。 下面是我的数据对象:

class Blog{
    // ...
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @OneToOne(optional = false, fetch = FetchType.EAGER)
    @PrimaryKeyJoinColumn
    private BlogVoteCounter voteCounter;    
}

和计数器类:

@Entity
public class BlogVoteCounter extends ManuallyAssignIdEntitySuperClass<Long> {
    @Id
    private Long id;

    private Integer value;
}

我将blogvotecounterBlog分开的原因是,我认为votecount字段的修改频率与Blog的其他字段完全不同,因为我想使用缓存来缓存Blog,遵循本指南,我选择将它们分开。

但是,由于在将Blog对象返回到前端时可能总是需要voteCount字段,并且为了避免N+1问题,我在Blog类中使用EAGER fetch类型声明了blogvoteCounter字段。

我已经看过这篇文章了。 因此根据我个人的理解,我使用单向关系,只在blog端声明onetoone

但是,当我检查该查询时,发现当在blogrepository上使用findAll方法时,jpa仍然会触发一个辅助查询来从数据库中检索blogvoteCounter,而不是简单地使用联接。

    select
        blogvoteco0_.id as id1_2_0_,
        blogvoteco0_.value as value2_2_0_ 
    from
        blog_vote_counter blogvoteco0_ 
    where
        blogvoteco0_.id=?

那么我应该如何配置,以始终使blog中的blogvoteCounter字段被急切地获取。

ManuallyAssignIdentitySuperClass的用法遵循spring JPA文档,因为我手动为BlogVoteCounter类分配id。

@MappedSuperclass
public abstract class ManuallyAssignIdEntitySuperClass<ID> implements Persistable<ID> {

    @Transient
    private boolean isNew = true;

    @Override
    public boolean isNew() {
        return isNew;
    }

    @PrePersist
    @PostLoad
    void markNotNew(){
        this.isNew = false;
    }
}

blogrepository派生自jparepository

public interface BlogRepository extends JpaRepository<Blog, Long>{
    // ...
}

我通过使用findAll方法触发查询,但是使用findById或其他条件查询似乎没有什么区别。


共1个答案

匿名用户

请尝试以下操作:

class Blog{
    // ...
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(optional = false, fetch = FetchType.EAGER)
    @PrimaryKeyJoinColumn
    @Fetch(FetchMode.JOIN)
    private BlogVoteCounter voteCounter;
}