스프링

 

초급자를 위해 준비한
[백엔드, 웹 개발] 강의입니다.

JPA와 스프링 데이터 JPA의 기본 사용법을 알아봅니다.

✍️
이런 걸
배워요!

JPA 기본 매핑

스프링 데이터 JPA 기본 사용법

DB 연동의 열쇠 JPA! 
실무 중심의 핵심 기본기를 빠르게 ????

백엔드 실무자를 위한 
JPA & 스프링 데이터 JPA

 

 

 

인프런 강의
https://www.inflearn.com/course/jpa-spring-data-기초

 

 

유튜브
https://www.youtube.com/playlist?list=PLwouWTPuIjUi9Sih9mEci4Rqhz1VqiQXX

 

 

 

 

 

 

 

 

 

8.JPA 기초 08 값 콜렉션 Set 매핑

 




 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

임베디드 타입


• 새로운 값 타입을 직접 정의할 수 있음
• JPA는 임베디드 타입(embedded type)이라 함
• 주로 기본 값 타입을 모아서 만들어서 복합 값 타입이라고도 함
• int, String과 같은 값 타입

 

 

임베디드 타입 사용법
• @Embeddable: 값 타입을 정의하는 곳에 표시
• @Embedded: 값 타입을 사용하는 곳에 표시
• 기본 생성자 필수
 

 

 

 

임베디드 타입의 장점


• 재사용
• 높은 응집도
• Period.isWork()처럼 해당 값 타입만 사용하는 의미 있는 메소드를 만들 수 있음
• 임베디드 타입을 포함한 모든 값 타입은, 값 타입을 소유한 엔티 티에 생명주기를 의존함

 

 

 


값 타입 컬렉션
• 값 타입을 하나 이상 저장할 때 사용
• @ElementCollection, @CollectionTable 사용
• 데이터베이스는 컬렉션을 같은 테이블에 저장할 수 없다.
• 컬렉션을 저장하기 위한 별도의 테이블이 필요함

 


값 타입 컬렉션 사용
• 값 타입 저장 예제
• 값 타입 조회 예제
• 값 타입 컬렉션도 지연 로딩 전략 사용
• 값 타입 수정 예제
• 참고: 값 타입 컬렉션은 영속성 전에(Cascade) + 고아 객체 제거 기능을 필수로 가진다고 볼 수 있다.

 

 

값 타입 컬렉션의 제약사항
• 값 타입은 엔티티와 다르게 식별자 개념이 없다.
• 값은 변경하면 추적이 어렵다.
• 값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다.
• 값 타입 컬렉션을 매핑하는 테이블은 모든 컬럼을 묶어서 기본 키를 구성해야 함: null 입력X, 중복 저장X

 

 

값 타입 컬렉션 대안
• 실무에서는 상황에 따라 값 타입 컬렉션 대신에 일대다 관계를 고려
• 일대다 관계를 위한 엔티티를 만들고, 여기에서 값 타입을 사용
• 영속성 전이(Cascade) + 고아 객체 제거를 사용해서 값 타입 컬 렉션 처럼 사용
• EX) AddressEntity

 

 


정리
• 엔티티 타입의 특징
• 식별자O
• 생명 주기 관리
• 공유
• 값 타입의 특징
• 식별자X
• 생명 주기를 엔티티에 의존
• 공유하지 않는 것이 안전(복사해서 사용)
• 불변 객체로 만드는 것이 안전

항상 new 새롭게 생성하고, 수정시에는 기존것을 제거후 수정치한다.

 

 

Role

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Role {

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    @Column
    private Long id;
    private String name;

    /**
     * 다음 코드로 role_perm 테이블이 생성되며
     * 1.role_id 컬럼과 2."perm" 컬럼 이 생성된다.
     */
    @ElementCollection
    @CollectionTable(
            name="role_perm", // role_perm 테이블 이름
            joinColumns = @JoinColumn(name="role_id") //1.role_id 컬럼
    )
    @Column(name="perm") //2."perm" 컬럼
    private Set<String> permissions=new HashSet<>();

    public Role(String name,  Set<String> permissions) {
        this.name = name;
        this.permissions=permissions;
    }
}

 

RoleRepository

