JPA

star_pooh·2025년 1월 2일
0

TIL

목록 보기
38/39
post-thumbnail

객체와 관계형 데이터베이스(RDB)의 패러다임 불일치

  • 상속
    • DB에는 상속 관계가 없음
    • 각각의 객체별로 데이터를 저장해야하고, JOIN을 사용해서 데이터를 조회해야 함
    • 데이터를 저장하고 조회하기 까다롭기 때문에 DB에 저장할 객체는 상속 관계를 사용하지 않음
  • 연관관계
    • DB는 외래키를 사용하여 표현
    • 객체는 참조를 사용하여 표현
// 데이터베이스 중심 객체 설계
public class Tutor {
		private Long id; // PK
		private Long companyId; // FK
		private String name;
}

public class Company {
		private Long id; // PK
		private String name;
}
// 객체 중심 설계
public class Tutor {
		private Long id; // PK
		private Company company; // 참조 연관관계
		private String name;
		
		public Company getCompany() {
				return company;
		}
		
		public Company setCompany(Company company) {
				this.company = company;
		}
}

public Company {
		private Long id; // PK
		private String name;
}
SELECT p.*, c.* FROM product p JOIN category c ON p.category_id = c.id;
product.getCategory(); // 가능
product.getOrder(); // 불가능
  • 객체 그래프
    • 객체는 연관된 객체를 탐색할 수 있어야 하지만, 실행된 SQL만큼만 탐색 가능해짐
      • Entity의 신뢰성에 문제 발생
    • 연관 객체를 한꺼번에 조회하면 신뢰성은 생기지만,
      • SQL 쿼리가 무거워짐
      • 진정한 의미의 계층 분할이 어려움
      • 필요 없는 데이터도 항상 함께 조회
Product product1 = productRepository.findById(productId);
Product product2 = productRepository.findById(productId);

product1 == product2; // false
  • 객체의 비교
    • 데이터는 같지만, 새로운 인스턴스이기 때문에 주소값이 다름
    • Collection에 저장하면 문제를 해결할 수 있음

JPA

객체 지향 프로그래밍 언어인 Java와 관계형 데이터베이스 간의 패러다임 불일치 문제를 해결하여 데이터베이스 작업을 객체 지향적으로 수행할 수 있도록 지원. 대표적으로 Hibernate를 사용.

ORM(Object-Relational Mapping)

  • 객체와 관계형 DB를 자동으로 매핑하여 패러다임 불일치 문제를 해결
  • 개발자 대신 데이터베이스와 상호작용하는 역할을 수행

JPA를 사용하는 이유

  • 생산성
  • 유지보수성
  • 패러다임 불일치 문제 해결
    • SQL 중심적인 개발에서 객체 중심으로 개발하기 때문에
  • 성능 향상
    • 1차 캐시
    • 쓰기 지연
    • 지연 로딩
    • 즉시 로딩

영속성 컨텍스트

Entity 객체를 영속성 상태로 관리하는 일종의 캐시 역할을 하는 공간으로 여기에 저장된 Entity는 데이터베이스와 자동으로 동기화되며, 같은 트랜잭션 내에서는 동일한 객체가 유지됨.

Entity

  • 데이터베이스에서 엔티티란 저장할 수 있는 데이터의 집합을 의미
  • JPA에서 엔티티란 데이터베이스의 테이블을 나타내는 클래스를 의미

Entity 생명주기

Entity 상태

  • 비영속(new/transient)
    • 영속성 컨텍스트가 모르는 새로운 상태
    • 데이터베이스와 전혀 연관이 없는 객체
  • 영속(managed)
    • 영속성 컨텍스트에 저장되고 관리되고 있는 상태
    • 데이터베이스와 동기화되는 상태
  • 준영속(detached)
    • 영속성 컨텍스트에 저장되었다가 분리되어 더 이상 기억하지 않는 상태
    • 영속성 컨텍스트가 제공하는 기능을 사용하지 못함
  • 삭제(removed)
    • 영속성 컨텍스트에 의해 삭제로 표시된 상태
    • 트랜잭션이 끝나면 데이터베이스에서 제거

1차 캐시

  • 엔티티를 영속성 컨텍스트에 저장할 때 생성되는 메모리 내 캐시
  • 엔티티는 1차 캐시에 먼저 저장
    • 이후 같은 엔티티를 요청하면 DB를 조회하지 않음
    • 1차 캐시에서 데이터를 반환하여 성능을 높임
  • 동일한 트랜잭션 안에서만 사용 가능
  • 트랜잭션이 종료되면 영속성 컨텍스트는 삭제됨
  • 새로운 엔티티를 영속시키면 1차 캐시에 저장됨
  • id가 1번인 엔티티를 조회하면, DB가 아닌 1차 캐시에서 데이터를 반환함
  • id가 2번인 엔티티를 조회하면, 1차 캐시에 해당 데이터가 없으므로
  • DB를 조회하고, 1차 캐시에 저장한 후 데이터를 반환함

동일성 보장

  • 동일한 트랜잭션 안에서 특정 엔티티를 여러 번 조회해도 항상 같은 객체 인스턴스를 반환
  • 1차 캐시를 사용하여 동일한 객체를 참조하게 하기 때문에 일관성 유지 가능

쓰기 지연

  • 동일한 트랜잭션 내에서 생성된 SQL들을 Commit 시점에 한꺼번에 반영

변경 감지(Dirty Checking)

  • 영속성 컨텍스트가 엔티티의 초기 상태를 저장하고 커밋 시점에 현재 상태와 비교하여 변경 사항이 있는지 확인하는 기능
  • DB에서 조회한 데이터에 대해 스냅샷(snapshot) 저장
  • 커밋 시점에 엔티티와 스냅샷을 비교
  • 변경 사항이 있다면 UPDATE 쿼리문을 생성하여 반영

flush

  • 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 기능
  • 변경된 엔티티 정보를 SQL로 변환해 데이터베이스에 동기화함
  • 트랜잭션 커밋 시 자동으로 실행되지만, 특정 시점에 데이터베이스 반영이 필요하다면 수동으로 호출도 가능

0개의 댓글

관련 채용 정보