QueryDSL Predicate SetPath.any with multiple conditions

14,686

Solution 1

Got some help here : https://groups.google.com/forum/#!topic/querydsl/hxdejLyqXos

Basically the conditions on the program need to be in a separate subQuery (a JPASubquery instance)

QProgram program = QProgram.program
JPASubQuery subQuery = new JPASubQuery();
subQuery.from(program)
        .where(program.programType.eq(ProgramType.FULLTIME),
            program.programCost.gt(1000));

Predicate predicate = QMember.member.name.eq("John")
    .and(subQuery.exists());

memberRepository.findAll(predicate);

Solution 2

As mentionned by @Shahbour, this is not working anymore with QueryDsl 4.x+.

I had a similar case (except that my entities are bidirectionnal), and I've solved it with this :

QProgram program = QProgram.program;
QProgram member  = QProgram.member;

Predicate predicate = JPAExpressions
    .selectOne()
    .from(program)
    .where(program.member.id.eq(member.id),
            program.programCost.gt(1000),
            program.programType.eq(ProgramType.FULLTIME))
    )
    .exists();

memberRepository.findAll(predicate);
Share:
14,686
Pranjal
Author by

Pranjal

Updated on June 15, 2022

Comments

  • Pranjal
    Pranjal almost 2 years

    I have a simple entity with one to many relationship

    @Entity // and other @ stuff
    public class Member {
      @Id
      private Long id;
      private String name;
      private List<Program> programs;
      ...
    }
    
    @Entity
    public class Program {
       @Id
       private Long id;
       private Long programName;
       private ProgramType programType;
       private Long programCost;
       ...
    }
    

    Now using QueryDSL, I would like to query 'All members enrolled in a program with programType = "FULLTIME" and programCost > $1000'

    I used the following predicate

    Predicate predicate = QMember.member.programs.any()
        .programType.eq(ProgramType.FULLTIME)
          .and(QMember.member.programs.any().programCost.gt(1000));
    

    with JPARepository

    memberRepository.findAll(predicate);
    

    Now the problem is that the two queries are independent. It returns al members with at least one program of type 'FULLTIME' or at least one program of cost greater than 1000.

    Desired result : Return members if he has at least one program that is of type FULLTIME and cost > 1000.

  • Shahbour
    Shahbour almost 6 years
    I think this example is outdated for querydsl 4.x
  • user1955934
    user1955934 over 3 years
    im confused with the first 2 lines of declaration, are you using a different example? QProgram does not have a member path?
  • user1955934
    user1955934 over 3 years
    how to handle this in case of mongodb? jpa is for relational?
  • Alex K.
    Alex K. over 2 years
    This solution misses the link between program and member. It should include an additional where clause in the subquery: program.in(QMember.member.programs)