연관관계 매핑 기초

Goals

  1. 객체와 테이블 연관관계의 차이를 이해
  2. 객체의 참조와 테이블의 외래 키를 매핑
  • 용어
    • 방향 : 단방향, 양방향
    • 다중성 : 다대일 , 일대다, 일대일, 다대다 이해
    • 연관관계의 주인 : 객체 양방향 연관관계는 관리 주인이 필요

연관관계가 필요한 이유

객체지향 설계의 목표는 자율적인 객체들의 협력 공동체를 만드는 것이다.


예제 시나리오

  • 회원과 팀이 있다.
  • 회원은 하나의 팀에만 소속될 수 있다.
  • 회원과 팀은 다대일 관계다.

객체를 테이블에 맞추어 모델링

  • 연관관계가 없는 객체

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21696?category=questionDetail&tab=curriculum&q=340623

객체를 테이블에 맞추어 모델링

  • 참조 대신에 외래 키를 그대로 사용
@Entity
 public class Member { 

    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String name;

    @Column(name = "TEAM_ID")
    private Long teamId; 

	 … 
 } 
 @Entity
 public class Team {
	 
    @Id @GeneratedValue
    @Column(name = "TEAM_ID")
    private Long id;

    private String name; 
 …
}

객체를 테이블에 맞추어 모델링

  • 외래 키 식별자를 직접 다룸
//팀 저장
 Team team = new Team();
 team.setName("TeamA");
 em.persist(team);
 //회원 저장
 Member member = new Member();
 member.setName("member1");
 member.setTeamId(team.getId());
 em.persist(member)

객체를 테이블에 맞추어 모델링

  • 식별자로 다시 조회, 객체 지향적인 방법이 아님!!
//조회
 Member findMember = em.find(Member.class, member.getId()); 
 //연관관계가 없음
 Team findTeam = em.find(Team.class, team.getId());

객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력 관계를 만들 수 없다.

  • 테이블은 외래 키로 조인을 사용해서 테이블을 찾는다.
  • 객체는 참조를 사용해서 연관된 객체를 찾는다.
  • 테이블과 객체 사이에는 이런 큰 간격이 있다.

단방향 연관관계

객체 지향 모델링

객체 연관관계 사용

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21696?category=questionDetail&tab=curriculum&q=340623


객체의 참조와 테이블의 외래 키를 매핑

