2016-08-12 97 views
0

這是一個RBAC模塊,有三個基本的表用戶,角色和權限以及中間映射表user_role和role_permission。使用Criteria API和Metamodel API連接兩個中間表總是交叉連接

@Entity 
@Table(name = "USER") 
public class User implements Serializable { 
    @Id 
    private String userId; 
    ... 
} 

@Entity 
@Table(name = "ROLE") 
public class Role implements Serializable { 
    @Id 
    private String roleId; 
    ... 
} 

@Entity 
@Table(name = "PERMISSION") 
public class Permission implements Serializable { 
    @Id 
    private String permissionId; 
    ... 
} 

@Entity 
@Table(name = "USER_ROLE") 
public class UserRole implements Serializable { 
    @Id 
    @GenericGenerator(name = "uuidGenerator", strategy = "uuid") 
    @GeneratedValue(generator = "uuidGenerator") 
    @Column(name = "ID") 
    private String id; 

    @ManyToOne 
    @JoinColumn(name = "USERID") 
    private User user; 

    @ManyToOne 
    @JoinColumn(name = "ROLEID") 
    private Role role; 
    ... 
} 

@Entity 
@Table(name = "ROLE_PERMISSION") 
public class RolePermission implements Serializable { 
    @Id 
    private String id; 

    @ManyToOne 
    @JoinColumn(name = "PERMISSIONID") 
    private Permission permission; 

    @ManyToOne 
    @JoinColumn(name = "ROLEID") 
    private Role role; 
    ... 
} 

,現在我想找到user.id所有權限,SQL表達這樣的:

select rp.* from Role_Permission rp,User_Role ur where ur.roleId = rp.roleId and ur.userId = :id 

而是通過標準API:

public Predicate toPredicate(Root<RolePermission> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { 
      List<Predicate> predicates = new ArrayList<Predicate>(); 
      if (StringUtil.isNotEmpty(userId)) { 
       final Root<UserRole> userRoleRoot = criteriaQuery.from(UserRole.class); 
       Join<RolePermission,UserRole> join = root.join("role", JoinType.INNER); 
       Predicate predicate = criteriaBuilder.equal(join.get("roleId"), root.get("role").get("roleId")); 
       predicate = criteriaBuilder.and(predicate,criteriaBuilder.equal(userRoleRoot.<UserRole>get("user").get("id"), userId)); 
       predicates.add(predicate); 
      } 
      return criteriaBuilder.and(predicates.toArray(new Predicate[]{})); 
     } 

和查詢生成的結果是:

select count(rolepermis0_.id) as col_0_0_ from role_permission rolepermis0_ inner join role role2_ on rolepermis0_.roleid=role2_.roleid cross join user_role userrole1_ where role2_.roleid=rolepermis0_.roleid and userrole1_.userid=? 

但爲什麼在這裏role_permission交叉連接user_role,role_permission如何通過條件API加入user_role?

非常感謝。

+0

首先您的JPQL無效。你在關係上做一個JOIN,而不是在一個班上。因此,從「從RolePermission rp inner join rp.role r中選擇rp」開始。使用它來決定使用什麼標準 –

+0

JPQL只是一個假的代碼。我真的只需要找到是RolePermission,像這樣的SQL表達式:select rp。* from RolePermission rp,UserRole ur where ur.roleId = rp.roleId and ur。 userId =:id –

+1

首先,如果它是「僞代碼」,那麼不要發佈它。其次,如果你想添加一個謂詞(「criteriaBuilder.equal」),你應該使用「join」而不是「root.get()。get()」。另外,如果你只有RolePermission中的關係,那麼這就需要你成爲Criteria中的「候選人」......是嗎? –

回答

0
final Subquery<UserRole> userRoleSubquery = criteriaQuery.subquery(UserRole.class); 
final Root<UserRole> userRole = userRoleSubquery.from(UserRole.class); 
userRoleSubquery.select(userRole.<UserRole>get("id")); 
userRoleSubquery.where(criteriaBuilder.equal(root.get("role").get("roleId"), userRole.get("role").get("roleId")), criteriaBuilder.equal(userRole.get("user").get("id"), userId)); 
Predicate predicate = criteriaBuilder.exists(userRoleSubquery); 
predicates.add(predicate);