使用Criteria API和Metamodel API连接两个中间表始终交叉连接

时间:2016-08-12 02:48:43

标签: jpa criteria-api

这是一个RBAC模块,有三个基本表用户,角色和权限以及中间映射表user_role和role_permission。

@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

但是根据Criteria 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?

非常感谢。

1 个答案:

答案 0 :(得分: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);