@Entity
 public class Member { 

	 @Id @GeneratedValue
	 private Long id;

	 @Column(name = "USERNAME")
	 private String name;

	 private int age;

// @Column(name = "TEAM_ID")
// private Long teamId;

	 @ManyToOne
	 @JoinColumn(name = "TEAM_ID")
	 private Team team;
 …

ORM 매핑

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21696?category=questionDetail&tab=curriculum&q=340623


연관관계 저장

//팀 저장
 Team team = new Team();
 team.setName("TeamA");
 em.persist(team);
 //회원 저장
 Member member = new Member();
 member.setName("member1");
 member.setTeam(team); //단방향 연관관계 설정, 참조 저장
 em.persist(member);

참조로 연관관계 조회 - 객체 그래프 탐색

//조회
 Member findMember = em.find(Member.class, member.getId()); 
//참조를 사용해서 연관관계 조회
 Team findTeam = findMember.getTeam()

연관관계 수정

// 새로운 팀B
 Team teamB = new Team();
 teamB.setName("TeamB");
 em.persist(teamB);
 // 회원1에 새로운 팀B 설정
 member.setTeam(teamB);

'DB > JPA' 카테고리의 다른 글

실전 예제 - 요구사항 분석과 기본 매핑  (0) 2023.01.04
기본 키 매핑  (0) 2023.01.03
필드와 컬럼 매핑  (0) 2022.12.31
데이터 베이스 스키마 자동생성  (0) 2022.12.30
객체와 테이블 매핑  (0) 2022.12.30

요구사항 분석

  • 회원은 상품을 주문할 수 있다.
  • 주문 시 여러 종류의 상품을 선택할 수 있다.

기능

  • 회원 기능
    • 회원 등록
    • 회원 조회
  • 상품 기능
    • 상품 등록
    • 상품 수정
    • 상품 조회
  • 주문 기능
    • 상품 주문
    • 주문 내역 조회
    • 주문 취소

도메인 모델 분석

  • 회원과 주문의 관계 : 회원은 여러 번 주문할 수 있다.(일대다)
  • 주문과 상품의 관계 : 주문할 때 여러 상품을 선택할 수 있다. 반대로 같은 상품도 여러번 주문될 수 있다. 주문상품 이라는 모델을 만들어서 다대다 관계를 일대다, 다대일 관계로 풀어냄

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21695

테이블 설계

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21695

엔티티 설계

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21695

데이터 중심 설계의 문제점

  • 현재 방식은 객체 설계를 테이블 설계에 맞춘 방식
  • 테이블의 외래키를 객체에 그대로 가져옴
    • 참조 값을 가져와야하는데....
  • 객체 그래프 탐색이 불가능
  • 참조가 없으므로 UML도 잘못됨
    • id만 가지고 있고 참조가 끊기는 상황임
연관 관계 매핑이 필요..!!

'DB > JPA' 카테고리의 다른 글

단방향 연관관계  (0) 2023.01.04
기본 키 매핑  (0) 2023.01.03
필드와 컬럼 매핑  (0) 2022.12.31
데이터 베이스 스키마 자동생성  (0) 2022.12.30
객체와 테이블 매핑  (0) 2022.12.30

기본 키 매핑

기본 키 매핑 어노테이션

  • @Id
  • @GeneratedValue
@Id @generatedValue(strategy = GenerationType.AUTO)
private Long id;

기본 키 매핑 방법

  • 직접 할당
    • @Id만 사용
  • 자동 생성
    • @GeneratedValue
      • IDENTITY
        • 데이터베이스에 위임, MYSQL
      • SEQUENCE
        • 데이터베이스 시퀀스 오브젝트 사용, ORACLE
          • @SequenceGenerator 필요
      • TABLE
        • 키 생성용 테이블 사용, 모든 DB에서 사용
          • @TableGenerator 필요
      • AUTO
        • 방언에 따라 자동 지정, 기본값

IDENTITY 전략 - 특징

  • 기본 키 생성을 데이터베이스에 위임
  • 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용
    • MySQL의 AUTO_INCREMENT
  • JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행
  • AUTO_INCREMENT는 데이터베이스에 INSERT SQL을 실행 한 이후에 ID값을 알 수 있다.
    • 그런데 영속성 컨텍스트에서 관리되려면 PK값이 존재해야만 한다.
  • IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL 실행하고 DB에서 식별자를 조회
    • 원래는 commit시점에 쿼리가 보내지게 됐었지만 예외상황임
    • 모아서 처리할 수 있는 장점이 사라지게 된다.

IDENTITY 전략 - 매핑

@Entity
public class Member{
	@ID
	@GeneratedValue(Strategy = GenerationType.IDENTITY)
	private Long id;

SEQUENCE 전략 - 특징

  • 데이터베이스 시퀀스를 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트
    • 오라클 시퀀스
  • 오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용

SEQUENCE 전략 - 매핑

@Entity 
@SequenceGenerator( 
 name = “MEMBER_SEQ_GENERATOR", 
 sequenceName = “MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
 initialValue = 1, allocationSize = 1) 
public class Member { 
 @Id 
 @GeneratedValue(strategy = GenerationType.SEQUENCE, 
 generator = "MEMBER_SEQ_GENERATOR") 
 private Long id;

SEQUENCE - @SequenceGenerator

  • 테이블 마다 시퀀스를 따로 관리하고 싶을때 사용
  • 주의 : allocationSize 기본값 = 50
속성 설명 기본값
name 식별자 생성기 이름 필수
sequenceName 데이터베이스에 등록되어 있는 시퀀스 이름 hibernate_sequence
initialValue DDL 생성 시에만 사용됨, DDL을 생성할 때 처음 시작하는 수를 지정한다. 1
allocationSize 시퀀스 한번 호출에 증가하는 수( 성능 최적화에 사용됨) 50
catalog, schema    

SEQUENCE 전략과 최적화

  • DB에 가봐야 SEQUENCE 값을 알 수 있다.
    • SEQUENCE는 DB가 관리하기 때문에 당연
  • 영속성 컨텍스트에 들어가려면 PK가 있어야한다.
  • 다음값을 얻어서 id변수에 값을 넣는다.
  • 실제 insert가 바로 날아가지는 않는다.(IDENTITY와 차이)
    • 버퍼링 처리가 가능해진다.
  • 그렇게 되면 성능저하가 고민 된다…
    • 미리 N개의 사이즈를 가져온다.
    • 메모리에서는 1씩 올려주는 방식을 사용
    • 동시성 이슈없이 해결가능하다.

TABLE 전략

  • 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
  • 장점 : 모든 데이터베이스에 적용 가능
  • 단점 : 성능

TABLE 전략 - 매핑

create table MY_SEQUENCES ( 
 sequence_name varchar(255) not null, 
 next_val bigint, 
 primary key ( sequence_name )
)
@Entity 
@TableGenerator( 
 name = "MEMBER_SEQ_GENERATOR", 
 table = "MY_SEQUENCES", 
 pkColumnValue = “MEMBER_SEQ", allocationSize = 1) 
public class Member { 
 @Id 
 @GeneratedValue(strategy = GenerationType.TABLE, 
 generator = "MEMBER_SEQ_GENERATOR") 
 private Long id;
}
  • 잘 사용하지는 않는다!

권장하는 식별자 전략

  • 기본 키 제약 조건 : null이 아님, 유일, 변하면 안됨
  • 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자
    • 자연키 = 주민등록번호, 전화번호 등등
    • 대리키 = 비즈니스와 전혀 상관없는 키
  • 예를들어 주민등록번호도 기본키로 적절하지 않다.
  • 권장 : Long형 + 대체키 + 키 생성전략 사용

'DB > JPA' 카테고리의 다른 글

단방향 연관관계  (0) 2023.01.04
실전 예제 - 요구사항 분석과 기본 매핑  (0) 2023.01.04
필드와 컬럼 매핑  (0) 2022.12.31
데이터 베이스 스키마 자동생성  (0) 2022.12.30
객체와 테이블 매핑  (0) 2022.12.30

필드와 컬럼 매핑

요구사항

  • 회원은 일반 회원과 관리자로 구분
  • 회원 가입일, 수정일 필요
  • 회원을 설명할 수 있는 필드가 있어야하고 길이 제한이 없어야한다.
package hellojpa;

public enum RoleType {
    USER, ADMIN
}
package hellojpa;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@Entity
public class Member {
    @Id
    private Long id;

    @Column(name = "name") //실제 DB 컬럼명
    private String username;

    private Integer age;

    @Enumerated(EnumType.STRING)
    private RoleType roleType;

    @Temporal(TemporalType.TIMESTAMP)
    //생성일
    private Date createdDate;

    @Temporal(TemporalType.TIMESTAMP)
    //수정일
    private Date lastModifiedDate;

    @Lob
    private String description;

}

 

콘솔 화면


매핑 어노테이션

hibernate.hbm2ddl.auto

어노테이션 설명

@Column 컬럼 매핑
@Temporal 날짜 타입 매핑
@Enumerated enum 타입 매핑
@Lob BLOB, CLOB 매핑
@Transient 특정 필드를 컬럼에 매핑하지 않음(매핑 무시)


@Column

속성 설명 기본값
name 필드와 매핑할 테이블의 컬럼 이름 객체의 필드 이름
insertable,
updatable
등록, 변경 가능 여부 true
nullable(DDL) null 값의 허용 여부를 설정한다.
false -> DDL 생성 시에 NOT NULL 제약조건 이 붙는다.
 
unique(DDL) @Table의 uniqueConstraints와 같지만,
한 컬럼에 간단히 유니크 제약 조건을 걸 때 사용
 
columnDefinition(DDL) 필드의 자바 타입, 방언 정보를 활용하여
데이터 베이스 컬럼 정보를 직접 줄 수 있다.
 
length(DDL) 문자 길이 제약 조건, String 에만 사용 255
precision, scale(DDL) BigDecimal 타입에서 사용
precision은 소수점을 포함한 전체 자리수를
scale은 소수의 자릿수이다.
double, float타입에는 적용되지 않고 아주 큰 숫자나 정밀한 소수를 다루어야 할때만 사용한다.
precision = 19,
scale = 2

@Enumerated

  • 자바 enum 타입을 매핑할 때 사용
  • 💡 !!!!주의!!!! ORDINAL 사용X
    • 예를들어 요구사항이 늘어나서 코드가 변경되어 순서가 바뀌면 DB값은 변경되지 않고 꼬여버린다.
속성 설명 기본값
value EnumType.ORDINAL: enum 순서를 데이터베이스에 저장

EnumType.STRING: enum 이름을 데이터베이스에 저장
EnumType.ORDINAL

@Temporal

  • LocalDate, LocalDateTime을 사용할 때는 생략 가능(최신 하이버네이트 지원)
    • 굳이 쓸 필요가 없어진 상황이다!!

속성 설명 기본

속성 설명 기본값
value TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑 (예: 2013–10–11)

TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑 (예: 11:11:11)

TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이 스 timestamp 타입과 매핑(예: 2013–10–11 11:11:11)
 

@Lob

  • DB에 대용량의 데이터를 저장할 필요성이 있을 경우 LOB을 사용한다.
  • 데이터베이스 BLOB, CLOB 타입과 매핑
    • @Lob에는 지정할 수 있는 속성이 없다.
    • 매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지는 BLOB 매핑
      • CLOB: String, char[], java.sql.CLOB
      • BLOB: byte[], java.sql. BLOB

@Transient

  • 필드 매핑X
  • 데이터 베이스에 저장X, 조회X
  • 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용
  • ex
    • @Transient private Integer temp;

'DB > JPA' 카테고리의 다른 글

실전 예제 - 요구사항 분석과 기본 매핑  (0) 2023.01.04
기본 키 매핑  (0) 2023.01.03
데이터 베이스 스키마 자동생성  (0) 2022.12.30
객체와 테이블 매핑  (0) 2022.12.30
준영속 상태  (0) 2022.12.30

데이터베이스 스키마 자동 생성

  • DDL을 애플리케이션 실행 시점에 자동 생성
    • 테이블을 미리 만들어 두지 않아도 된다는 이점이 있음.
  • 테이블 중심 → 객체 중심
  • 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL 생성
    • DB 별로 문법이 살짝씩 다른 것을 극복 가능하다.
  • 이렇게 생성된 DDL은 개발 장비에만 사용
  • 생성된 DDL은 운영서버에서는 사용하지 않거나, 적절히 다듬은 후 사용

데이터 베이스 스키마 자동 생성 - 속성

  • hibernate.hbm2ddl.auto
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="hello">
        <properties>
            <!-- 필수 속성 -->
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <!-- 아래 코드의 value 값을 말한다. -->
            <property name="hibernate.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>
</persistence>
옵션 설명
create 기존 테이블 삭제 후 다시 생성(DROP + CREATE)
create-drop create와 같으나 종료시점에 테이블 DROP
update 변경분만 반영(운영DB 사용하면 안됨) -> alter 동작 지우는건 안됨!! 추가하는거만 동작함!!
validate 엔티티와 테이블이 정상 매핑되었는지만 확인
none 사용하지 않음 -> 관례상 none 이라고 씀 아무거나 넣어도 상관은 없음! 어짜피 동작하지 않기에..

 

데이터베이스 스키마 자동 생성 - 주의

  • 운영 장비에는 절대 create, create-drop, update 사용하면 안된다
  • 개발 초기 단계는 create 또는 update
  • 테스트 서버는 update 또는 validate
    • update는 편하긴 하지만 alter 문은 굉장히 위험하기 때문에 가급적으로 쓰지 않아야 할 것 같다.
  • 스테이징과 운영 서버는 validate 또는 none

DDL 생성 기능

  • 제약조건 추가: 회원 이름은 필수, 10자 초과X
    • @Column(nullable = false, length = 10)
  • 유니크 제약조건 추가
    • @Table(uniqueConstraints = {@UniqueConstraint( name = "NAME_AGE_UNIQUE", columnNames = {"NAME", "AGE"} )}
  • DDL 생성 기능은 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다

'DB > JPA' 카테고리의 다른 글

기본 키 매핑  (0) 2023.01.03
필드와 컬럼 매핑  (0) 2022.12.31
객체와 테이블 매핑  (0) 2022.12.30
준영속 상태  (0) 2022.12.30
플러시  (1) 2022.12.30

엔티티 매핑 소개

  • 객체와 테이블 매핑 : @Entity, @Table
  • 필드와 컬럼 매핑 : @Column
  • 기본 키 매핑 : @Id
  • 연관관계 매핑 : @ManyToOne,@JoinColumn

객체와 테이블 매핑

@Entity

  • @Entity가 붙은 클래스는 JPA가 관리하고 , 엔티티라 한다.
  • JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 필수!!!

💡 주의

  • 기본 생성자 필수(파라미터가 없는 public 또는 protected 생성자)
    • 스펙 상 규정되어 있음
    • 리플렉션 등 동적인 기술을 쓸때 꼭 필요한 조건이다.
  • final 클래스, enum, interface, inner 클래스 사용불가하다.
  • 저장할 필드에 final 사용할 수 없다.(당연하지만..)

@Entity 속성

  • 속성 : name
    • JPA에서 사용할 엔티티 이름을 지정한다.
    • 기본값은 클래스 이름을 그대로 사용한다.
    • 같은 클래스 이름이 없으면 가급적으로 기본값 사용.

@Table

  • @Table은 엔티티와 매핑할 테이블 지정
속성 기능 기본값
name 매핑할 테이블 이름 엔티티 이름
catalog 데이터베이스 catalog 매핑  
schema 데이터베이스 schema 매핑  
uniqueConstraints DDL생성 시에 유니크 제약 조건 생성  

 

'DB > JPA' 카테고리의 다른 글

필드와 컬럼 매핑  (0) 2022.12.31
데이터 베이스 스키마 자동생성  (0) 2022.12.30
준영속 상태  (0) 2022.12.30
플러시  (1) 2022.12.30
영속성 컨텍스트 2  (0) 2022.12.30

준영속 상태

  • 영속 → 준영속
  • 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)
  • 영속성 컨텍스트가 제공하는 기능을 사용 못함

준영속 상태로 만드는 방법

  • em.detach(entity)
    • 특정 엔티티만 준영속 상태로 전환
  • em.clear()
    • 영속성 컨텍스트를 완전히 초기화
  • em.close()
    • 영속성 컨텍스트를 종료

'DB > JPA' 카테고리의 다른 글

데이터 베이스 스키마 자동생성  (0) 2022.12.30
객체와 테이블 매핑  (0) 2022.12.30
플러시  (1) 2022.12.30
영속성 컨텍스트 2  (0) 2022.12.30
영속성 컨텍스트 1  (0) 2022.12.30

플러시

영속성 컨텍스트의 변경내용을 데이터베이스에 반영


플러시 발생

  • 변경 감지
  • 수정된 엔티티 쓰기 지연 SQL 저장소에 등록
  • 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송
  • 플러스가 발생한다고해서 commit이 되는건 아니다.

영속성 컨텍스트를 플러시 하는 방법

  • em.flush() - 직접 호출
    • 직접 쓸 일은 거의 없다.
  • 트랜잭션 커밋 - 플러시 자동 호출
  • JPQL 쿼리 실행 - 플러시 자동 호출

JPQL 쿼리 실행시 플러시가 자동으로 호출되는 이유

em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//중간에 JPQL 실행
query = em.createQuery("select m from Member m", Member.class);
List<Member> members= query.getResultList();

 

  • 위와 같은 상황일때 DB에 값이 없는 상황이 생길 수 있다.
  • 이런 상황을 방지하고자 기본모드가 flush()를 항상 수행하도록 설계되었다.

플러시는!

  • 영속성 컨텍스트를 비우지 않음
  • 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화
  • 트랜잭션이라는 작업 단위가 중요 → 커밋 직전에만 동기화 하면 된다.

 

'DB > JPA' 카테고리의 다른 글

객체와 테이블 매핑  (0) 2022.12.30
준영속 상태  (0) 2022.12.30
영속성 컨텍스트 2  (0) 2022.12.30
영속성 컨텍스트 1  (0) 2022.12.30
JPA - 애플리케이션 개발  (0) 2022.12.30

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21687?category=questionDetail&q=385382

  1. 엔티티를 영속 시킨다.
    1. 내부의 1차캐시가 있다.
      1. @id (Key)
      2. Entity (Value)

이렇게 되면 무슨 이점이 있을까?


1. 1차 캐시에서 조회

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21687?category=questionDetail&q=385382

멤버객체를 저장하고 조회를 하면

jpa는 영속성 컨텍스트에서

  • 1차 캐시를 조회(DB를 바로 가지않음)

2. 데이터베이스에서 조회

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21687?category=questionDetail&q=385382

1차 캐시에 없는 데이터를 조회 해보자

  1. 1차 캐시를 조회(없는 상황)
  2. DB에서 조회
  3. 1차 캐시에 저장
  4. 해당 데이터 반환
  • 엔티티 매니저라는 것은 데이터베이스 트랜잭션 단위로 만들고 끝나면 종료된다.
  • 고객의 요청이 하나 들어와서 비즈니스가 끝나면 영속성 컨텍스트가 지워져서 1차 캐시가 지워져버려 그다지 큰 이득을 볼 수 있다곤 할 수 없다.

3. 영속 엔티티의 동일성 보장

Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.println(a == b);
  • 콘솔에 찍히는 값은 true 이다.
  • 1차 캐시로 반복 가능한 읽기(REPEEATABLE READ) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공

4. 엔티티 등록 트랜잭션을 지원하는 쓰기 지연

EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit(); // [트랜잭션] 커밋

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21687?category=questionDetail&q=385382&tab=curriculum

  • 영속성 컨텍스트 안에는 쓰기 지연 SQL 저장소 라는 것이 있다.
  1. persist(memberA)
  2. 1차캐시에 memberA 들어감
  3. 동시에 JPA가 엔티티를 분석하여 Insert Query 생성
  4. 쓰기지연 SQL 저장소에 쿼리 저장
  5. persist(memberB)
  6. 1차캐시에 memberB 들어감
  7. 동시에 JPA가 엔티티를 분석하여 Insert Query생성(현재 insert Query가 2개 저장되어 있음)
  8. transaction.commit();
  9. flush
    • 영속성 컨텍스트의 변경 내용을 DB 에 반영하는 것을 말한다
  10. commit

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21687?category=questionDetail&q=385382&tab=curriculum

5. 엔티티 수정 - 변경 감지

EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // [트랜잭션] 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);
//em.update(member) 이런 코드가 있어야 하지 않을까?
transaction.commit(); // [트랜잭션] 커밋
  • 단순히 값만 바꿨지만
  • UPDATE Query가 실행되는걸 알 수 있다.
  • 비밀이 뭘까??

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21687?category=questionDetail&q=385382&tab=curriculum

  1. 바로 영속성 컨텍스트 안에 있다.
  2. 1차 캐시에는스냅샷이라는 것이 들어있다. 최초 시점의 상태를 스냅샷을 떠둔다.
  3. JPA는 commit하는 시점에 flush()가 호출된다.
  4. 이때 엔티티와 스냅샷을 비교한다.
  5. 비교를 해보고 바뀌었다면
  6. UPDATE Query를 쓰기 지연 저장소에 저장하고
  7. DB반영
  8. commit() 수행

'DB > JPA' 카테고리의 다른 글

객체와 테이블 매핑  (0) 2022.12.30
준영속 상태  (0) 2022.12.30
플러시  (1) 2022.12.30
영속성 컨텍스트 1  (0) 2022.12.30
JPA - 애플리케이션 개발  (0) 2022.12.30
더보기

💡 JPA에서 가장 중요한 2가지

  • 객체와 관계형 데이터베이스 매핑하기
  • 영속성 컨택스트

영속성 컨텍스트

엔티티 매니저 팩토리와 엔티티 매니저

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21686?category=questionDetail&q=385382

  • EntityManagerFactory를 통해서 고객의 요청이올때마다 EntityManager를 생성한다.
  • Entity 매니저는 내부적으로 데이터베이스 커넥션으로디비를 사용하게 된다.

영속성 컨텍스트

  • JPA를 이해하는데 가장 중요한 용어
  • “엔티티를 영구 저장하는 환경” 이라는 뜻

https://www.inflearn.com/course/ORM-JPA-Basic/unit/21686?category=questionDetail&q=385382
https://www.inflearn.com/course/ORM-JPA-Basic/unit/21686?category=questionDetail&q=385382

  • 비영속(new/transient)
    • 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
      • 객체를 생성만 한 상태(셋팅만 한 상태)
      • JPA와 관련없음
  • 영속(managed)
    • 영속성 컨텍스트에 관리되는 상태
      • 엔티티매니저 안에는 영속 컨텍스트가 있다.
      • em.persist(객체)
      • 영속상태가 된다고해서 DB에 쿼리를 보내는 것이 아니다.
      • 트랜잭션을 commit 하는 시점에 쿼리가 실행된다.
  • 준영속(detached)
    • 영속성 컨텍스트에 저장되었다가 분리된 상태
      • em.detach(객체)
  • 삭제(removed)
    • 삭제된 상태
      • em.remove(객체)

왜 이런 매커니즘일까?

애플리케이션과 DB사이에 무언가 있다.!!

중간에 무언가 있으면 이점들을 누릴 수 있다.

'DB > JPA' 카테고리의 다른 글

객체와 테이블 매핑  (0) 2022.12.30
준영속 상태  (0) 2022.12.30
플러시  (1) 2022.12.30
영속성 컨텍스트 2  (0) 2022.12.30
JPA - 애플리케이션 개발  (0) 2022.12.30

+ Recent posts