Spring-data-JPA(2) 개념
연관 관계
- 단반향 연관관계
@Entity
public class User{
@Id @GeneratedValue
private Long id;
@Column
private String name;
@Column
private int age;
@ManyToOne
@JoinColumn(name= "team_id")
private Team team // 연관 관계 설정
}
- 양방향 연관관계
@Entity
public class User{
@Id @GeneratedValue
private Long id;
@Column
private String name;
@Column
private int age;
@ManyToOne
@JoinColumn(name= "team_id")
private Team team // 연관 관계 설정
}
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
@Column
private String name;
@OneToMany(mappedBy = "team")
List<User> users = new ArrayList<User>();
}
연관관계의 주인과 mappedBy
- 객체의 두 관계중 하나를 연관관계의 주인으로 지정
- 연관관계의 주인만이 외래키를 관리
- 주인이 아닌쪽은 읽기만 가능 -> mappedBy 속성이다.
- 주인은 mappedBy 설정하지 않는다.
- 주인이 아니면 mappedBy 속성으로 주인 지정
- 연관관계의 주인은 외래키가 있는 곳으로 해라
- 외래키는 1:N중에서 N에 보통 위치시키고 1:1의 경우 access가 많이 사용되는 곳에 둔다.
연관관계 annotation
- @JoinColumn
- name: 매핑할 외래 키 이름
- @Column 속성과 같은 것을 다 가지고 있다.
- @ManyToOne
- optional: false로 설정하면 연관된 엔티티가 항상 있어야한다.
- fetch: 글로벌 패치 전략을 설정한다. 최적화를 위해 LAZY로 설정한다.
- cascade: 영속성 전이 기능을 사용한다.
- @OneToMany
- mappedBy: 연관관계의 주인 필드를 선택한다.
- fetch: 글로벌 패치 전략을 설정한다.
- cascade: 영속성 전이 기능을 사용한다.
상속관계 매핑
- 슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법
- 각각 테이블로 변환 -> 조인 전력
- 통합 테이블로 변환 -> 단일 테이블 전략
- 서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략
- 주요 annotation
- @Inheritance ( strategy = InheritaneType.xxx)
- JOINED: 조인전력
- 장점: 테이블 정규화, 외래키 참조 무결성 제약조건 활용가능, 저장공간 효율화
- 단점: 조회시 조인을 많이 사용, 성능저하, 조회 쿼리가 복잡함
- SINGLE_TABLE: 단일 테이블 전략
- 장점: 조인이 필요 없어서 일반적으로 조회 성능이 빠름, 조회 쿼리가 단순함
- 단점: 자식 엔티티가 매핑한 걸럼은 모두 null 허용, 단이 테이블에 모든 것을 저장하므로 크기가 커진다.
- TABLE_PER_CLASS: 구현 클래스마다 테이블 전략
- 장점: 서브 타입을 명확하게 구분해서 처리할 때 효과적
- 단점: 여러 자식 테이블을 함께 조회할 때 성능이 느림
- JOINED: 조인전력
- @DiscriminatorColumn( name = "DTYPE" )
- @DiscriminatorValue("xxx")
- @Inheritance ( strategy = InheritaneType.xxx)
1. @Inheritance 예시입니다.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "dtype")
public abstract class Item {
@Id
@GeneratedValue
@Column(name = "item_id")
private Long id;
private int price;
private int stockQuantity;
}
@Entity
@DiscriminatorValue("B")
public class Book extends Item {
private String author;
private String isbn;
}
- MappedSuperClass
- 공통 매핑 정보가 필요할 때 사용
- 상속관계 매핑 x
- 엔티티x, 테이블과 매핑x
- 부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공
- 조회, 검색 불가능
- 직접 생성해서 사용할 일이 없으므로 추상 클래스 권장
1. Auditing에 추후에 설명할 예정이고 @MappedSuperclass의 예시를 보겠습니다.
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Getter
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdTime;
@LastModifiedDate
private LocalDateTime lastChangedTime;
@Column(updatable = false)
private String createdBy;
@LastModifiedBy
private String lastModifiedBy;
}
@Entity
public class Member extends BaseEntity {
@Id
@GeneratedValue
@Column(name = "member_id")
private Long id;
}
프록시
- 실제 클래스를 상속 받아서 만들어진다.
- 실제 클래스와 겉 모양이 같다.
- 사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용하면 된다.
- 프록시 객체는 실제 객체의 참조( target )를 보관
- 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드 호출
즉시 로딩과 지연 로딩
- 지연 로딩은 프록시를 두고 실제로 사용할 때 불러온다.
- 즉시 로딩은 바로 엔티티를 불러온다
- 지연 로딩 최적화 시 fetchJoin, default_batch_fetch_size를 설정하여 최적화한다.가급적 지연 로딩만 사용한다. -> 즉시 로딩 적용 시 예상하지 못한 sql이 발생하고 N+1문제도 일으킬 수 있다.
영속성 전이: CASCADE
- 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을 때
- 영속성 전이는 연관관계를 매핑하는 것과는 아무런 관계가 없다.
- 종류
- ALL: 모두 적용
- PERSIST: 영속
- REMOVE: 삭제
- MERGE: 병합
- REFRESH: REFRESH
- DETACH: DETACH
고아객체
- 고아 객체 제거: 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제
- orphanRemoval = true
- 주의
- 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능
- 참조하는 곳이 하나일 때 사용해야한다.
- 특정엔티티가 개인 소요할 때 사용
- 엔티티 타입
- @Entity로 정의하는 객체
- 데이터가 변해도 식별자로 지속해서 추적 가능
- 값 타입
- int, Integer, String처럼 단순히 값으로 사용하는 자바 기본타입
- 식별자가 없고 값만 있으므로 변경시 추적 불가
- 값 타입 분류
- 자바 기본 타입: int, double
- 래퍼 클래스: Integer, Long
- String
- 생명주기를 entity에 의존한다.
- 값 타입은 공유하면 안된다.
- 임베디드 타입
- 새로운 값 타입을 직접 정의가 가능하다.
- JPA는 임베디드 타입이라한다.
- 주로 기본 값 타입을 모아서 만든다.
- @Embeddable: 값타입을 정의하는 곳에 표시
- @Embedded: 값 타입을 사용하는 곳에 표시
- 기본 생성자 필수
- 컬렉션 값 타입
- 값 타입을 하나 이상 저장할 때 사용
- @ElementCollection, @CollectionTable 사용
- 데이터베이스는 컬렉션을 같은 테이블에 저장할 수 없다.
- 컬렉션을 저장하기 위한 별도의 테이블이 필요함.
- 고려 사항
- 값 타입은 엔티티와 다르게 식별자 개념이 없다.
- 값은 변경하면 추적이 어렵다
- 일대다 관계를 생각하자
JPQL
- SQL 문법과 유사 SELECT, FROM, WHERE GROP BY, ORDER BY, HAVING, JOIN
- JPQL은 엔티티 객체를 대상으로 쿼리
- 엔티티와 속성은 대소문자 구분한다.
- 별칭 가능
- getResultList() -> List
- getSingleResult() -> 단일 값
파라미터 바인딩
1. 이름 기준
em.createQuery( select m from Member m where m.username: username)
.setParameter("useranme", useranme);
2. 위치 기준
em.createQuery( select m from Member m where m.username=?1)
.setParameter(1, useranme);
명확성을 위해서 이름 기준으로 한다.
조인
- 내부조인
- SELECT m FROM Member m [INNER] JOIN m.team t
- 외부조인
- SELECT m FROM Member m LEFT [OUTER] JOIN m.team t
- 세타조인
- select count(m) from Member m, Team t where m.username = t.name
서브쿼리
- exists: 서브쿼리에 결과가 존재하면 참
- all: 모두 만족하면 참
- any, some: 조건을 하나라도 만족하면 참
- in: 서브쿼리 결과중 하나라도 같은 것이 있으면 참
- from절에서는 아직 사용할 수 없다.
조건식 - case식
- select case when m.age <=10 then '어린이 요금'from Member m
when m.age >= 60 then '노인 요금' else '기본요금' end
경로 표현식 특징
- 상태 필드(state field): 경로 탐색의 끝, 탐색 x
- 단일 값 연관 경로: 묵시적 내부 조인 (inner join) 발생, 탐색 o
- 컬렉션 값 연관 경로: 묵시적 내부 조인 발생, 탐색x -> select t.members.username from Team t(x)
-> select m.username from Team t join t.members m (o)
페치 조인
- SQL 조인 종류가 아니다.
- JPQL에서 성능 최적화를 위해 제공하는 기능이다.
- 연관된 엔티티나 컬렉션을 SQL 한 번에 함께 조회하는 기능이다.
- join fetch 명령어 사용 -> select m from Member join fetch m.team
- distinct를 사용하여 컬렉션에 의해서 발생하는 중복 제거 가능
페치 조인의 특징과 한계
- 페치 조인 대상에는 별칭을 줄 수 없다.
- 하이버네이트는 가능하지만 가급적 사용하지 말자
- 둘 이상의 컬렉션은 페치 조인할 수 없다.
- 컬렉션을 패치 조인하면 페이징 api를 사용할 수 없다.
- 연관된 엔티티들을 SQL 한 번으로 조회하므로 성능이 최적화된다.
- 실무에서는 글로벌 로딩 전략은 모두 지연 로딩
벌크 연산
- UPDATEupdate Member m set m.age = m.age +1 where m.age>=10
- Deleteupdate와 동일하게 수행
지금까지 Spring-data-JPA에 관한 개념을 알아보았습니다. 감사합니다.
참고
https://book.naver.com/bookdb/book_detail.nhn?bid=9252528
'SpringBoot > JPA' 카테고리의 다른 글
Spring-Data-JPA [5] Fetch Join (0) | 2022.03.24 |
---|---|
Spring-data-JPA [4] Update와 @Query (0) | 2022.03.23 |
Spring-data-JPA [3] 명명법 (0) | 2022.03.22 |
Spring-data-JPA(1) [엔티티] Entity (0) | 2022.01.06 |
Spring-data-JPA(0) JPA란?? (0) | 2022.01.06 |
댓글
이 글 공유하기
다른 글
-
Spring-data-JPA [4] Update와 @Query
Spring-data-JPA [4] Update와 @Query
2022.03.23 -
Spring-data-JPA [3] 명명법
Spring-data-JPA [3] 명명법
2022.03.22 -
Spring-data-JPA(1) [엔티티] Entity
Spring-data-JPA(1) [엔티티] Entity
2022.01.06 -
Spring-data-JPA(0) JPA란??
Spring-data-JPA(0) JPA란??
2022.01.06