Search code examples
springspring-data-jpahibernate-criteria

Spring Data JPA: Creating Specification Subquery from different tables


I am trying to build a specifications to predicate subquery for the below query. Select u.* from User u where u.login in (select ur.role_id from userRoles ur where ur.role_Id = roleId).

till now this is the part I have built

public static Specification<User> userRoleId(String roleId) {
        return new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                //return builder.equal(root.<LocalDate> get("scheduledDisbursementDate"), scheduledDisbursementDate);
                Subquery<UserRole> subquery = query.subquery(UserRole.class);
                Root<UserRole> subqueryRoot = subquery.from(UserRole.class);
                subquery.select(subqueryRoot);
                Predicate roleIdList = builder.equal(subqueryRoot.get("roleId"), roleId);
                subquery.select(subqueryRoot).where(roleIdList);
                return builder.exists(subquery);
            }
        };
    }

Can you please help me out to link the subquery with main query.

Note: There are no joins defined in the Entity classes. evrything should be done through subquerys only


Solution

  • Found Answer

    first predicate will join UserRole userId column with and User table login column. Second predicate will filter the condition based on roleId.

    public static Specification<User> userRoleId(String roleId) {
        return new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                Subquery<UserRole> subquery = query.subquery(UserRole.class);
                Root<UserRole> subqueryRoot = subquery.from(UserRole.class);
                subquery.select(subqueryRoot);
                Predicate userIdPredicate = builder.equal(subqueryRoot.get("userId"), root.<String> get("login"));
                Predicate rolePredicate = builder.equal(subqueryRoot.get("roleId"), roleId);
                subquery.select(subqueryRoot).where(userIdPredicate, rolePredicate);
                return builder.exists(subquery);
    
            }
        };
    }