ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JPA 개념과 특징
    CS/Spring 2025. 1. 20. 01:50

    SQL Mapper & ORM

    • SQL Mapper와ORM은 개발자가 직접 JDBC Programming을 하지 않도록 기능들을 제공해주는Persistence Framework 종류이다.
    • SQL Mapper:
      • Object와 SQL의 필드을 매핑하여 데이터를 객체화하는 기술.
      • 객체와 테이블간의 관계를 매핑하는 것이 아니라, SQL문을 직접 작성하고 쿼리 수행결과를 어떠한 객체에 매핑하여 줄 지 바인딩하는 방법.
      • 즉 SQL 의존적인 방법이다.
      • ex) JdbcTemplate, Mybatis
      • MyBatis: SQL을 xml파일로 분리하여 관리하고, SQL결과와 객체 인스턴스의 매핑을 도와주는 역할을 수행. 동적쿼리를 지원하여 다이나믹하게 변경되는 쿼리 작성가능.
      단점
      • SQL을 개발자가 직접 작성하는 문제.
      • DBMS에 종속적인 문제.
      • 비슷한 쿼리를 반복적으로 작성해야하는 문제
      • 객체와 관계형 테이블 구조간패러다임 불일치 발생.
    • ORM (Object Relation Mapping):
      • Object와 DB테이블을 매핑하여 데이터를 객체화하는 기술.
      • CRUD 관련 메소드를 사용하면 자동으로 SQL이 만들어져 개발자가 반복적인 SQL을 직접 작성하지 않아도 되고, DBMS에 종속적이지 않다.
      • 또한 복잡한 쿼리의 경우 JPQL을 사용하거나 SQL Mapper를 혼용하여 사용할 수 있다.
      • Java ORM 기술에 대한 인터페이스 표준을 JPA라고 하고, 이를 구현한 가장 대표적인 기술이 Hibernate이다.
      • ex) Hibernate, EclipseLink, DataNucleus
      장점
      • DBMS에 의존하지 않음으로써 도메인과 비즈니스 로직 설계에 더 집중할 수 있는 장점
      • 요구사항 변화에 빠른 대처 가능한 장점
      • 복잡한 통계성 쿼리보다는 실시간 처리용 쿼리에 적합

     

    JPA

    JPA는 자바 진영에서 ORM(Object-Relational Mapping) 기술 표준으로 사용되는 인터페이스의 모음.

    Jpa의 대표적인 구현체로는 Hibernate가 있다.

     

    JPA Entity의 생명 주기

    비영속

    객체만 생성된 상태로, 영속성 컨텍스트에 의해 관리가 되기 전의 상태이다.

     

    영속

    영속성 컨텍스트의 관리 대상인 상태이다.

    persist 메서드를 사용해 영속 상태로 만들 수 있다.

     

    준영속 상태

    영속성 컨텍스트에 의해 관리가 되었다가 분리된 상태이다.

    detatch 메서드를 통해 준영속 상태로 만들 수 있다.

    다시 영속 상태로 만들기 위해서는 Merge 메서드를 사용한다.

     

    삭제

    remove 메서드로 삭제 상태로 전환한다.

    삭제 상태까지는 영속성 컨텍스트의 관리 대상이다.

     

    1차 캐시와 2차 캐시

    • 1차 캐시
      • JPA의 기본 기능으로, 영속성 컨텍스트(Persistence Context) 내부에 존재하는 캐시.
      • 데이터베이스에 접근하지 않고, 영속성 컨텍스트에서 관리 중인 엔티티를 직접 반환
      • 트랜잭션 범위 내에서만 유효.
      • 동일한 EntityManager를 사용하는 동안만 작동.
    • 2차 캐시
      • 애플리케이션 수준에서 동작하며, 여러 EntityManager 간에 공유되는 캐시.
      • 1차 캐시와 달리 EntityManager의 생명 주기와 독립적.
      • 명시적으로 설정해야 활성화.
      • 보통 읽기 전용 엔티티(변경이 적은 데이터)에 적합.
        • 2차 캐시는 기본적으로 데이터베이스와의 동기화를 보장하지 않는다.
        • 즉, 데이터베이스에서 데이터가 변경되더라도 2차 캐시에 반영되지 않을 수 있다.
        • 만약 자주 변경되는 데이터를 2차 캐시에 저장하면, 캐시 데이터와 실제 데이터베이스 데이터 간의 불일치가 발생할 수 있다.
        • 데이터가 변경되면 캐시를 무효화해야 하며, 무효화된 데이터를 다시 캐시에 적재하는 과정에서 성능 비용이 발생
    // 2차 캐시 사용 활성화 예시
    @Entity
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public class Parent {
        @Id @GeneratedValue
        private Long id;
        private String name;
    }

     

    Jpa의 Dirty Checking

    • JPA에서 더티 체킹(dirty checking)이란 영속성 컨테이너가 관리하는 엔티티의 상태를 감지해서, 변경된 부분이 있다면 자동으로 트랜잭션이 끝나는 시점에 데이터베이스에 반영하는 기능
    • 따라서 여기서 말하는 dirty는 “엔티티 데이터의 변경된 부분”을 뜻하며 dirty checking은 변경된 부분을 감지한다는 의미
    • 영속상태의 엔티티만 더티체킹의 대상
    • 더티체킹 과정
      • 엔티티가 처음 영속 상태가 될 때 엔티티의 초기 상태(스냅샷)을 저장
      • commit또는 flush 호출 시 영속성 컨텍스트에 있는 모든 엔티티를 순회
      • 엔티티의 현제 상태와 스냅샷을 비교
      • 변경사항이 발견될 경우 dirty 상태로 표시
      • 트렌젝션이 커밋되면 엔티티의 변경 상태를 db에 반영
    • 장점 : 개발자가 직접 쿼리를 작성하지 않아도, 변경 사항이 자동으로 데이터베이스에 반영
    • 단점 :
      • 스냅샷 비교로 인한 메모리와 CPU 오버헤드 발생
      • 대량 데이터 처리 시 성능 저하 가능

    다음과 같이 setName만 하고 save를 하지 않아도, Transaction이 끝나면 Dirty Checking 때문에 update문이 날라간다.

    @Transactional
    public void update(Long id, String name) {
        Member member = memberRepository.findOne(id);
        member.setName(name);
    }

     

    하지만, name만 변경되었어도 로그를 보면 다른 모든 필드까지 업데이트가 적용된다.

    모든 필드가 아닌 변경할 필드만 업데이트하고싶다면, @DynamicUpdate 어노테이션을 사용한다.

    @Entity
    @Getter @Setter
    @DynamicUpdate //추가
    public class Member {
    
        @Id @GeneratedValue
        @Column(name = "member_id")
        private Long id;
    
        private String name;
    
        @Embedded
        private Address address;
    
        @JsonIgnore
        @OneToMany(mappedBy = "member")
        private List<Order> orders = new ArrayList<>();

     

    Cascade Type

    • Cascade Type은 JPA에서 부모 엔티티의 작업(예: 저장, 삭제 등)을 연관된 자식 엔티티에도 자동으로 전파하도록 설정하는 기능.
    • 부모와 자식 엔티티 간의 연관 관계를 처리할 때, 자식 엔티티에 대해 별도로 처리하는 작업을 줄이기 위해 사용.
    • Cascade를 설정하지 않으면, 부모와 자식의 생명 주기가 맞지 않아서 데이터 정합성이 깨질 수 있음
    • 하지만 무조건 사용한다고 좋은 것은 아님.
    • 하나의 자식에 부모가 여러개 대응되는 경우에는 사용하지 않는 것이 좋음.

    종류

    • CascadeType.PERSIST
      • 부모 엔티티를 저장할 때 연관된 자식 엔티티도 함께 저장.
    • CascadeType.MERGE
      • 부모 엔티티를 병합(merge)할 때 자식 엔티티도 함께 병합.
      • 부모와 자식 엔티티가 분리된 상태에서 다시 병합할 때.
    • CascadeType.REMOVE
      • 부모 엔티티를 삭제(remove)하면 연관된 자식 엔티티도 자동으로 삭제
    • CascadeType.REFRESH
      • 부모 엔티티를 새로고침(refresh)하면 연관된 자식 엔티티도 새로고침
      • 새로고침: 영속성 컨텍스트의 데이터를 DB 상태로 동기화.
    • CascadeType.DETACH
      • 부모 엔티티를 영속성 컨텍스트에서 분리(detach)하면 연관된 자식 엔티티도 함께 분리됩니다.
    • CascadeType.ALL
      • 위에서 설명한 모든 Cascade 동작(PERSIST, MERGE, REMOVE, REFRESH, DETACH)을 적용
      • 부모와 자식이 완전히 동일한 생명 주기를 가지도록 설정할 때 사용합니다.
    // casecade type 설정 예시
    @Entity
    public class Parent {
        @Id @GeneratedValue
        private Long id;
        private String name;
    
        @OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
        private List<Child> children = new ArrayList<>();
    }

    'CS > Spring' 카테고리의 다른 글

    Maven 빌드 과정  (0) 2025.03.31
    Spring JPA가 Auto Configuration(자동 설정) 되는 과정 + Connenction, CP  (1) 2025.02.27
    동시성 제어  (1) 2024.09.30
    spring Batch 5.x (2) - 실습  (1) 2024.09.23
    spring Batch  (0) 2024.09.16
Designed by Tistory.