JPA Criteria条件加入

时间:2016-02-02 14:55:57

标签: java jpa join many-to-many criteria

我有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();

0 个答案:

没有答案