JPA

우리는 JPA를 사용해서 엔티티를 설계할 때, 보통 연관관계를 맺어서 설계하는 경우가 대다수이다. 연관관계는 보통 1:N, N:1의 연관관계가 가장 많이 쓰일 것이다. 팀 엔티티와 회원 엔티티가 일대다 관계로 존재한다고 가정해보자. A팀을 데이터베이스에서 가져와 영속화 상태로 만들고, A팀 객체에 회원들을 추가시키려면 회원 객체도 영속화 상태로 만들어서 추가해야 정상적으로 데이터베이스 테이블에 반영될 것이다. 그런데 추가해야할 회원이 100명 또는 엄청 많은 회원이라면 모두 영속화 시켜야 할 것이다. 이 때, 영속성 전이 속성을 이용하면 이런 문제를 모두 해결해준다. 영속성 전이 - CASCADE 영속성 전이를 사용하는 목적은 다음과 같다. 특정 엔티티를 영속 상태로 만들 때, 연관된 엔티티도 함께 영속..

프록시(Proxy) A 엔티티와 B 엔티티가 N:1의 연관관계를 가지고 있다고 가정해보자. 우리가 A 엔티티를 조회할 때 항상 B 엔티티가 필요하지 않을 수도 있다. 예를 들어 회원 엔티티를 조회할 때 연관된 팀 엔티티는 비즈니스 로직에 따라서 사용될 때도 있지만, 그렇지 않을 때도 있다. 예를들면 우리가 이미 팀을 알고있는 회원은 회원 정보만 궁금할 것이고, 아무 정보도 모르는 회원은 회원 정보와 팀 정보 모두 궁금할 것이다. 즉, 하고싶은 말은 회원 정보만 궁금할 때는 회원 엔티티만 사용하므로 연관된 팀 엔티티를 불러올 필요가 없다는 것이다. JPA는 이런 문제를 해결하려고 엔티티가 실제 사용될 때까지 데이터베이스 조회를 지연하는 방법을 제공하는데 이것을 지연 로딩이라고 한다. 쉽게 이야기해서 tea..


영속성 컨텍스트는 내부에 캐시를 가지고 있는데, 이것을 1차 캐시라고 한다. 엔티티가 영속상태가 되면 모두 1차 캐시에 저장이 된다. 1차 캐시의 형태는 @Id로 매핑된 엔티티의 식별자와 이에 해당하는 엔티티 객체, 스냅샷이 들어있다. 우선적으로 스냅샷을 제외하고 1차 캐시가 하는 역할을 알아보자. 엔티티 등록 밑의 소스코드는 엔티티 객체를 생성하고 초기화한 다음, 엔티티 매니저를 통해서 엔티티 인스턴스를 영속화하는 코드이다. //엔티티 인스턴스를 생성(비영속) Member memberA = new Member(); member.setId("memberA"); member.setUsername("회원A"); //엔티티 인스턴스를 영속화(영속) em.persist(memberA); 그렇다면 위 코드를 실행..

전체 종류 다대일: @ManyToOne 일대다: @OneToMany 일대일: @OneToOne 다대다: @ManyToMany 다대일(N:1) 단방향 가장 많이 사용하는 연관관계이다. 반대는 일대다(1:N) 이다. 객체 입장에서 한쪽에서만 참조가 가능하다. @Entity class Member { ... @ManyToOne @JoinColumn(name = "TEAM_ID") private Team team; } @Entity class Team {...} 다대일(N:1) 양방향 외래 키가 있는쪽이 연관관계의 주인이다. 객체 입장에서도 양쪽에서 참조가 가능하다. //연관관계의 주인 @Entity class Member { ... @ManyToOne @JoinColumn(name = "TEAM_ID") pr..

JPA의 데이터 타입 분류 엔티티 타입 @Entity로 정의하는 객체 데이터가 변해도 식별자로 지속해서 추적 가능하다. 회원 엔티티의 키나 나이 값을 변경해도 식별자로 인식이 가능하다. 값 타입 int Integer, String 처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체 식별자가 없고 값만 있으므로 변경시 추적이 불가능하다. 값 타입 분류 기본값 타입 자바 기본 타입(int, double) 래퍼 클래스(Integer, Long) String 임베디드 타입(embedded type, 복합 값 타입) 컬렉션 값 타입(collection value type) 기본값 타입 String name, int age 생명주기를 엔티티에 의존한다. 회원을 삭제하면 이름, 나이 필드도 함께 삭제된다. 값 타입..

프록시(Proxy) em.find(): 데이터베이스를 통해서 실제 엔티티 객체 조회 em.getReference(): 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회 특징 실제 클래스를 상속 받아서 만들어진다. 실제 클래스와 겉 모양이 동일하다. 사용하는 입장에서 진짜 객체인지 프록시 객체인지 구분하지 않고 사용하면 된다. 프록시 객체는 실제 객체의 참조를 보관한다. 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메서드를 호출한다. 프록시 초기화 프록시 객체는 처음 사용할 때 한 번만 초기화한다. 프록시 객체를 초기화 할때, 프록시 객체가 실제 엔티티로 바뀌는 것은 아니다. -> 초기화 되면 프록시 객체가 실제 엔티티에 접근이 가능한 것 뿐이다. 프록시 객체는 원본 엔티티를 상속받는다. -..

관계형 데이터베이스에는 상속관계가 존재하지 않는다. 슈퍼타입 서브타입 관계 모델링 기법이 객체의 상속과 유사하다. 따라서 객체의 상속 구조와 DB의 슈퍼타입 서브타입 관계를 매핑한다. 상속관계 매핑 슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법 각각 테이블로 변환: 조인 전략 통합 테이블로 변환: 단일 테이블 전략 서브타입 테이블로 변환: 구현 클래스마다 테이블 전략 상속관계 매핑 어노테이션 @Inheritance(strategy=InheritanceType.XXX) JOINED: 조인 전략 SINGLE_TABLE: 단일 테이블 전략 TABLE_PER_CLASS: 구현 클래스마다 테이블 전략 @DiscriminatorColumn(name="DTYPE"): 부모 클래스에 붙여주는 어노테이션..

단방향 연관관계 객체 관점 한쪽 객체에서만 참조가 가능 다른 한쪽 객체에서는 참조가 불가능한 관계 테이블 관점 한쪽 테이블에서 다른 한쪽 테이블의 FK를 가지고 있음 FK를 통해 같이 조회가 가능 @Entity public class Member { @Id @GeneratedValue private Long id; @ManyToOne @JoinColumn(name = "team_id") private Team team; } @Entity public class Team { @Id @GeneratedValue @Column(name = "team_id") private Long id; } 양방향 연관관계 객체 관점 양쪽 객체에서 모두 참조가능 한쪽 객체에서 연관관계의 주인이 된다. 테이블 관점 단방향 연관..

@Entity @Entity가 붙은 클래스는 JPA가 관리하는 객체이며, 엔티티라고 부른다. 기본 생성자가 필수이다. final 클래스, enum, interface, inner 클래스 사용이 불가능하다. name 속성 @Entity(name = "user") public class Member { } JPA에서 사용할 엔티티 이름을 지정한다. 기본값: 클래스 이름을 그대로 사용한다. (Member) 가급적 기본값을 사용하는 것을 권장한다. @Table 엔티티와 매핑할 테이블을 지정한다. @Table(name = "user") @Entity public class Member { } name 속성은 매핑할 테이블의 이름을 지정하고, 기본값은 엔티티 이름을 그대로 사용한다. @Column 엔티티 내의 필드..