我有2个实体用户和组在多对多关系中相关。我正在尝试使用JPA Criteria API来计算每个组的用户数。但是,我想有条件地仅为活动用户加入User实体,即User.deletedIndicator = false。
我目前所拥有的SQL是:
SELECT authorizat0_.group_name AS col_0_0_,
authorizat0_.description AS col_1_0_,
Count(user2_.user_id) AS col_2_0_
FROM authorization_group authorizat0_
LEFT OUTER JOIN user_group userset1_
ON authorizat0_.group_id = userset1_.group_id
LEFT OUTER JOIN user_account user2_
ON userset1_.user_id = user2_.user_id
GROUP BY authorizat0_.group_name,
authorizat0_.description;
我想要实现的目标是:
SELECT authorizat0_.group_name AS col_0_0_,
authorizat0_.description AS col_1_0_,
Count(user2_.user_id) AS col_2_0_
FROM authorization_group authorizat0_
LEFT OUTER JOIN user_group userset1_
ON authorizat0_.group_id = userset1_.group_id
LEFT OUTER JOIN user_account user2_
ON userset1_.user_id = user2_.user_id
**AND user2_.deleted_indicator = false**
GROUP BY authorizat0_.group_name,
authorizat0_.description;
以下是用户实体:
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, include = "all")
@Table(name = "user_account")
public class User extends BaseEntity implements Identifiable<Long>, Printable, MultiEditable<User>, java.io.Serializable {
private Long userId;
private Boolean deletedIndicator = Boolean.FALSE;
private List<AuthorizationGroup> userAuthorizationGroupList = new ArrayList<AuthorizationGroup>();
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
@Column(name = "user_id")
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
// FK
@ManyToMany(targetEntity = AuthorizationGroup.class, cascade = {
CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.LAZY)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@JoinTable(name = "user_group", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "group_id") })
public List<AuthorizationGroup> getUserAuthorizationGroupList() {
return userAuthorizationGroupList;
}
public void setUserAuthorizationGroupList(
List<AuthorizationGroup> userAuthorizationGroupList) {
this.userAuthorizationGroupList = userAuthorizationGroupList;
}
@Column(name = "deleted_indicator", length = 1)
public Boolean getDeletedIndicator() {
return deletedIndicator;
}
public void setDeletedIndicator(Boolean deletedIndicator) {
this.deletedIndicator = deletedIndicator;
}
}
这是AuthorizationGroupEntity:
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, include = "all")
@Table(name = "authorization_group")
public class AuthorizationGroup extends BaseEntity implements java.io.Serializable {
private Long authorizationGroupId;
private String groupName;
private String groupDescription;
private Set<User> userSet = new HashSet<User>();
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
@Column(name = "group_id")
public Long getAuthorizationGroupId() {
return authorizationGroupId;
}
public void setAuthorizationGroupId(Long authorizationGroupId) {
this.authorizationGroupId = authorizationGroupId;
}
@NotNull
@Column(name = "group_name", unique = true)
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
@Column(name = "description", length = 100)
public String getGroupDescription() { return groupDescription; }
public void setGroupDescription(String groupDescription) { this.groupDescription = groupDescription; }
// FK
@ManyToMany(targetEntity = com.lucas.entity.user.User.class, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
@JoinTable(name = "user_group", joinColumns = { @JoinColumn(name = "group_id") }, inverseJoinColumns = { @JoinColumn(name = "user_id") })
@JsonIgnore
public Set<User> getUserSet() {
return userSet;
}
public void setUserSet(Set<User> userSet) {
this.userSet = userSet;
}
}
以下是我用来组装的JPA Criteria代码:
EntityManager em = getEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery query = cb.createQuery();
Root<AuthorizationGroup> root = query.from(AuthorizationGroup.class);
Join<AuthorizationGroup, User> join = root.join("userSet", javax.persistence.criteria.JoinType.LEFT);
// was naively hoping that something like the following would have worked
// join.on(cb.equal(join.get("deletedIndicator"), false));
query.multiselect(root.get("groupName"), root.get("groupDescription"), cb.count(join));
query.groupBy(root.get("groupName"), root.get("groupDescription"));
List results = em.createQuery(query).getResultList();