如何使用Hibernate获取@ElementCollection的总和?
如何用Hibernate获取@ElementCollection的总和?
先确认下你的Post实体类大概是这样的(补全了你未写完的@OneToMany部分,应该是笔误吧):
@Entity public class Post { @Id @GeneratedValue private Long id; @NotBlank @Size(min = 1, max = 2014) private String text; @NotNull @Temporal(TemporalType.TIMESTAMP) private Date created; @NotNull @ManyToOne private User author; @ElementCollection(fetch = FetchType.EAGER) private Set<String> votesFor; @ElementCollection(fetch = FetchType.EAGER) private Set<String> againstFor; @OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE) private List<Comment> comments; // 省略getter、setter }
针对获取votesFor和againstFor两个集合的总和,我整理了三个实用方案,你可以根据场景选择:
方案1:用JPQL直接查询
如果只是针对单个Post或者批量统计,直接写JPQL查询最直接,利用Hibernate支持的SIZE()函数获取集合长度:
// 假设你已经获取到EntityManager实例 Long targetPostId = 1L; Query query = entityManager.createQuery( "SELECT SIZE(p.votesFor) + SIZE(p.againstFor) FROM Post p WHERE p.id = :postId" ); query.setParameter("postId", targetPostId); Integer totalVotes = (Integer) query.getSingleResult();
注意:SIZE()函数会自动处理null集合,返回0,不用额外判空。
方案2:用@Formula注解自动计算总和
如果你希望每次加载Post实体时,就能直接拿到总和,可以用Hibernate的@Formula注解,它会在查询实体时自动执行SQL计算:
@Entity public class Post { // 其他字段保持不变 @Formula("(SELECT COUNT(*) FROM post_votes_for pvf WHERE pvf.post_id = id) + (SELECT COUNT(*) FROM post_against_for paf WHERE paf.post_id = id)") private Integer totalVotes; // 只需要添加getter,不需要setter public Integer getTotalVotes() { return totalVotes; } }
注意:这里的表名post_votes_for和post_against_for是Hibernate默认生成的集合表名,如果你在@ElementCollection里用@CollectionTable指定了自定义表名,要替换成对应的名称。
方案3:在实体类里写普通getter方法
因为你的集合是FetchType.EAGER(立即加载),所以可以直接在实体类里写一个计算总和的getter方法,不需要额外查询:
@Entity public class Post { // 其他字段保持不变 public int getTotalVotes() { int votesForCount = votesFor != null ? votesFor.size() : 0; int againstForCount = againstFor != null ? againstFor.size() : 0; return votesForCount + againstForCount; } }
这个方法最简单,但要注意如果集合是懒加载(FetchType.LAZY),调用这个方法时可能会抛出懒加载异常,所以只适合立即加载的场景。
内容的提问来源于stack exchange,提问作者user7896362
相关产品推荐
相关产品推荐

