Querydsl中級文法


投影


投影とは、SELECTセクションで検索するオブジェクトを指定します.
select文で検索した内容は何ですか!
List<String> result = queryFactory
            .select(member.username)
            .from(member)
            .fetch();
以上のコードは、String用のプロジェクタが1つしかありません.
投影ターゲットが1つあれば、タイプを明確に指定できます.
クエリー・メンバー・クラスは、投影が1つのオブジェクトしかないことも示します.
2つ以上の投影オブジェクトがある場合は、凡例またはDTOを使用してクエリーを行います.
List<Tuple> result = queryFactory
            .select(member.username, member.age)
            .from(member)
            .fetch();
            
   for (Tuple tuple : result) {
      String username = tuple.get(member.username);
      Integer age = tuple.get(member.age);
      System.out.println("username=" + username);
      System.out.println("age=" + age);
}
これにより,複数のオブジェクトがある場合には,Tupleタイプを用いて探索し,Tupleから必要な値を抽出する.
このチュートリアルのほかに、DTOで書くこともできます.
JPQLの場合、DTOを選択するには、new演算子を使用してDTOのパッケージ名をすべて書き込む必要があるので、めちゃくちゃです.
QuerydslのDTOは3つの方式をサポートしています.
アクセスの設定-setter
List<MemberDto> result = queryFactory
          .select(Projections.bean(MemberDto.class,
                  member.username,
                  member.age))
          .from(member)
	  .fetch();
もちろんsetterを開きます.
フィールドダイレクトアクセス
List<MemberDto> result = queryFactory
          .select(Projections.fields(MemberDto.class,
                  member.username,
                  member.age))
          .from(member)
	  .fetch();
ジェネレータの使用
List<MemberDto> result = queryFactory
         .select(Projections.constructor(MemberDto.class,
                 member.username,
                 member.age))
         .from(member)
         .fetch();
パラメータに一致するジェネレータが必要です.
属性の名前が異なる
List<UserDto> fetch = queryFactory
        .select(Projections.fields(UserDto.class,
                member.username.as("name"),
                ExpressionUtils.as(
                   JPAExpressions
        		.select(memberSub.age.max())
        		.from(memberSub), "age")
         	)
	).from(member)
	.fetch();
ExpressionUtils.as(source,alias):フィールドまたはサブクエリの別名username.as("memberName"):フィールドに別名を適用
メンバーのユーザー名とDTOの名前を別の名前に変更します.
前述したように、サブクエリに使用されるQclassインスタンスの内外は異なるはずです.
上記のDTO戻りを宣言で解決することもできます...
@Data
@NoArgsConstructor
public class MemberDto {

    private String username;
    private int age;

    @QueryProjection
    public MemberDto(String username, int age) {
        this.username = username;
        this.age = age;
    }
}
前述したように、ジェネレータに@QueryProjection宣言を追加します.
Qclassを再構築すると、アシスタント付きQclassが生成されます.
List<MemberDto> result = queryFactory
          .select(new QMemberDto(member.username, member.age))
             .from(member)
             .fetch();
これで上と同じように簡単になります.
コンパイラでタイプをチェックできるので、これは最も安全な方法です.しかし、欠点はDTOがQuerydsl宣言を保持する必要があり、DTOもQファイルを生成する必要があることです.
この方法を使用するために、後でQuerydslを無効にする可能性があるかどうか...考えなきゃって.
Querydslに依存しているから!

動的クエリー


ついに、動的クエリーの処理部分について説明します.
ダイナミッククエリは、2つの方法で処理できます.
BooleanBuilder

BooleanBuilderクラスを設定します.
入力パラメータがnullであるかどうかを確認し、条件を与えます.
前述したように、Querydslはnullが現れると無視されます.
JPQLとは違います.
whereマルチパラメータ

各パラメータがnullであるかどうかを確認するためにwhere文に追加のメソッドを作成します.
第一の方法は比較的に直感的で分かりやすいと思います.もっと良い方法だと思います.
しかし,第2の方式は可読性が良く,方法の回収性も向上する.
基本的に実務ではこのような付加方法はよく見えないので、コードがもっと簡潔でもっと良く、細かい方法が気になっても乗れますので、確認してもいいです.
そして、最大のメリットは
private BooleanExpression allEq(String usernameCond, Integer ageCond) {
      return usernameEq(usernameCond).and(ageEq(ageCond));
}
前述したように、条件文は組み合わせて使用できます.

バッチ演算

// 28살 미만의 데이터 이름 바꾸기
long count = queryFactory
          .update(member)
	  .set(member.username, "비회원") 
	  .where(member.age.lt(28)) 
	  .execute();

// 전체 나이 1살 증가
long count = queryFactory
          .update(member)
          .set(member.age, member.age.add(1))
          .execute();

// 18살 초과 데이터 삭제
long count = queryFactory
            .delete(member)
            .where(member.age.gt(18))
            .execute();
.execute()を利用します.
JPQL展開と同様に、永続性コンテキスト内のエンティティを無視して実行するため、展開クエリーを実行した後、永続性コンテキストを初期化するのは安全です.