[Spring] Entity Mapping

호호빵·2022년 6월 22일
0

Spring

목록 보기
10/24

Entity

  • 필요하고 유용한 정보르 저장하고 관리하기 위한 집합적인 것
  • @Entity가 붙은 클래스는 JPA가 관리
유일한 식별자에 의해 식별가능해야 함
영속적으로 존재하는 인스턴스의 집합이어야 함(2개 이상)
반드시 속성이 있어야 함
다른 엔티티와 최소한 한 개 이상의 관계가 있어야 함

영속성 컨텍스트(Persistance Context)

  • 엔티티를 영구저장하는 환경
  • 어플리케이션과 DB 사이에서 객체를 보관하는 가상의 데이터베이스 같은 역할
  • 엔티티 매니저가 영속성 컨텍스트에 엔티티를 보관하고 관리
  • 엔티티 매니저를 생성할 때 하나 만들어 짐.
  • 엔티티 매니저를 통해서 영속성 컨텍스트에 접근, 관리 가능
Context 
- 호출, 응답 간의 환경 정보라고 정의
- 누가 무엇을 어떤 의도를 가지고 언제 행위를 하였는지에 대한 정보를 통칭
- 일반적인 환경설정 정보와 다르게 런타임시에 생성되는 정보

필드와 컬럼 매핑

@Entity
public class Member2 {
    
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
    
    private String username;
    
    @Enumerated(EnumType.STRING)
    private RoleType roleType;
    
    @Temporal(TemporalType.TIMESTAMP)
    private Date cereatedDate;
    
    private LocalDate lastModifiedDate;
    
    @Lob
    private String description;

		@Transient
		private int tmp_number;
}

@Enumerated

  • 자바 Enum 타입을 매핑할 때 사용
  • ORDINAL 타입을 사용하지 말자.
    → enum타입이 추가,변경,삭제 되어 순서가 달라질 경우 사이드 이펙트가 생긴다.
  • EnumType.ORDINAL: ENUM 순서를 데이터베이스에 저장
  • EnumType.STRING: ENUM 이름을 데이터베이스에 저장

@Temporal

  • 날짜 타입(Date, Calendar)을 매핑할 때 사용
  • LocalDate(년월), LocalDateTime(년월일)을 사용할 때는 생략 가능(최신 하이버네이트 지원)

@Lob

  • 데이터베이스 BLOB, CLOB 타입과 매핑
  • 매핑하는 필드 타입이 문자면 CLOB, 나머지는 BLOB매핑
  • CLOB: String, char[], java.sql.CLOB
  • BLOB: byte[], java.sql.BLOB

@Transient
필드 매핑이 안되게 하는 어노테이션

@Column - 제일 자주 쓰이는 어노테이션

  • 속성
    a. name: 필드와 매핑할 테이블의 컬럼 이름
    b. insertable, updatable: 등록, 변경 가능여부
    c. nullable: null 허용 여부(false로 하면 not null 조건이 붙는다)
    d. unique: @Table의 uniqueConstrainst 와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용
    → 사용 빈도가 낮다(제약조건의 이름이 너무 난수값이라 알아보기 힘듬)
    → @Table(uniqueConstraint())에 사용하는 것을 권장.
    e. columnDefinition: 컬럼 정보를 직접 줄 수 있다.
    f. length: 문자 길이 제약조건. ( String 타입에서만 사용한다)
    g. precision, scale(DDL): BigDecimal 타입에서 사용한다.(아주 큰 숫자)

요구사항 분석과 기본 매핑

요구사항 분석

기능목록

도메인 모델 분석

테이블 설계

엔티티 설계와 매핑

# Member에서 Team 참조
# Member
@Entity
@Getter
@Setter // 사용하지 않는게 좋지만 예제이므로 사용
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
public class Member {

    @Id @GeneratedValue
    @Column(name = "member_id")
    private Long id;
    private String username;
    private int age;

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "team_id")
    private Team team;

    public Member(String username) {
        this.username = username;
    }

    public Member(String username, int age, Team team) {
        this.username = username;
        this.age = age;
        if(team != null){
            changeTeam(team);
        }
    }

    // 팀 변경
    public void changeTeam(Team team){
        this.team = team;
        team.getMembers().add(this); // 객체기 때문에 반대쪽에도 바꿔줘야함
    }
}

# Team
@Entity
@Getter
@Setter // 사용하지 않는게 좋지만 예제이므로 사용
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "name"})
public class Team {

    @Id @GeneratedValue
    @Column(name = "team_id")
    private Long id;
    private String name;

    @OneToMany(mappedBy = "team") // db 연관관계 세팅: mappedBy는 FK가 없는쪽에 걸어주는게 좋다
    private List<Member> members = new ArrayList<>();

    public Team(String name) {
        this.name = name;
    } 
}

# Test
@SpringBootTest
@Transactional  // 테스트 코드에서 사용시 테스트 종료 후 롤백 시킴
@Rollback(value = false)  // 롤백 안시키도록 설정
class MemberTest {

    @PersistenceContext
    EntityManager em; //JPA의 영속성 컨텍스트

    @Test
    public void testEntity(){
        Team teamA = new Team("teamA");
        Team teamB = new Team("teamB");
        em.persist(teamA);
        em.persist(teamB);

        Member merber1 = new Member("member1", 10, teamA);
        Member merber2 = new Member("member2", 20, teamA);
        Member merber3 = new Member("member3", 30, teamB);
        Member merber4 = new Member("member4", 40, teamB);

        em.persist(merber1);
        em.persist(merber2);
        em.persist(merber3);
        em.persist(merber4);

        // 초기화
        em.flush();
        em.clear();

        // 확인
        List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();

        for (Member member : members) {
            System.out.println("member = " + member);
            System.out.println("-> member.team = " + member.getTeam());

        }
    }
}

영속성 컨텍스트
엔티티 매핑
예제도메인모델

profile
하루에 한 개념씩

0개의 댓글