QueryDSL

53084 ワード

QueryDSL
クエリーを非文字コードで記述し、クエリーに似た外観のシンプルで簡潔なクエリーを開発できるプロジェクトです.
  <dependency>
        <groupId>com.mysema.querydsl</groupId>
        <artifactId>querydsl-jpa</artifactId>
        <version>3.6.3</version>
    </dependency>

    <dependency>
        <groupId>com.mysema.querydsl</groupId>
        <artifactId>querydsl-apt</artifactId>
        <version>3.6.3</version>
    </dependency>
Querydsl-jpa:QuerdsL JPAライブラリ
Querydsl-apt:クエリー・タイプを作成するために必要なライブラリ
in pom.xml
  <build>
        <plugins>
            <plugin>
                <groupId>com.mysema.maven</groupId>
                <artifactId>apt-maven-plugin</artifactId>
                <version>1.1.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>process</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>target/generated-sources/java</outputDirectory>
                            <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>
コンパイル時にtarget/generated-sources/java/フォルダにメタモデル(Q)クラスファイルが作成されます.
開始します.
 EntityManager em = emf.createEntityManager();

  // 쿼리타입 생성 생성자의 파라미터는 별칭이다 
 JPAQuery query = new JPAQuery(em);
  
 List<Member> members = query.from(member)
                .where(member.name.eq("회원1"))
                .orderBy(member.name.desc())
                .list(member);
基本Qの作成
クエリタイプ(Q)は、メタモデルクラスに静的インスタンスを保存して使用しやすいようにします.
public class QMember extends EntityPathBase<Member> {

