JPA

· JPA/QueryDSL
querydsl 을 사용하기위해 JPAQueryFactory를 다음과 같이 스프링 빈으로 등록하였다. @Bean JPAQueryFactory jpaQueryFactory(EntityManager em) { return new JPAQueryFactory(em); } 참고 스프링이 주입해주는 엔티티 매니저는 실제 동작 시점에 진짜 엔티티 매니저를 찾아주는 프록시용 가짜 엔티티 매니저이다. 이 가짜 엔티티 매니저는 실제 사용 시점에 트랜잭션 단위로 시ㄹ제 엔티티 매니저를 할당해준다. 따라서 동시성문제는 발생하지 않는다. 1. 기본 설정 1) 조회 최적화 용 DTO를 생성 @Data public class MemberTeamDto { private Long memberId; private String user..
· JPA/QueryDSL
1. 프로젝션 결과 반환 1) 기본 - 대상 하나 List result = queryFactory .select(member.username) .from(member) .fetch(); 2) 튜플 - 대상 둘 이상 List result = queryFactory .select(member.username, member.age) .from(member) .fetch(); 3) DTO조회 - 순수 JPA List result = em.createQuery("select new study.querydsl.dto.MemberDto(m.username,m.age)" + " from Member m", MemberDto.class) .getResultList(); 패키지이름이 지저분함 생성자 방식만 지원 4) qu..
· JPA/QueryDSL
1. JPAQueryFactory EntityManager로 JPAQueryFactory를 생성한다. Querydsl은 JPQL 빌더이다. JPQL: 문자(실행시점 오류), Querydsl:코드(컴파일 시점 오류) JPQL: 파라미터 바인딩 직접, Querydsl: 파라미터 바인딩 자동 처리 querydsl은 JPQL을 작성해주는 도구이다. EntityManager로 JPAQueryFactory를 생성하고, JPAQueryFactory를 이용하여 Querydsl로 JPQL을 생성한다. JPAQueryFactory를 필드로 제공하면 동시성 문제는 어떻게 될까? 스프링 프레임워크는 여러 쓰레드에서 동시에 같은 EntityManager에 접근해도, 트랜잭션 마다 벼도의 영속성 컨텍스트를 제공하기 때문에, 동시..
1. 사용자 정의 레포지토리 스프링 데이터 JPA 레포지토리는 인터페이스만 정의하고 구현체는 스피링이 자동 생성해준다. 스프링 데이터가 JPA가 제공하는 인터페이스를 직접 구현하면 구현해야 하는 기능이 너무 많아진다. 인터페이스의 메서드를 구현해야 하는 상황 JPA 직접 사용 스프링 JDBC Template 사용 마이 바티스 사용 데이터 베이스 커넥션 직접 사용 Querydsl 사용 메서드를 구현하기 위해서는 사용자 정의 인터페이스를 새로 만들어야한다. 1) 인터페이스 public interface MemberRepositoryCustom { List findMemberCustom(); } 2) 구현클래스 @RequiredArgsConstructor public class MemberRepositoryI..
Hint & Lock 쿼리 힌트 기능은 JPA가 제공하는 것이 아니라 하이버네이트가 제공하는 기능이다. 우리는 지금까지 DB에 쿼리를 날리게 되면 2개의 중복된 데이터를 보관하고 있었다. 그 이유는 update 쿼리가 발생 할 수 있으므로, 원본 데이터를 보관해야 하기 때문! 즉 데이터의 변동이 생기면 영속성 컨텍스트에서 원본데이터와 비교한 후 update쿼리가 생성되는 것이다. 반대로 말하면 수정하지 않는 데이터는 원본데이터(스냅샷)을 저장하고 있을 필요가 없다. 이 경우 하이버네이트에서는 JPA구현체에게 힌트를 제공하여 중복 데이터 문제를 해결 할 수 있다. 1. 쿼리 힌트 @QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value =..
쿼리 메서드 기능 지금부터는 더 복잡한 JPA 메서드들을 구현해보고 스프링 데이터 JPA로 바꿔보겠다. 1. 메서드 이름으로 쿼리 생성 이름과 나이를 기준으로 회원을 조회 1) 순수 JPA public List findByUsernameAndAgeGreaterThan(String username, int age){ return em.createQuery("select m from Member m where m.username = :username and m.age > :age") .setParameter("username", username) .setParameter("age", age) .getResultList(); } 순수 JPA를 사용하면 이러한 메서드를 작성해야 한다. 하지만 데이터 JPA를 사..
JPA와 스프링 데이터 JPA 스프링 데이터 JPA는 JPA를 더 효율적으로 사용하기 위한 기술이다. 데이터 JPA는 매우 유용한 기능들을 많이 제공해 주지만, JPA를 활용하는 기술이기 때문에 JPA 동작원리를 알고 있어야 한다. 데이터 JPA가 만능인것은 아니다. 동적 쿼리는 QueryDSL을 이용해야함. 1. JPA 레포지토리 다음은 JPA를 이용한 Member레포지토리이다. @Repository public class MemberJpaRepository { @PersistenceContext private EntityManager em; public Member save(Member member){ em.persist(member); return member; } public void delete..
1. OSIV JPA에서 EntityManager가 하이버네이트 에서는 Session이라고 한다. 여기서 말하는 Session이란 사용자의 데이터를 저장해주는 곳이 아니다. 따라서 OSIV(Open Session In View) 는 하이버네이트, OEIV(Open EntityManager In View) 는 JPA에서 사용된다. OSIV는 말 그대로 영속성 컨텍스트를 뷰 까지 열어두는 기능이다. Spring.jpa.open-in.view는 기본값이 True이다. 1)True 해당 값을 True로 하게 되면 트랜젝션 시작 시점에 DB와 커넥션을 맺는 영속성 컨텍스트가 생성되고 API응답이 끝날 때까지 영속성 컨텍스트와 DB커넥션을 유지한다. 따라서 지금까지 View Template이나 API Control..
V1. 엔티티 직접 노출 엔티티가 변하면 API 스펙이 변한다. 트랜잭션 안에서 지연 로딩 필요(1 + N Query) 양방향 연관관계 문제 V2. 엔티티를 조회해서 DTO로 변환(fetch join 사용X) 트랜잭션 안에서 지연 로딩 필요(1 + N Query) V3. 엔티티를 조회해서 DTO로 변환(fetch join 사용O) 페이징 시에는 N 부분을 포기해야함(대신에 batch fetch size? 옵션 주면 N -> 1 쿼리로 변경 가능) V4. JPA에서 DTO로 바로 조회, 컬렉션 N 조회 (1 + N Query) 페이징 가능 V5. JPA에서 DTO로 바로 조회, 컬렉션 1 조회 최적화 버전 (1 + 1 Query) 페이징 가능 V6. JPA에서 DTO로 바로 조회, 플랫 데이터 (1 Que..
1. 컬렉션 조회 - 플랫 데이터 최적화 V5는 괜찮게 최적화 되었지만 여전히 쿼리가 2번 나간다. 이를 1번만 나가게 하는 방법을 알아보겠다. 방법은 간단하다. 필요한 모든 데이터를 담은 DTO를 새로 만들고, 해당 데이터를 모두 가져와서 우리가 원래 반환 하려는 DTO로 변환해주면 된다. 1. DTO 생성 컬렉션 필드의 값을 채워 넣는 과정을 없애기 위해서 새로운 DTO가 필요하다. @Data public class OrderFlatDto { private Long orderId; private String name; private LocalDateTime orderDate; private OrderStatus orderStatus; private Address address; // 컬렉션 필드 대신..
코드 미식가
'JPA' 카테고리의 글 목록