JPA 기본 pdf 중 '08. 프록시와 연관관계 관리' 내용 

 

-Member안에 team 객체가 있는 상황에서 member를 조회할 때 항상 team도 함께 조회해야할까?

굳이 그럴 필요없을 때 사용하는 것이 프록시(Proxy)이다 

 

-프록시 기초

em.getReference(): 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체를 조회한다

em.find(): 데이터베이스를 통해서 실제 엔티티 객체를 조회한다

 

 

-프록시 특징

실제 클래스를 상속 받아서 만들어진다

실제 클래스와 겉모양이 같다

사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용한다(이론상)

 

 

프록시 객체는 실제 객체의 참조(target)를 보관한다 

프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드를 호출한다

 

-프록시 객체의 초기화

 

-프록시 특징(중요!!)

1. 프록시 객체는 처음 사용할 때 한번만 초기화 한다

 

2.프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는 것은 아니다. 초기화되면 프록시 객체를 통해서 실제 엔티티에 접근 가능하다

jpa는 한 트랜잭션에서 같은 걸 보장해준다 

영속성 컨텍스트에 엔티티가 있으면 엔티티를 반환한다

 

3.프록시 객체는 원본 엔티티를 상속받는다. 따라서 타입 체크시 주의해야한다(==비교는 실패하기 때문에 instanceof를 사용해야한다)

 

4. 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티를 반환한다

 

5. 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때, 프록시를 초기화하면 문제가 발생한다

(하이버네이트는 Org.hibernate.LazyInitializationException 예외를 터트린다. 실무에서 자주 마주칠 에러다)

 

-프록시 확인

1. 프록시 인스턴스의 초기화 여부 확인: PersistenceUnitUtil.isLoaded(Object Entity)

 

2.프록시 클래스 확인 방법: entity.getClass().getName()출력

(..javasis..or HibernateProxy)

 

3. 프록시 강제 초기화: org.hibernate.initialize(entity);

 

4.참고로 JPA 표준은 강제 초기화가 없다. 

강제 호출: member.getName()

-상속관계 매핑

관계형 데이터베이스(RDB)에는 상속 관계가 없다

슈퍼타입,서브타입 관계라는 모델링 기법이 객체 상속과 유사핟

상속관계 매핑은 객체의 상속 구조와 DB의 슈퍼타입,서브타입관계를 매핑하는 것이다 

 

-슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법

1) 각각 테이블로 변환-> 조인 전략

2)통합 테이블로 변환 ->단일 테이블 전략

3)서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략(비추천)

 

1),2) 방법만 기록할 예정이다. 3)방법은 사용하면 안됨 

 

-주요 어노테이션

1. @Inheritance(strategy=InheritanceType.xxx)

 

1) JOINED: 조인전략

 

2) SINGLE_TABLE: 단일 테이블 전략

 

3) TABLE_PER_CLASS: 구현 클래스마다 테이블 전략

 

2. @DiscriminatorColumn(name="DTYPE")

3. @DiscriminatorValue("XXX")

 

1) 조인 전략 

장점: 

테이블의 정규화

외래키 참조 무결성 제약조건(null값이 아닌거) 활용가능

저장공간 효율화

 

단점:

조회시 조인을 많이 사용해서 성능이 저하된다

조회 쿼리가 복잡하다

데이터 저장시 INSERT SQL 2번 호출

 

2) 단일 테이블 전략(간단한 경우에 많이 사용한다)

장점: 

조인이 필요없으므로 일반적으로 조회 성능이 빠르다

조회 쿼리가 단순하다

단점:

자식 엔티티가 매핑한 컬럼은 모두 null 허용한다

단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다. 

상황에 따라서 조회 성능이 오히려 느려질 수 있다 

 

@MappedSuperClass

: 공통 매핑 정보가 필요할 때 사용한다(id,name,createdBy,modifiedBy,createdDate,modifiedDate)

상속관계 매핑 하지 않는다

엔티티가 아니고, 테이블과 매핑하지 않는다

부모 클래스를 상속받는 자식 클래스에 매핑 정보만 제공한다

조회,검색이 불가능하다(em.find(BaseEntity) 불가능)

