tonykang22 / study

0 stars 0 forks source link

[JPA] 10장. 객체지향 쿼리 언어 #140

Open tonykang22 opened 1 year ago

tonykang22 commented 1 year ago

10장. 객체지향 쿼리 언어

객체지향 쿼리 소개



JPQL


예시

@Entity(name = "Member")
public class Member {

    @Column(name = "name")
    private String username;
    ...
}
String jpql = "select m from Member as m where m.username = 'kim'";
List<Member> resultList = em.createQuery(jpql, Member.class).getResultList();
# 실행한 JPQL
select m 
from Member as m
where m.username = 'kim'

# 실제 실행된 SQL
select 
    member.id as id,
    member.age as age,
    member.team_id as team,
    member.name as name,
from
    Member member
where
    member.name='kim'



JPQL 사용 방법



SELECT 문



TypeQuery, Query

    TypedQuery<Member> query = em.createQuery("SELECT m FROM Member m", Member.class);

    List<Member> resultList = query.getResultList();
    for (Member member : resultList) {
        System.out.println("member = " + member);
    }

   Query<Member> query = em.createQuery("SELECT m FROM Member m", Member.class);

    List resultList = query.getResultList();
    for (Object o : resultList) {
        Object[] result = (Object[]) o;
        System.out.println("username = " + result[0]);
        System.out.println("age = " + result[1]);
    }



파라미터 바인딩


이름 기준 파라미터


예시

String usernameParam = "User1";

TypedQuery<Member> query = em.createQuery("SELECT m FROM Member m where m.username = :username", Member.class);
query.setParameter("username", usernameParam);
List<Member> resultList = query.getResultList();

// 체인 방식으로 작성
List<Member> members = 
            em.createQuery("SELECT m FROM Member m where m.username = :username", Member.class)
                    .setParameter("username", usernameParam)
                    .getResultList();



위치 기준 파라미터


파라미터 바인딩 주의사항

// 파라미터 바인딩 방식을 사용하지 않고 직접 JPQL을 만들어 사용하는 경우
”select m Member m where m.username = ’” + usernameParam + ”’”



프로젝션



페이징 API



집합과 정렬



JPQL 조인


내부 조인

외부 조인

컬렉션 조인

세타 조인

# JPQL
select count (m) from Member m, Team t
where m.username = t.name

# SQL
SELECT COUNT(M.ID)
FROM
        MEMBER M CROSS JOIN TEAM T
WERHE
        M.USERNAME=T.NAME



JOIN ON 절 (JPA 2.1)



페치 조인


엔티티 페치 조인


image

image



페치 조인과 일반 조인의 차이


페치 조인의 특징


페치 조인의 한계



서브 쿼리



Named 쿼리: 정적 쿼리



Criteria


예시

    //Criteria 사용 준비
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Member> query = cb.createQuery(Member.class);

    //루트 클래스 (조회를 시작할 클래스)
    Root<Member> m = query.from(Member.class);

    //쿼리 생성
    CriteriaQuery<Member> cq = query.select(m).where(cb.equal(m.get("username"), "kim"));
    List<Member> resultList = em.createQuery(cq).getResultList();



QueryDSL


예시

//준비
    JPAQuery query = new JPAQuery(em);
    QMember member = QMember.member;

    //쿼리, 결과 조회
    List<Member> members = query.from(member)
            .where(member.username.eq("kim"))
            .list(member);



QueryDSL 사용 방법

EntityManager em = emf.createEntityManager();

        JPAQuery query = new JPAQuery(em);
        QMember qMember = new QMember("m"); // 생성되는 JPQL의 별칭이 m
        List<Member> members = query.from(qMember)
                .where(qMember.name.eq("회원1"))
                .orderBy(qMember.name.desc())
                .list(qMember);


기본 Q 생성

public class QMember extends EntityPathBase<Member> {

    public static final QMember member = new QMember("member1");
    ...
}


검색 조건 쿼리


동적 쿼리

        SearchParam param = new SearchParam();
        param.setName("둘리");
        param.setPrice(10000);

        QItem item = QItem.item;

        BooleanBuilder builder = 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)
                .list(item);


메소드 위임

public class ItemExpression {

    @QueryDelegate(Item.class)
    public static BooleanExpression isExpensive(QItem item, Integer price) {
        return item.price.gt(price);
    }
}

public class QItem extends EntityPathBase<Item> {
    ...
    public BooleanExpression isExpensive(Integer price) {
       return ItemExpression.isExpensive(this, price); 
    }
}



네이티브 SQL