JVM 80

영속성 컨텍스트와 프록시

영속 엔티티의 동일성 보장 해당 코드에 refMember와 findMember는 모두 프록시 객체로 같은 인스턴스이다. 이는 영속 엔티티의 동일성을 보장하기 위함이다. 반대로 엔티티를 먼저 조회후 프록시를 조회하면 모두 엔티티이다. @Test void 영속성컨텍스트와_프록시() { Member member = new Member("member1", "회원1"); em.persist(member); em.flush(); em.clear(); Member refMember = em.getReference(Member.class, "member1"); Member findMember = em.find(Member.class, "member1"); Assertions.assertSame(refMember, fi..

JVM/JPA 2023.07.03

JPA 예외 처리

JPQ 표준 예외 javax.persistence.PersistenceException의 자식 클래스다. 그리고 이 예외 클래스는 RuntimeException의 자식이다. 트랜잭션 롤백을 표시하는 예외는 심각한 예외이므로 복구해선 안 된다. 이 예외가 발생하면 트랜잭션을 강제로 커밋해도 트랜잭션이 커밋되지 않고 대신에 javax.persistence.RollbackException 예외가 발생한다. 트랜잭션 롤백을 표시하지 않는 예외는 심각한 예외가 아니다. 따라서 개발자가 트랜잭션을 커밋할지 롤백할지를 판단하면 된다. 트랜잭션 롤백을 표시하는 예외 트랜잭션 롤백을 표시하는 예외 설명 EntityExistsException 저장 중에 이미 같은 엔티티가 있으면 발생 EntityNotFoundExcept..

JVM/JPA 2023.07.03

엔티티 그래프

엔티티를 조회할 때 연관된 엔티티를 함께 조회할 필요가 있으면 JPQL의 페치 조인을 사용한다. 그런데 페치 조인을 사용하면 같은 JPQL을 중복해서 작성하는 경우가 많다. 이는 JPQL이 엔티티를 조회할 뿐 아니라 연관된 엔티티를 함께 조회하는 기능도 제공하기 때문이다. JPA 2.1에 추가된 엔티티 그래프 기능을 사용하면 엔티티를 조회하는 시점에 함께 조회할 연관된 엔티티를 선택할 수 있다. 따라서 JPQL은 데이터를 조회하는 기능만 수행하면 되고 연관된 엔티티를 함께 조회하는 기능은 엔티티 그래프를 사용하면 된다. 그러므로 엔티티 그래프 기능을 적용하면 다음 JPQL만 사용하면 된다. SELECT o FROM Order o WHERE o.status = ? Named 엔티티 그래프 @NamedEnt..

JVM/JPA 2023.07.03

리스너

엔티티의 생명주기에 따른 이벤트를 처리하는데 사용된다. 이벤트를 잘 활용하면 대부분의 엔티티에 공통으로 적용하는 등록 일자, 수정 일자 처리와 해당 엔티티를 누가 등록하고 수정했는지에 대한 기록을 리스너 하나로 처리할 수 있다. 이벤트 종류 종류 설명 PostLoad 엔티티가 영속성 컨텍스트에 조회된 직후 또는 refresh를 호출한 후 (2차 캐시에 저장되어 있어도 호출된다.) PrePersist persist 메소드를 호출해서 엔티티를 영속성 컨텍스트에 관리하기 직전에 호출된다. 식별자 생성 전략을 사용한 경우 엔티티에 식별자는 아직 존재하지 않는다. 새로운 인스턴스를 merge할 때도 수행된다. PreUpdate flush나 commit을 호출해서 엔티티를 데이터베이스에 수정하기 직전에 호출된다. ..

JVM/JPA 2023.07.02

@Converter

객체 필드로 Boolean을 사용하고 데이터베이스에서는 Y, N으로 저장하고 싶을 때 사용한다. // 클래스 또는 필드 한곳에 지정 @Entity @Convert(converter=BooleanToYNConverter.class, attributeName = "vip") public class Member { @Id private String id; @Convert(converter=BooleanToYNConverter.class) private boolean vip; } @Converter public class BooleanToYNConverter implements AttributeConverter { @Override public String convertToDatabaseColumn(Boolea..

JVM/JPA 2023.07.02

컬렉션

하이버네이트는 컬렉션을 효율적으로 관리하기 위해 엔티티를 영속 상태로 만들 때 원본 컬렉션을 감싸고 있는 내장 컬렉션을 생성해서 이 내장 컬렉션을 사용하도록 참조를 변경한다. 하이버네이트가 제공하는 내장 컬렉션(org.hibernate.collection.internal.PersistentBag)은 원본 컬렉션을 감싸고 있어서 래퍼 컬렉션으로도 부른다. 하이버네이트는 이런 특징 때문에 컬렉션을 사용할 때 다음처럼 즉시 초기화해서 사용하는 것을 권장한다. Collection members = new ArrayList(); 하이버네이트 내장 컬렉션과 특징 컬렉션 인터페이스 내장 컬렉션 중복 허용 순서 보관 Collection, List PersistentBag O X Set PersistentSet X X ..

JVM/JPA 2023.07.02

스프링 데이터 JPA와 QueryDSL 통합

QueryDslPredicateExecutor QueryDSL을 검색조건으로 사용하면서 스프링 데이터 JPA가 제공하는 페이징과 정렬 기능도 함께 사용할 수 있다. 하지만 join, fetch를 사용할 수 없다. // 상속 public interface ItemRepository extends JpaRepository, QueryDslPredicateExecutor{} // 사용 QMember member = QMember.member; Iterable result = memberRepository.findAll( member.name.contains("김").and(member.age.between(10, 20)) ); public interface QuerydslPredicateExecutor { O..

JVM/JPA 2023.07.02

스프링 데이터 JPA

소개 단순 CRUD를 처리하기 위하여 데이터 접근 계층을 개발할 때 구현 클래스 없이 인터페이스만 작성하면 실행 시점에 스프링 데이터 JPA가 구현 객체를 동적으로 생성해서 주입해준다. 스프링 데이터 JPA는 스프링 데이터 프로젝트의 하위 프로젝트로 JPA에 특화된 기능을 제공한다. 스캔 범위 설정 @EnableJpaRepositories 어노테이션으로 범위를 지정해 줄 수 있으며 없을 시에는 @SpringBootApplication에서 설정한 빈 스캔 범위에서 스캔한다. @Configuration @EnableJpaRepositories(basePackages = "jpaboo.jpashop.repository") public class AppConfig {} JPARepository 주요 메소드 메소..

JVM/JPA 2023.07.02

객체지향 쿼리 심화

벌크 연산 벌크 연산은 수정, 삭제 모두 executeUpdate()를 사용한다. 이 메소드의 반환값은 영향을 받은 엔티티 건수이다. 벌크 연산은 2차 캐시와 영속성 컨텍스트를 무시하고 데이터베이스 직접 쿼리한다는 점에 주의해야한다. em.refesh(entity) 벌크 연산을 수행한 직후에 정확한 상품A 엔티티를 사용해야 한다면 em.refresh()를 사용해서 데이터베이스에서 상품A를 다시 조회하면 된다. 벌크 연산 먼저 실행 가장 실용적인 해결책은 벌크 연산을 가장 먼저 실행하는 것이다. 예를 들어 위에서 벌크 연산을 먼저 실행하고 나서 상품 A를 조회하면 벌크 연산으로 이미 변경된 상품 A를 조회하게 된다. 이 방법은 JPA와 JDBC를 함께 사용할 때도 유용하다. 벌크 연산 수행 후 영속성 컨텍..

JVM/JPA 2023.06.30