직접 생성해서 사용할 일이 없으므로 추상 클래스를 권장한다 

테이블과 관계 없고, 단순히 엔티티가 공통으로 사용하는 매핑정보를 모으는 역할이다

주로 등록일,수정일,등록자,수정자 같은 전체 엔티티에서 공통으로 적용하는 정보를 모을 때 사용한다

 

참고: @Entity 클래스는 엔티티나 @MappedSuperclass로 지정한 클래스만 상속 가능하다 

 

JPA기본 pdf 중 '06. 연관관계 매핑 기초' 내용이다

 

엔티티를 컨트롤러에서 반환 절대 하지마라!

무한루프가 발생할 수 있고, 엔티티에 변경이 있을 시 API 스펙이 달라진다

컨트롤러에서는 dto 사용하자 

-연관관계 매핑시 고려사항 3가지

1. 다중성

2. 단방향, 양방향

3. 연관관계의 주인 

 

1. 다중성

다대일: @ManyToOne

일대다: @OneToMany

일대일: @OneToOne

다대다: @ManyToMany

 

2. 단방향, 양방향

-테이블

외래키 하나로 양쪽 조인 가능

사실 방향이라는 개념이 없다

 

-객체 

참조용 필드가 있는 쪽으로만 참조 가능

한쪽만 참조하면 단방향

양쪽이 서로 참조하면 양방향 

 

3.연관관계의 주인

테이블은 외래 키 하나로 두 테이블이 연관관계를 맺음

객체 양방향 관계는 a->b, b->a처럼 참조가 2군데이다

객체 양방향 관계는 참조가 2군데 있다. 둘 중 테이블의 외래키를 관리할 곳을 지정해야한다

연관관계 주인은 외래키를 관리하는 참조

주인의 반대편(양방향에서)은 외래키에 영향을 주지 않고, 단순조회만 가능하다 

 

테이블에서는 다(n)쪽에 외래키 참조를 넣어야 한다

다대일에서는 ‘다’가 연관관계 주인이고

일대다에서는 연관관계 주인이다

실무에서 주로 사용하는 것은 다대일이라서 다대일을 중심으로 기록하려 한다 

 

-다대일 단방향

가장 많이 사용하는 연관관계이고, 반대는 일대다이다.

-다대일 양방향

외래 키가 있는 쪽이 연관관계의 주인이고

양쪽을 서로 참조하도록 개발한다

 

@JoinColumn: 외래키를 매핑할 때 사용한다

속성 설명 기본값
name
매핑할 외래 키 이름
필드명 + _ + 참조하는 테 이블의 기본 키 컬럼명
referencedColumnName
외래 키가 참조하는 대상 테이블의 컬럼명
참조하는 테이블의 기본 키 컬럼명
foreignKey(DDL)
외래 키 제약조건을 직접 지정할 수 있다. 이 속성은 테이블을 생성할 때만 사용한다.
 
unique
nullable insertable updatable columnDefinition table
@Column의 속성과 같다.
 

 

@ManyToOne 주요속성

 

속성 설명 기본값
optional
false로 설정하면 연관된 엔티티가 항상 있어야 한다.
TRUE
fetch
글로벌 페치 전략을 설정한다.
- @ManyToOne=FetchType.EAGER - @OneToMany=FetchType.LAZY
cascade
영속성 전이 기능을 사용한다.
 
targetEntity
연관된 엔티티의 타입 정보를 설정한다. 이 기능은 거 의 사용하지 않는다. 컬렉션을 사용해도 제네릭으로 타 입 정보를 알 수 있다.
 

 

@OneToMany

속성 설명 기본값
mappedBy
연관관계의 주인 필드를 선택한다.
 
fetch
글로벌 페치 전략을 설정한다.
- @ManyToOne=FetchType.EAGER - @OneToMany=FetchType.LAZY
cascade
영속성 전이 기능을 사용한다.
 
targetEntity
연관된 엔티티의 타입 정보를 설정한다. 이 기능은 거 의 사용하지 않는다. 컬렉션을 사용해도 제네릭으로 타 입 정보를 알 수 있다.
 

 

+ Recent posts