JVM/JPA 47

리스너

엔티티의 생명주기에 따른 이벤트를 처리하는데 사용된다. 이벤트를 잘 활용하면 대부분의 엔티티에 공통으로 적용하는 등록 일자, 수정 일자 처리와 해당 엔티티를 누가 등록하고 수정했는지에 대한 기록을 리스너 하나로 처리할 수 있다. 이벤트 종류 종류 설명 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

네이티브 SQL

JPQL을 사용할 수 없을 때 SQL을 직접 사용할 수 있는 기능을 네이티브 SQL이라 한다. 네이티브 SQL을 사용하면 엔티티를 조회할 수 있고 JPA가 지원하는 영속성 컨텍스트의 기능을 그대로 사용할 수 있다. 엔티티 조회 실제 데이터베이스 SQL을 사용한다는 것과 위치기반 파라미터만 지원한다는 차이가 있다. 하이버네이트는 이름 기반 파라미터를 지원한다. String sql = "SELECT ID, AGE, NAME, TEAM_ID FROM MEMBER WHERE AGE > ?"; Query nativeQuery = em.createNativeQuery(sql, Member.class).setParameter(1, 20); List resultList = nativeQuery.getResultList..

JVM/JPA 2023.06.30

QueryDSL

build.gradle dependencies { ... // QueryDSL JPA 라이브러리 implementation 'com.querydsl:querydsl-jpa' // QueryDSL 관련된 쿼리 타입(QClass)을 생성할 때 필요한 라이브러리로, annotationProcessor을 사용하여 추가 annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" // java.lang.NoClassDefFoundError(javax.annotation.Entity) 발생 시 추가 annotationProcessor 'jakarta.persistence:..

JVM/JPA 2023.06.28