[SPRING] JPA

라미·2024년 2월 25일

spring

목록 보기
8/17
post-thumbnail

JPA (Java Persistence API)

ORM(Object-relational mapping)

  • 객체 관계 매핑 : 객체는 객체대로 설계, 관계형 데이터베이스는 광계형 데이터 베이스대로 설계 이것을 ORM 프레임워크가 중간엣 ㅓ매핑해주는 것을 뜻한다
  • ORM은 객체와 RDB 두 기둥 위에 있는 기술이다.

JPA

  • 자바 ORM(Object Relational Mapping) 기준 표준, 인터페이스의 모음.
  • 실제로 동작은 하지 않는다.
  • JPA 인터페이스를 구현한 대표적인 오픈소스가 Hibernate이다.

JPA 동작 과정

  • JPA는 애플리케이션과 JDBC 사이에서 동작.
  • 개발자가 JPA를 사용하면, JPA 내부에서 JDBC API를 사용하여 SQL을 호출하고 DB와 통신을 한다
  • 개발자가 직접 JDBC API를 쓰는 것이 아니다.
한줄정의 개발자 대신 JDBC를 사용하여 DB와 소통하는 친구! 나 대신 SQL을 작성하고 매핑해준다!
@Entity // JPA가 관리할 수 있는 Entity 클래스 지정 @Entitey(name ="관리할클래스명") default 어노테이션 달린 클래스
@Table(name = "memo") // 매핑할 테이블의 이름을 지정, default class 명으로 잡힘
public class Memo {
    @Id // pk 키 지정, 없으면 error 발생함
    @GeneratedValue(strategy = GenerationType.IDENTITY) //auto_increment 옵션
    private Long id;

    // name : 테이블 속성명 default 필드 이름과 동일하게 잡힘
    // nullable: null 허용 여부
    // unique: 중복 허용 여부 (false 일때 중복 허용)
    @Column(name = "username", nullable = false, unique = true)
    private String username;

    // length: 컬럼 길이 지정, default : 255
    @Column(name = "contents", nullable = false, length = 500)
    private String contents;
}

영속성 컨텍스트란?

영속성 컨텍스트는 Entity 객체를 효율적으로 관리하기 위해 만들어진 공간

EntityManagerFactory와 EntityManager

EntityManagerFactory

  • 일반적으로 DB 하나에 하나만 생성되어 애플리케이션이 동작하는 동안 사용된다.
  • EntityManagerFactory를 만들기 위해서는 DB에 대한 정보를 전달해야한다.(/resources/META-INF/presistence.xml 파일, db connection 정보와 entity class 정보 등등)

EntityManager

  • EntityManager를 통해 생성하여 사용할 수 있다.
  • 영속성 컨텍스트에 접근하여 Entity객체들을 조작하기 위해 필요한 친구!
  • 실제 Transaction 단위를 수행할 때마다 생성한다.
  • Transaction 수행 후에는 반드시 EntityManager 를 닫는다. -> 그래야 내부적으로 DB Connection을 반환한다.
// EntityManagerFactory 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("memo"); 
// EntityManager 생성
EntityManager em = emf.createEntityManager();
// EntityManager 사용후 종료 꼭!
em.close();
// EntityManagerFactory 사용 후 종료 꼭!
emf.close();

JPA 트랜잭선

DB 트랜잭션과 동일하게 동작한다. 변경이 발생한 객체들의 정보를 쓰기 지연 저장소에 전부 가지고 있다가 마지막에 SQL을 한번에 DB에 요청해 변경을 반영한다.
-> DB에서 실제 커밋을 했을때만 커밋이 되는것과 같이 얘도 커밋이 일어나야지만 DB에 모아둔 녀석들을 전달해준다!!! 동일하게 동작한다!!!

// EntityManager 에서 EntityTransaction 가져오기
EntityTransaction et = em.getTransaction();
tx.begin(); // transaction 시작
tx.commit(); // transaction 수행
tx.rollback(); //작업에 문제가 생겼을 시 

영속성 컨텍스트

영속성 컨텍스트는 내부적으로 캐시 저장소를 가지고 있다.

  • 캐시 저장소는 Map 자료구조로 key:value 형태로 저장된다.
  • Key : PK(기본 키 저장) / value : Entity 클래스의 객체를 저장(필드 값들~~)

1차 캐시

  1. 1차 캐시
    1차 캐시에 Entity 가 있을 때의 이점
    entityManager.find() 를 하면 DB보다 먼저, 1차 캐시를 조회한다.
    1차 캐시에 해당 Entity가 존재하면 바로 반환한다.
    Q. 1차 캐시에 조회하고자하는 Entity가 없다면?
    1) DB에서 조회 한다.
    2) 해당 Entity를 DB에서 꺼내와 1차 캐시에 저장한다.
    3) Entity를 반환한다.
    이후에 다시 해당 Entity를 조회하면 1차 캐시에 있는 Entity를 반환한다.
저장

em.persist(entity);:Entity를 영속성 컨텍스트에 저장하는 것. EntityManager를 통해 영속성 컨텍스트에 접근한다!

조회

em.find(entity.class, pkkey);

객체 동일성 보장

Memo memo1 = em.find(Memo.class, 1);
Memo memo2 = em.find(Memo.class, 1);
System.out.println(memo1 == memo2); // true
  • 영속 Entity의 동일성을 보장한다!
  • 동일한 pk에 해당하는 Entity를 2번 조회하면 1차 캐시에 의해 같은 reference로 인식되어 하나의 transaction 안에서 같은 Entity 비교시 true 이다.
  • DB 조회 횟수를 줄인다. 한번 1차캐시에 저장된 값은 1차 캐시에서 가져온다!(db에서 또다시 조회 x)
삭제

em.remove(entity)

  • 삭제할 Entity 조회 후 캐시 저장소에 없으면 db에서 조회 후 저장.
    em.remove(entity); 호출 시 삭제할 Entity를 DELETED 상태로 만든 후 트랜잭션 commit 후 Delete SQL이 DB에 요청됩니다. (db에 insert와 delet sql 두번의 요청)

  • 삭제할 Entity 조회 후 캐시 저장소에 있다면?
    em.remove(entity); 호출 되면서 Entity를 DELETED 상태로 만든 후 트랜잭션 commit 후 Delete SQL이 DB에 요청됩니다.(db에 delete sql 한번 요청)

영속성 컨텍스트의 이점

쓰기지연저장소

JPA를 사용하여 데이터를 변경하고 싶다면
1. 해당 데이터를 조회해온다
2. 해당 데이터를 수정한다.
3. COMMIT이 되고 flush() 가 호출되면 최초데이터(LoadedState)와 Entity의 현재 상태를 비교한다
4. 쓰기 지연 저장소에 update sql을 저장한다.
5. 트랜잭션이 commit 되면서 반영된다
(주의사항 수정,삭제,변경 등이 있다면 꼭 트랜잭션 환경에서 실행해야 한다!)
-> 이러한 과정을 변경감지 or Dirty Checking 이라 한다.

0개의 댓글