본문 바로가기

JPA

(35)
[Spring Data JPA] 구현체 분석 스프링 데이터 JPA 구현체 분석스프링 데이터 JPA가 제공하는 공통 인터페이스의 구현체 org.springframework.data.jpa.repository.support.SimpleJpaRepository@Repository @Transactional(readOnly = true) public class SimpleJpaRepository ...{ @Transactional public S save(S entity) { if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merg..
[Spring Data JPA] WEB 확장 기능, 페이지 1처리 코드 구현 Web 확장 - 도메인 클래스 컨버터HTTP 파라미터로 넘어온 엔티티의 아이디로 엔티티 객체를 찾아서 바인딩  **도메인 클래스 컨버터 사용 전** @RestController@RequiredArgsConstructorpublic class MemberController { private final MemberRepository memberRepository; @GetMapping("/members/{id}") public String findMember(@PathVariable Long id) { Member member = memberRepository.findById(id).get(); return member.getUsername(); } @Po..
[Spring Data JPA] Auditing Auditing엔티티를 생성, 변경할 때 변경한 사람과 시간을 추적하고 싶으면? 등록일수정일등록자수정자순수 JPA 사용하여 등록일, 수정일 적용해보자.@MappedSuperclass@Getterpublic class JpaBaseEntity { @Column(updatable = false) private LocalDateTime createTime; private LocalDateTime updateTime; @PrePersist public void prePersist() { this.createTime = LocalDateTime.now(); this.updateTime = LocalDateTime.now(); } @PreUpdate ..
[Spring Data JPA] 사용자 정의 리포지토리 구현 사용자 정의 리포지토리 구현스프링 데이터 JPA 리포지토리는 인터페이스만 정의하고 구현체는 스프링이 자동 생성을 한다. 스프링 데이터 JPA가 제공하는 인터페이스를 직접 구현하면 상속을 받아야 하니 구현해야 하는 기능이 너무 많다. 다양한 이유로 인터페이스의 메서드를 직접 구현하고 싶다면? JPA 직접 사용('EntityManager')스프링 JDBC Template 사용MyBatis 사용데이터베이스 커넥션 직접 사용 등등...Querydsl 사용1. 사용자 정의 인터페이스 public interface MemberRepositoryCustom { List findMemberCustom();} 2. 사용자 정의 인터페이스 구현 클래스@RequiredArgsConstructorpublic class..
[Spring Data JPA] JPA Hint & Lock JPA HintJPA Hint는 Java Persistence API에서 쿼리 실행 시 추가적인 힌트를 제공하여 동작을 커스터마이즈하거나 성능 최적화를 돕는 기능JPA 쿼리의 동작 방식을 유연하게 제어하거나, 특정 데이터베이스 벤더에 특화된 설정을 추가하는 데 사용된다. (SQL 힌트가 아니라 JPA 구현체에게 제공하는 힌트) 지금까지 JPA Hint의 뜻과 사용 용도를 알아보았고, 이제부터는 사용 방법에 대해서 알아보자. 쿼리 힌트 사용 @QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true")) Member findReadOnlyByUsername(String username); 쿼리 힌트 사용 확인@Testpubli..
[Spring Data JPA] @EntityGraph 엔티티 그래프(Entity Graph)JPA(EntityManager)나 Hibernate에서 제공하는 기능으로, 엔티티를 조회할 때 연관된 엔티티를 어떤 방식으로 가져올지 정의하는 방법이다. 이를 통해 명시적으로 패치 전략(Fetch Strategy)을 설정하고, 필요에 따라 지연 로딩(Lazy Loading)과 즉시 로딩(Eager Loading)을 제어할 수 있다. 엔티티 그래프를 사용하는가?N+1 문제 해결:JPA의 기본 설정에서 연관 엔티티는 지연 로딩(FetchType.LAZY)으로 설정한다.필요 시 연관된 데이터를 쿼리하는데, 다수의 추가 쿼리가 발생해 성능 문제가 생길 수 있다.이를 엔티티 그래프로 해결할 수 있다.JPQL 대체:복잡한 JPQL을 사용하지 않고, 엔티티 그래프를 활용해 간결..
[Spring Data JPA] 벌크성 수정 쿼리 벌크성 쿼리벌크성 쿼리(Bulk Query)란 데이터베이스에서 한 번의 실행으로 대량의 데이터를 삽입, 수정, 삭제하거나 조회하는 쿼리를 의미한다.주로 많은 데이터를 효율적으로 처리하기 위해 사용되며, 데이터 처리 속도를 높이고 시스템 리소스를 절약하는 데 유용하다.예시로 모든 직원의 연봉을 10% 인상하는 쿼리를 짜야 한다면, 직원들을 하나씩 끌어서 10% 씩 인상하는 것보다는 DB에서 업데이트 쿼리를 한번만에 끝내고 커밋하는 것이 효율적일 것이다. 먼저 순수 JPA를 사용하여 벌크성 수정 쿼리를 처리하는 방법을 알아보자. JPA를 사용한 벌크성 수정 쿼리public int bulkAgePlus(int age) { int resultCount = em.createQuery("update Membe..
[Spring Data JPA] 페이징과 정렬 순수 JPA 페이징과 정렬JPA에서 페이징을 어떻게 할 것인가? 페이징과 정렬을 사용하는 예제 코드검색 조건: 나이가 10살정렬 조건: 이름으로 내림차순페이징 조건: 첫 번째 페이지, 페이지당 보여줄 데이터는 3건순수 JPA 페이징 리포지토리 코드public List findByPage(int age, int offset, int limit) { return em.createQuery("select m from Member m where m.age = :age order by m.username desc ", Member.class) .setParameter("age", age) .setFirstResult(offset) ..
[JPA] OSIV와 성능 최적화 OSIV와 성능 최적화 Open Session In View: 하이버네이트Open EntityManager In View: JPA(관례상 둘 다 OSIV라 한다.)OSIV ON  `spring.jpa.open-in-view` : true 기본값  장점이 기본값을 뿌리면서 애플리케이션 시작 시점에 warn 로그를 남기는 것은 이유가 있다.OSIV 전략은 트랜잭션 시작처럼 최초 데이터베이스 커넥션 시작 시점부터 API 응답이 끝날 때 까지 영속성 컨텍스트 와 데이터베이스 커넥션을 유지한다.그래서 지금까지 View Template이나 API 컨트롤러에서 지연 로딩이 가능했던 것이다.지연 로딩은 영속성 컨텍스트가 살아있어야 가능하고, 영속성 컨텍스트는 기본적으로 데이터베이스 커넥션을 유지한다.이것 자체가 큰 장..
[JPA] 컬렉션 조회 최적화 컬렉션인 일대다 관계(OneToMany) 를 조회, 최적화 주문 조회 V1: 엔티티 직접 노출 /** * V1. 엔티티 직접 노출 * - Hibernate5Module 모듈 등록, LAZY=null 처리 * - 양방향 관계 문제 발생 -> @JsonIgnore */@GetMapping("/api/v1/orders")public List ordersV1() { List all = orderRepository.findAllByString(new OrderSearch()); for (Order order : all) { order.getMember().getName(); order.getDelivery().getAddress(); List orderItems =..