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
자바 ORM 표준 JPA 프로그래밍
자바 ORM 표준 JPA는 SQL 작성 없이 객체를 데이터베이스에 직접 저장할 수 있게 도와주고, 객체와 관계형 데이터베이스의 차이도 중간에서 해결해준다. 이 책은 JPA 기초 이론과 핵심 원리, 그리고
book.naver.com
'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.231. @Query Repository의 메서드 위에 선엄함으로써 sql 쿼리를 작성할 수 있습니다. 명명법으로 해결하기 힘든 쿼리를 사용할 때 유용합니다. 1-1. 기본 사용법 메서드 위에 @Query(sql)을 해주시면 됩니다. @Query("select m from Member m") List findMemberBy(); @Query 안에 들어가는 테이블은 별칭을 부여해서 사용할 수 있습니다. Member 객체를 m이라는 별칭을 이용했습니다. @Test @DisplayName("@Query 사용 basic") void selectAll(){ List members = createMember(); for(Member member: members){ memberRepository.save(member);… -
Spring-data-JPA [3] 명명법
Spring-data-JPA [3] 명명법
2022.03.22Springboot-Data-JPA 명명법 JPA는 반복적인 SQL 작성과 객체를 SQL에 맵핑하는 것을 대신 수행해줍니다. 따라서 개발자는 JPA를 통해서 단순 코드 작성, 맵핑하는 것에 초점을 두지 않고, 비즈니스 개발에 집중할 수 있게 되었습니다. 그중에서 SQL을 직접 작성하지 않고 메서드의 명명으로 쿼리를 사용할 수 있게 해주는 명명법에 대해서 알아보겠습니다. 명명법이 동작하는 원리도 포스팅하려 했지만, Hibernate 구현체에 디버깅 걸어도 보고 구글링도 했지만 찾지 못했습니다… 추후에 찾게 된다면 동작 원리에 대해서도 포스팅 하겠습니다. 2022.04.10 추가 명명법의 동작 과정을 살펴보겠습니다. 사용된 query는 아래와 같습니다. Optional findByName(String na… -
Spring-data-JPA(1) [엔티티] Entity
Spring-data-JPA(1) [엔티티] Entity
2022.01.06@Entity JPA가 괸리하는 엔티티라는 어노테이션 기본 생성자가 필수이다. (파라미터가 없는 protected 생성자 ) final 클래스, enum, interface 사용 불가 저장할 필드에 final 사용 X 속성 name --> JPA에서 사용할 엔티티의 이름을 설정한다. default 값은 클래스의 이름 그대로 @Entity // entity로 할 것에 붙여줍니다. public class Member { @Id @GeneratedValue private Long id; } @Column 컬럼 매핑 속성 name: 필드와 매핑할 테이블의 컬럼 이름 insertable, updatable: 등록, 변경 가능 여부 nullable: null값 허용을 결정 unique: 유니크한 제약조건을 건다. … -
Spring-data-JPA(0) JPA란??
Spring-data-JPA(0) JPA란??
2022.01.06▶ JPA란?? Java Persistence API: 자바 진영의 ORM 기술 표준 Object-relational mapping(객체 관계 매핑) - 객체는 객체대로 설계 - 관계형 데이터베이스는 관계형 데이터베이스대로 설계 - ORM 프레임워크가 중간에서 매핑 - 대중적인 언어에는 대부분 ORM 기술이 존재 ▶ JPA를 사용하는 이유 SQL 중심적인 개발에서 객체 중심으로 개발이 가능하여 생산성, 유지보수, 패러다임의 불일치 해결, 성능 등등 많은 이점을 얻을 수 있습니다. 영속성: 데이터를 생성한 프로그램의 실행이 종료되더라도 사라지지 않는 데이터의 특성을 의미합니다. DB에 저장되는 entity가 영속성 컨텍스트에 포함된다면 아래와 같은 이점을 얻을 수 있다. 1. 1차 캐시 -> 영속성 컨텍스…
댓글을 사용할 수 없습니다.