728x90

JPA 48

@Converter (부제 - 데이터 변환)

컨버터(converter)를 사용하면 엔티티의 데이터를 변환해서 데이터베이스에 저장할 수 있다. 자바의 boolean 타입은 방언에 따라 다르지만 데이터베이스에 저장될 때 0 또는 1인 숫자로 저장된다. 그런데 데이터베이스에 숫자 대신 문자 Y 또는 N으로 저장하고 싶다면 컨버터를 사용하면 된다. CREATE TABLE MEMBER ( ID VARCHAR(255) NOT NULL, USERNAME VARCHAR(255), VIP VARCHAR(1) NOT NULL, -- 변환할 컬럼 PRIMARY KEY(ID) ) 매핑할 테이블을 보면 문자 Y, N을 입력하려고 VIP 컬럼을 VARCHAR(1)로 지정했다. @Entity public class Member { @Id private String id; p..

JPA 2022.06.21

벌크 연산(부제 - DB에 직접 쿼리)

엔티티를 수정하려면 영속성 컨텍스트의 변경 감지 기능이나 병합을 사용한다. 하지만 이방법으로는 수백개 이상의 엔티티를 하나씩 처리하기에는 시간이 너무 오래 걸린다. 이럴 때 여러건을 한 번에 수정하거나 삭제하는 벌크 연산을 사용하면 된다. String sqlString = "update Product p " + "setp.price = p.price * 1.1 " + "where p.stockAmount < :stockAmount"; int resultCount = em.createQuery(qlString) .setParameter("stockAmount", 10) .executeUpdate(); 벌크 연산은 executeUpdate() 메소드를 사용한다. 이 메소드는 벌크 연산으로 영향을 받은 엔티티..

JPA 2022.06.18

컬렉션 엔티티 조회 + 페이징을 함께 해결 (feat. default_batch_fetch_size)

먼저 ToOne(OneToOne, ManyToOne) 관계를 모두 페치조인 한다. ToOne 관계는 row수를 증가시키지 않으므로 페이징 쿼리에 영향을 주지 않는다. 컬렉션은 지연 로딩으로 조회한다. 지연 로딩 성능 최적화를 위해 hibernate.default_batch_fetch_size , @BatchSize 를 적용한다. hibernate.default_batch_fetch_size: 글로벌 설정 - 이 옵션을 사용하면 컬렉션이나, 프록시 객체를 한꺼번에 설정한 size 만큼 IN 쿼리로 조회한다. @Repository public class OrderRepository { public List findAllWithMemberDelivery(int offset, int limit) { return..

JPA 2022.06.16

QueryDSL(Criteria 보다 더 나은 JPQL 빌더)

쿼리를 문자가 아닌 코드로 작성해도, 쉽고 간결하며 그 모양도 쿼리와 비슷하게 개발할 수 있는 프로젝트가 바로 QueryDSL이다. QueryDSL도 Criteria처럼 JPQL 빌더 역할을 하는데 JPA Criteria를 대체할 수 있다. QueryDSL 설정 .... com.mysema.maven apt-maven-plugin 1.1.3 process target/generated-sources/java com.querydsl.apt.jpa.JPAAnnotationProcessor .... com.querydsl querydsl-apt ${querydsl.version} provided com.querydsl querydsl-jpa ${querydsl.version} querydsl-jpa: Quer..

JPA 2022.06.16

Criteria 기초(feat. JPQL의 빌더 클래스)

Criteria 쿼리는 JPQL을 자바 코드로 작성하도록 도와주는 빌더 클래스 API다. Criteria를 사용하면 문자가 아닌 코드로 JPQL을 작성하므로 문법 오류를 컴파일 단계에서 잡을 수 있고 문자 기반의 JPQL보다 동적 쿼리를 안전하게 생성할 수 있는 장점이 있다. 하지만 실제 Criteria를 사용해서 개발해보면 코드가 복잡하고 장황해서 직관적으로 이해가 힘들다는 단점도 있다. //JPQL: select m from Member m CriteriaBuilder cb = em.getCriteriaBuilder(); //Criteria 쿼리 빌더 ...1 //Criteria 생성, 반환 타입 지정 ...2 CriteriaQuery cq = cb.createQuery(Member.class); R..

JPA 2022.06.16

페치 조인과 일반 조인의 차이(feat. 연관된 엔티티 함께 조회)

페치 조인을 사용하지 않고 조인만 사용하면 어떻게 될까 select t-- 내부 조인 JPQL from Team t join t.members m where t.name = '팀A' SELECT--실행된 SQL T.* FROM TEAM T INNER JOIN MEMBER M ON T.ID=M.TEAM_ID WHERE T.NAME = '팀A' JPQL에서 팀과 회원 컬렉션을 조인했으므로 회원 컬렉션도 함께 조회할 것으로 기대해선 안 된다. 실행된 SQL의 SELECT 절을 보면 팀만 조회하고 조인했던 회원은 전혀 조회하지 않는다. JPQL은 결과를 반환할 때 연관관계까지 고려하지 않는다. 단지 SELECT 절에 지정한 엔티티만 조회할 뿐이다. 따라서 팀 엔티티만 조회하고 연관된 회원 컬렉션은 조회하지 않는..

JPA 2022.06.15

페이징 API

JPA는 페이징을 다음 두 API로 추상화했다. setFirstResult(int startPosition): 조회 시작 위치(0부터 시작한다) setMaxResults(int maxResult): 조회할 데이터 수 TypedQuery query = em.createQuery("SELECT m FROM Member m ORDER BY m.username DESC", Member.class); query.setFirstResult(10); query.setMaxResults(20); query.getResultList(); 위 코드를 분석하면 FirstResult의 시작은 10이므로 11번째부터 시작해서 총 20건의 데이터를 조회한다. 따라서 11~30번 데이터를 조회한다. 또한, 데이터베이스마다 다른 페..

JPA 2022.06.15

프로젝션 NEW 명령어

바로 밑의 예제는 username, age 두 필드를 프로젝션해서 타입을 지정할 수 없으므로 TypeQuery를 사용할 수 없다. 따라서 Object[]를 반환받았다. List resultList = em.createQuery("SELECT m.username, m.age FROM Member m") .getResultList(); //객체 변환 작업 List userDTOs = new ArrayList(); for (Object[] row : resultList) { UserDTO userDTO = new UserDTO((String)row[0], (Integer)row[1]); userDTOs.add(userDTO); } return userDTOs; public class UserDTO { priv..

JPA 2022.06.14
728x90