Need to find all Users for a specific role JPA Criteria API

独自空忆成欢 提交于 2020-06-29 04:04:17

问题


I am implementing a user management system which has the following entities :

public class UserEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    Long id;

    @Column(unique = true, name = "EMAIL")
    private String email;
    @Column(name = "NAME")
    private String name;
    @Column(name = "PASSWORD")
    private String password;
    @Column(name = "MOBILE")
    private String mobile;
    @Column(name = "OWNER_ID")
    private String ownerId;
    @Column(name = "TRAINER_ID")
    private String trainerId;
    @Column(name = "ADDED_ON")
    private Timestamp addedOn;
    @Column(name = "MODIFIED_ON")
    private Timestamp modifiedOn;
    @Column(name = "ADDED_BY")
    private String addedBy;
    @Column(name = "MODIFIED_BY")
    private String modifiedBy;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "USER_ROLES", joinColumns = @JoinColumn(name = "USER_ID", referencedColumnName = "ID"),
            inverseJoinColumns =
            @JoinColumn(name =
                    "ROLE_ID", referencedColumnName = "ROLE_ID"))
    List<RoleEntity> roles;

    @OneToOne(
            mappedBy = "user",
            cascade = CascadeType.ALL,
            orphanRemoval = true,
            fetch = FetchType.LAZY
    )
    private UserStatisticsEntity userStatisticsEntity;

here is the RoleClass :

public class RoleEntity implements GrantedAuthority {

    @Id
    @Column(name="ROLE_ID")
    private String roleId;

    @Column(name="ROLE_NAME")
    private String roleName;

    @ManyToMany(mappedBy = "roles")
    private List<UserEntity> users;

    @Override
    public String getAuthority() {
        return this.roleId;
    }
}

I would like to fetch all users belonging to a particular role and also be able to add dynamic where clauses on name, mobile, email along with paging etc.

My current code looks like this to fetch selected fields of Users with dynamic where clauses and pagination :

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();

        CriteriaQuery<TrainerDTO> criteriaQuery = criteriaBuilder.createQuery(TrainerDTO.class);
        Root<UserEntity> main = criteriaQuery.from(UserEntity.class);
        criteriaQuery.multiselect(main.get("id"), main.get("name"), main.get("email"), main.get("ownerId"), main.get(
                "mobile"),
                main.get("addedBy"), main.get("modifiedBy"), main.get("addedOn"), main.get("modifiedOn"))
                     .orderBy(criteriaBuilder.desc(main.get("addedOn")))
                     .distinct(true);
        List<Predicate> predicates = new ArrayList<>();
        if (StringUtils.isNotBlank(queryParams.get("mobile"))) {
        predicates.add(criteriaBuilder.and(criteriaBuilder.equal(main.get("mobile"), queryParams.get("mobile"))));
    }
    if (StringUtils.isNotBlank(queryParams.get("name"))) {
        predicates.add(criteriaBuilder.and(criteriaBuilder.like(main.get("name"),
                "%" + queryParams.get("name") + "%")));
    }
    if (StringUtils.isNotBlank(queryParams.get("email"))) {
        predicates.add(criteriaBuilder.and(criteriaBuilder.equal(main.get("email"), queryParams.get("email"))));
    }
        criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));
        log.info("TrainerDAO::getAllTrainersPaginatedForOwner Query created...");

        TypedQuery<TrainerDTO> query = entityManager.createQuery(criteriaQuery);
        query.setFirstResult(pageNumber - 1);
        query.setMaxResults(pageSize);
        return query.getResultList();

I am having two issues here :

  1. How do I get all users which have a certain role? Suppose I need to find all users which have a Role with ROLE_ID = "ROLE_ADMIN".
  2. In my pagination implementation, the last item in repeated on the next page. Suppose User1 was the last item on page 1, he is coming as first item on page 2 as well.

Please suggest on how to proceed further. All help would be appreciated.


回答1:


Here is my way would be like this:

Issue 1:

You need to reach RoleEntity to check if the role_id is equal to "ROLE_ADMIN", so you need to fetch roles from RoleEntity first and get all the information there.

After you created main object:

Fetch<UserEntity, RoleEntity> fetchedRoles = main.fetch("roles", JoinType.LEFT);
  1. You will append your condition to your predicates list;
predicates.add(criteriaBuilder.equal( fetchedRoles.get( "roleId" ), "ROLE_ADMIN"));

Issue 2:

I will try to share what I would do in this case to help you solve the issue.

Let's say you create the query here, in this method with pageable object, you want to return Page

private Page<Books> getUsersWithAdminRole(String... parameters, Pageable pageable){
  //...

  List<UserEntity> result = entityManager.createQuery(criteria).setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize()).getResultList();

  CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
  Root<UserEntity> userCount = countQuery.from(UserEntity.class);
  countQuery.select(criteriaBuilder.count(userCount)).where(criteriaBuilder.and(predicates.toArray(newPredicate[predicates.size()])));
  Long count = entityManager.createQuery(countQuery).getSingleResult();
  Page<UserEntity> userPage = new PageImpl<>(result, pageable, count);
  return userPage;
}

I hope, it is helpful



来源:https://stackoverflow.com/questions/61850249/need-to-find-all-users-for-a-specific-role-jpa-criteria-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!