본문 바로가기

spring boot

실전! 스프링 부트와 JPA 활용1 - 2주차

1. 요구사항 분석 & 2. 도메인 모델과 테이블 설계

 

테이블 설계
엔티티 분석

하나 이상의 속성을 가지며 서로 구별되는 하나의 개체를 엔티티라 한다.

단방향/양방향, 일대일/일대다/다대다 관계를 주목해야 한다.

또, Album, Book, Movie는 같은 속성을 가지므로 Item을 상속하는 구조로 표현했다.


3&4. 엔티티 클래스 개발

 

예제에서는 Getter와 Setter를 모두 열었지만, 실무에서는 Setter를 꼭 필요한 경우에만 사용한다. 이 둘은 안전을 위해 메소드를 통해 필드를 건드리게 해준다.

@Getter : 메소드로 필드값을 가공한 후 외부로 전달

@Setter : 매개값을 검증해서 유효한 값만 객체의 필드로 저장

이게 없으면 public void~~this.a=a;~~이런거 다 작성해줘야 함.

 

#주문 엔티티

package jpabook.jpashop.domain;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;
import java.time.LocalDateTime;

@Entity
@Table(name = "orders") //order -> orders로 테이블명 수정
@Getter @Setter
public class Order {
    @Id
    @GeneratedValue
    @Column(name = "order_id")
    private Long id;
    @ManyToOne(fetch = FetchType.LAZY) //다대일관계, 다==order
    @JoinColumn(name = "member_id")
    private Member member; //주문 회원
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) //일대다관계, order테이블의 Memeber에 의해 mapping,
    private List<OrderItem> orderItems = new ArrayList<>(); //cascade 설정은 orderitem모두에 연결을 안해도 가능하게 만듬.
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "delivery_id")
    private Delivery delivery; //배송정보
    private LocalDateTime orderDate; //주문시간
    @Enumerated(EnumType.STRING)
    private OrderStatus status; //주문상태 [ORDER, CANCEL]
    //==연관관계 메서드==//
    public void setMember(Member member) {
        this.member = member;
        member.getOrders().add(this);
    }
    public void addOrderItem(OrderItem orderItem) {
        orderItems.add(orderItem);
        orderItem.setOrder(this);
    }
    public void setDelivery(Delivery delivery) {
        this.delivery = delivery;
        delivery.setOrder(this);
    }
}

대표적인 코드 하나만 가져왔다.

설명은 간단하게 코드에 주석으로 작성했는데 주의할 점은 교재는 javax지만 jakarta로 바꾸어서 작성해야 한다.

Alt + Enter로 존재하지 않는 엔티티를 Order화면에서 바로 만들 수 있다. 익숙해지면 편리하겠지...

또, 카테고리 엔티티에는 ManyToMany가 존재하는데 실무에서는 절대 쓰지 말라고 한다. 중간테이블에 컬럼 추가나 변경이 어려워서, 보통 중간 엔티티를 만들고 ManyToOne, OneToMany로 매핑해서 사용함.

 

오류없이 성공!


5. 엔티티 설계시 주의점

 

1. 엔티티에는 가급적 Setter 사용하지 않기

  • Setter가 모두 열려있으면 변경 포인트가 많아서 유지보수가 어렵다

2. 모든 연관관계는 지연로딩(LAZY)으로 설정하기

  • 즉시로딩(EAGER)은 예측이 어려우므로 실무에서는 지연로딩으로 설정한다.
  • @XToOne관계는 기본이 즉시로딩이므로 직접 지연로딩으로 설정한다.
  • @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)

3. 컬렉션은 필드에서 초기화하기

  • null 문제에서 안전화하다.
  • 필드레벨에서 생성하는 것이 안전하고 코드도 간결하다.

4. 테이블 컬럼명 생성 전략

  • SpringPhysicalNamingStrategy : 엔티티의 필드명을 그대로 테이블의 컬럼명으로 사용(기존구현, 언더스코어)
  • spring.jpa.hibernate.naming.implict-strategy : 테이블이나 컬럼명을 명시하지 않을 때 논리명 적용
  • @Table, @Column 등
  • spring.jpa.hibernate.naming.physical-strategy : 모든 논리명에 적용(항상 마지막에 적용)

#참고사이트

 

https://velog.io/@mumuni/Hibernate5-Naming-Strategy-%EA%B0%84%EB%8B%A8-%EC%A0%95%EB%A6%AC

 

Hibernate5 Naming Strategy 간단 정리

작성개기 JPA책을 보면서 공부하던 중 Hibernate4 에서 5로 넘어가면서 변경된 내용이 있어 기록에 남기기로 했다. 그렇게 어려운 부분은 아니였지만 일부 예제를 사용하면 NullPointerException를 띄어버

velog.io