我正在建立一个博客系统,并喜欢为博客提供上投/下投功能。 由于博客的票数应该被持久化,所以我选择使用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;
}
我将blogvotecounter
与Blog
分开的原因是,我认为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
或其他条件查询似乎没有什么区别。
请尝试以下操作:
class Blog{
// ...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(optional = false, fetch = FetchType.EAGER)
@PrimaryKeyJoinColumn
@Fetch(FetchMode.JOIN)
private BlogVoteCounter voteCounter;
}