import org.springframework.data.jpa.repository.JpaRepository;
import study.datajpa.entity.Role;

public interface RoleRepository  extends JpaRepository<Role, Long> {

    public Role findByName(String name);
}

 

RoleTest

package study.datajpa.entity;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;
import study.datajpa.repository.RoleRepository;

import javax.persistence.EntityManager;
import java.util.Set;


@SpringBootTest
@Transactional
@Rollback(value = false)
class RoleTest {
    @Autowired
    RoleRepository roleRepository;

    @Autowired
    EntityManager em;
    @Test
    public void 데이터등록() throws Throwable {
        Role role1=new Role("ADMIN" , Set.of("F1", "F2"));
        roleRepository.save(role1);

        Role role2=new Role("GENERAL", Set.of("F3", "F4"));
        roleRepository.save(role2);

        roleRepository.findByName("ADMIN");
        Role admin = roleRepository.findByName("ADMIN");
        System.out.println("roleName = " + admin.getPermissions());
    }

}

 

/* insert collection row study.datajpa.entity.Role.permissions */ insert into role_perm (role_id, perm) values (?, ?)
/* insert collection row study.datajpa.entity.Role.permissions */ insert into role_perm (role_id, perm) values (1, 'F1');

 

 

 

 

 

 

 

 

 

9.JPA 기초 08 값 콜렉션 Set 매핑

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Choice 객체 생성 후  @Embeddable

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

10.JPA 기초 08 값 콜렉션 Set 매핑

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

11.JPA 기초 11 값 콜렉션 주의사항

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

참고값 타입은 변경 불가능하게 설계해야 한다.

 

> @Setter 를 제거하고, 생성자에서 값을 모두 초기화해서 변경 불가능한 클래스를 만들자. JPA 스펙상 엔티티나 임베디드 타입( @Embeddable )은 자바 기본 생성자(default constructor)를 public 또는 protected 로 설정해야 한다. public 으로 두는 것 보다는 protected 로 설정하는 것이 그나마 더  안전하다.


> JPA가 이런 제약을 두는 이유는 JPA 구현 라이브러리가 객체를 생성할 때 리플랙션 같은 기술을 사용할 수 있도록 지원해야 하기 때문이다.

 

참조 :  https://macaronics.net/index.php/m01/spring/view/2055

 

 

 


다대일 엔티에서  상관이 없으나   일대 다 엔티인  컬렉션에  문제가 발생한다.


1.지연 전략을 사용한다.
2. DISTINCT는 중복된 결과를 제거하는 명령을 사용한다.
3. 페치 조인을 사용해서 데이터를 가져오면 되지만. 페이징 처리에서 페이징 API(setFirstResult, setMaxResults)를 사용할 수 없다.

해결 방법: 
페치 조인을 풀고, _batch_fetch_siz 전략을 통해 데이트를 가져온다.


#spring.jpa.properties.hibernate.default_batch_fetch_size=100

 


참조: 
https://macaronics.net/index.php/m01/spring/view/2054

 

 

 

 

 

 

 

 

 

 

 

 

 

 

12.JPA 기초 12 영속 컨텍스트 & 라이프사이클

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

13.JPA 기초 13 엔티티 연관 매핑 시작에 앞서

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

14.JPA 기초 14 엔티티 간 1-1 단방향 연관 매핑

 

항상  지연로딩   fetch = FetchType.LAZY 을 사용해라

 

 

 

 

 

 

 

 

 

참조키 방식 1-1 단방향 연관 매핑

 

 

 

 

 

 

 

 

 

 

 

 

 

식별자 공유  방식 1-1 단방향 연관 매핑

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

15.JPA 기초 15 엔티티 간 N-1 단방향 연관 매핑

 

항상  지연로딩   fetch = FetchType.LAZY 을 사용해라

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

16.JPA 기초 16 엔티티 간 1-N 단방향 연관 매핑

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

17.JPA 기초 17 영속성 전파 & 연관 고려사항

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

spring

 

about author

PHRASE

Level 60  라이트

호화로운 임금의 수레도 부서지듯 우리 몸도 늙으면 허물어진다. 오로지 덕행을 쌓아 가는 일만이 이 괴로움에서 벗어나는 길이다. -법구경

댓글 ( 4)

댓글 남기기

작성