web-dev-qa-db-ja.com

複数の条件を持つQueryDSL述語SetPath.any

私は1対多の関係を持つ単純なエンティティを持っています

@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;
   ...
}

ここでQueryDSLを使用して、「programType = "FULLTIME"およびprogramCost> $ 1000のプログラムに登録されているすべてのメンバー」にクエリを実行したいと思います。

私は次の述語を使用しました

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

jPARepositoryを使用

memberRepository.findAll(predicate);

ここで問題となるのは、2つのクエリが独立していることです。タイプ「FULLTIME」のプログラムが少なくとも1つ、またはコストが1000を超えるプログラムが少なくとも1つあるすべてのメンバーを返します。

望ましい結果:タイプがFULLTIMEでコストが1000を超えるプログラムが少なくとも1つある場合は、メンバーを返します。

9
Pranjal

ここでいくつかの助けを得ました: https://groups.google.com/forum/#!topic/querydsl/hxdejLyqXos

基本的に、プログラムの条件は別のサブクエリにある必要があります( JPASubquery インスタンス)

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);
14
Pranjal

@Shahbourが述べたように、これはQueryDsl 4.x +では機能しなくなりました。

私は同様のケースを持っていました(私のエンティティが双方向であることを除いて)、そして私はこれでそれを解決しました:

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);
4
Thoomas