💡 벌크 연산 PK를 특정한 엔티티의 Update, Delete를 제외한 모든 Update, Delete 쿼리이다. 쿼리 한 번으로 여러 테이블의 Row를 변경한다. (Entity) executeUpdate()의 결과는 영향을 받은 Entity의 수를 반환한다. Insert 문을 Hibernate에서 지원한다. (insert into .. select) // 재고가 10개 미만인 Product의 Price를 쿼리 한 번으로 10% 인상 String qlString = "update Product p " + "set p.price = p.price * 1.1 " + "where p.stockAmount < :stockAmount"; int resultCount = em.createQuery(qlString..
💡 Fetch Join SQL 조인의 종류가 아니다. JPQL에서 성능 최적화를 위해 제공하는 기능이다. 연관된 Entity나 Collection을 SQL 한 번에 같이 조회하는 기능 (성능 최적화) 글로벌 Fetch Loading 전략보다 우선순위가 높다. 객체 그래프를 유지할 때 사용하면 효과적이다. 여러 테이블을 조인해서 엔티티가 가진 모양이 아닌 전혀 다른 결과를 내야하면, 일반 조인을 사용하고 필요한 데이터만 조회해서 DTO로 반환하는 것이 좋다. join fetch 명령어 사용 ::= [ LEFT [OUTER] | INNER ] join fetch 경로 Entity Fetch Join 엔티티를 조회하면서 연관된 엔티티까지 같이 한번의 쿼리로 조회한다. JPQL String query = "se..
💡 JPQL 경로표현식 .(점)을 찍어 객체 그래프를 탐색하는 것 select m.username // 상태 필드 from Member m join m.team t // 단일 값 연관 필드 join m.orders o // 컬렉션 값 연관 필드 where t.name = 'teamA'; 상태 필드 단순히 값을 저장하기 위한 필드 연관 필드 연관관계를 위한 필드 단일 값 연관 필드 : 대상이 Entity이다. (N:1, 1:1) 컬렉션 값 연관 필드 : 대상이 Collection이다. (1:N, N:M) 특징 묵시적 내부 조인이 발생하는 단일 값 연관 경로, 컬렉션 값 연관 경로는 조심해서 사용해야 한다. 내부적으로 inner join문이 나가기 때문에 쿼리튜닝이 어렵기 때문에, 왠만하면 명시적 조인을 사..
💡 TypeQuery & Query TypeQuery 반환 타입이 명확할 때 사용 Query 반환 타입이 명확하지 않을 때 사용 // Member 타입, 명확한 반환 타입 TypedQuery query = em.createQuery("SELECT m FROM member m", Member.class); // String, int 2가지의 명확하지 않은 반환 타입 Query query = em.createQuery("SELECT m.username, m.age from Member m"); 💡 JPA Sub Query 쿼리 안에 서브 쿼리 작성 가능 JPA 서브 쿼리의 한계 JPA는 WHERE, HAVING 에서만 서브 쿼리 사용 가능 SELECT도 가능 (Hibernate에서 지원) FROM의 서브 쿼..
💡 Paging API JPA는 페이징 API를 다음 두 API로 추상화 해뒀다. 조회 시작위치(0부터 시작) setFirstResult(int startPosition) 조회할 데이터 수 setMaxResults(int maxResult) 예시 모든 데이터 베이스의 방언이 동작한다. LIMIT & OFFSET은 MySQL 방언이다. hibernate.dialect를 Oracle12cDialect로 변경해주면 Oracle 방언인 rownum 3 depth 전략으로 페이징을 짠다. // Member Class에 toString()을 Override 해준다. for (int i=0, i
💡 프로젝션 Select에 조회할 대상을 지정하는 것이다. 프로젝션의 대상은 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자 등 기본 데이터 타입)이다. 프로젝션 조회 대상은 전부 영속성 컨텍스트의 관리 대상이다. 엔티티 프로젝션(멤버 조회) SELECT m FROM Member m ... 결과는 멤버가 조회된다. 엔티티 프로젝션(멤버 안에 있는 팀 조회) SELECT m.team FROM Member m ... 결과는 멤버가 아닌 멤버의 팀이 결과로 조회된다. List result = em.createQuery("select m.team from Member m", Team.class) .getResultList(); // --- 쿼리 튜닝의 편리함을 위해 명시적 Join 형식으로 Join을 하는걸 ..
💡 파라미터 바인딩 왠만하면 이름으로 바인딩하자. 위치 기준으로 바인딩 시 위치가 바뀌면 꼬일 수 있다. 이름 기준 Member result = em.createQuery( "select m from Member m where m.username = :username", Member.class) .setParameter("username", "member1") .getSingleResult(); SELECT m FROM Member m where m.username=:username 위치 기준 Member result = em.createQuery( "select m from Member m where m.username = ?1", Member.class) .setParameter(1, "member1..