    public static final QMember member = new QMember("member1");
したがって
QMember qMember= new jpabook.queryDSL.QMember("m");// 직접 별칭 생성
QMember qMember1 = jpabook.queryDSL.QMember.member; // 기본 인스턴스 사용
どちらかをクエリータイプとして使用すればよい.
検索条件の問合せ
  QItem item = QItem.item;
  List<Item> items = query.from(item)
  				.where(item.name.eq("상품A").and(item.price.gt(20000)).list(item);
->
select item from Item item where item.name =?1 and item.price > ?2
クエリー・タイプ・フィールドには、必要なメソッドの大部分が明確に表示されます.
item.price.between(100,150);
item.name.contains("상품A"); // like '%상품A%'
item.name.startsWith("고급"); // lite '고급%'
クエリ結果
クエリーを作成すると、結果クエリー・メソッドが呼び出されると、実際のデータベースがクエリーされます.
1.uniqueResult():クエリーの結果が1つの場合に使用し、ない場合nullを返し、1つ以上の場合に例外が発生します.
2.singleResult():uniqueResultと同じですが、1つ以上のデータが検出された場合、最初のデータが返されます.
3.list():結果が1つ以上の場合に使用され、ない場合は空の配列を返します.
ページの配置
QItem item = QItem.item;
query.from(item)
	.orderBy(item.price.desc(), item.stockQuantity.asc())
    .offset(10).limit(20)
    .list(item)
restrict()メソッドでは、ページングにはQueryModifiersをパラメータとして使用できます.
QueryModifiers qm = new QueryModifier(20L,10L); // limit, offset

List<Item> items = query.from(item).restrict(qm).list(list);
実際のページングを行うには、合計データ数を知る必要があります.リスト()ではなくlistResults()を使用します.
listResults()カウントクエリを再度使用します.
SearchResults<Item> results = query.from(item)
	.where(item.price.gt(1000))
    .offset(10).limit(20)
    .listResults(item);
    
long total = results.getTotal();
long limit = results.getLimit();
long offset = results.getOffset();
List<Item> items =results.getResults();
チーム
グループBy()を使用してグループ結果を制限するにはhave()を使用します.
query.from(item)
	.groupBy(item.price)
    .having(item.price.gt(10000))
    .list(item);
    
サイン
InnerJoin、leftJoin、rightJoin、fullJoin、on、fetchを使用できます.
結合は、最初のパラメータに結合オブジェクトを指定し、2番目のパラメータに別名を使用するクエリー・タイプです.
기본조인
QOrder order = QOrder.order;
QMember member = QMember.member;
QOrderItem orderItem = QOrderItem.orderItem;

query.from(order)
	.join(order.member ,member)
    .leftJoin(order.orderItems, ordreItem)
    .list(order);
    
// 조인 on 사용

query.from(order)
	.leftJoin(order.orderItems, orderItem)
    .on(orderItem.count.gt(2))
    .list(order);
//fetch join

query.from(order)
	.innerJoin(order.member, member).fetch()
    .leftJoin(order.orderItems,orderItem).fetch()
    .list(order)
//from 절에 여러 조건 사용

QOrder order = QOrder.order;
QMember member =QMember.member;

query.from(order,member)
	.where(order.member.eq(member))
    .list(order);
サブクエリ
サブクエリの結果は一意()であり、複数の結果はlist()である.
// 서브 쿼리 한건	
QItem item = QItem.item;
QItem itemSub = new QItem("itemSub");

query.from(item)
	.where(item.price.eq(
		new JPASubQuery().from(itemSub).unique(itemSub.price.max())
	))
	.list(item);
//  서브쿼리 조회 여러건

QItem item = QItem.item;
QItem itemSub = new QItem("itemSub");

query.from(item)
	.where(item.in(
   	 new JPASubQuery().from(itemSub)
        .where(item.name.eq(itemSub.name))
		.list(itemSub)
)).list(item);
投影結果を返す
投影ターゲット1
QItem item = QItem.item;
List<String> result = query.from(item).list(item.name);
複数の列と釘を返します.
投影ターゲットとして複数のフィールドを選択すると、基本的にTupleと呼ばれるMapに似た内部タイプがQueryDSLによって使用されます.
結果はTupleget()メソッドのクエリータイプを指定できます.
QItem item = QItem.item;

List<Tuple> result = query.from(item).list(item.name, item.price);
// List<Tuple> result = query.from(item).list(new QTuple(item.name, item.price));


for(Tuple tuple : result) {
	soutv("name =" + tuple.get(item.name));
    soutv("price = " + tuple.get(item.price));
}
空の作成
エンティティではなく特定のオブジェクトとしてクエリー結果を受信する場合は、空の生成機能を使用します.
QueryDSL内のオブジェクトを作成するには、さまざまな方法があります.
1.Propertyアクセス
2.直接アクセスフィールド
3.現実に近づく
public class ItemTDO{
	String username;
    int price;
    
    // 기본생성자
    // 모든 필드 생성자
    
    // 개터 셋터
}
    
1.Property Access(Setter)
QItem item = QItem.item;
List<ItemDTO> result = query.from(item).list(
	Projections.bean(ItemDTO.class, item.name.as("username"), item.price));
2.フィールドアクセス
QItem item = QItem.item;
List<ItemDTO> result = query.from(item).list(
	Projections.fields(ItemDTO.class, item.name.as("username"), item.price));
2.ジェネレータアクセス
QItem item = QItem.item;
List<ItemDTO> result = query.from(item).list(
	Projections.constructor(ItemDTO.class, item.name, item.price));
DISTINCT
quert.distinct.from(item)...
削除の変更クエリーの展開
QueryDSLでは、バッチ・クエリー(変更や削除など)も使用します.
JPQLバッチクエリーのように、永続性コンテキストを無視してDebeに直接クエリーを送信します.
// 수정,

QItem item= QItem.item;

JPAUpdateClause updateClause = new JPAUpdateClause(em,item);
long count = updateClause.where(item.name.eq("책A"))
.set(item.price, item.price.add(100))
.excute();
本Aの価格は100元加算されます.
// 삭제,
QItem item= QItem.item;
JPADeleteClause deleteClause = new JPADeleteClause(em,itme);
long count = deleteClause.where(item.name.eq("책A")).excute();
動的クエリー
SearchParam param = new SearchParam();
param.setName("bookA");
param.setPrice(1000);

QItem item = QItem.item;

BooleanBuilder buildere = new BooleanBuilder();

if(StringUtils.hasText(param.getName())){
	builder.and(item.name.contains(param.getName()));
}

if(param.getPrice() != null) {
	builder.and(item.price.gt(param.getPrice()));
}
List<Item> result = query.from(item)
	.where(builder)
    .lite(list);
委任メソッド
検索条件は、クエリー・タイプで直接定義できます.
// 검색 조건 정의

import com.mysema.query.annotations.QueryDelegate;
import com.mysema.query.types.expr.BooleanExpression;

public class ItemExpression {

	@QueryDelegate(Item.class) // 엔티티가 아니라 자바 기장 내장 타입도 가능하다.
    public static BooleanExpression isExpensive(QItem item , Integer price) {
    	return item.price.gt(price);
   }
}
クラスに静的メソッドを作成し、@QueryDelegateプレゼンテーションにこの機能を適用するエンティティを属性として指定します.
静的メソッドの最初のパラメータは、ターゲットエンティティのクエリー・タイプを指定し、残りのパラメータは必要なパラメータを定義します.コンパイル後、次の方法を4つのタイプに追加します.
public class QItem extends EntityPathBase<Item> {
	...
    public com.mysema.query.types.expr.BooleanExpression isExpensive(Integer price) {
        return ItemExpression.isExpensive(this, price);
    }
定義された機能が後でクエリタイプに追加され、使用できることがわかります.
query.from(item).where(item.isExpensive(30000)).list(item);