엔티티 클래스 개발
📘스프링부트
모든 도메인을 묶기 위해 페키지 설정
main-java-jpabook.jpashop-domain이라는 페키지생성
컬럼명 설정, Embedded
Member 엔티티 생성
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name ="member_id") //컬럼명설정
private Long id; // member_id로 설정됨
private String name;
@Embedded ////Address클래스를 값타입 객체를 엔티티로 승격하여도 되지만,
값타입의 엔티티 승격은 식별자(id)와 지속적인 추적이 필요한 경우에 진행해야한다.
예제에서의 주소는 잘 변하지 않는 데이터로 간주하여 값타입으로 설계하였다.
private Address address;
private List<Order> orders = new ArrayList<>();
}
이 테이블 안에는 Member_id, name , adress(city,street,zipcode)가 생성된다.
Embeddable
Member안에있는 address클래스 생성
@Embeddable //Address클래스를 값타입 객체를 엔티티로 승격하여도 되지만,값타입의 엔티티 승격은 식별자(id)와 지속적인 추적이 필요한 경우에 진행해야한다.예제에서의 주소는 잘 변하지 않는 데이터로 간주하여 값타입으로 설계하였다.
@Getter //참고: 값 타입은 변경 불가능하게 설계해야 한다.
// @Setter 를 제거하고, 생성자에서 값을 모두 초기화해서 변경 불가능한 클래스를 만들자
public class Address {
private String city;
private String street;
private String zipcode;
protected Address() {
}
public Address(String city, String street, String zipcode) {
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
}
테이블명 바꾸기, 엔티티 관계(m:1),FK값 설정,Enumerated, fetch ,cascade ,연관관계 메서드
order엔티티생성
@Entity
@Table(name="orders") //테이블 명을 orders로 바꾼다
@Getter @Setter
public class Order {
@Id @GeneratedValue
@Column(name = "order_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY) //다대일 관계
@JoinColumn(name = "member_id")
//여기의 값이 바뀌면 FK의 값이 변경됨
private Member member; // member_id로 변경 member의 FK값이 됨
@OneToMany(mappedBy = "order",cascade = CascadeType.ALL))
private List<OrderItem> orderItems = new ArrayList<>();
@OneToOne
@JoinColumn(name="delivery_id")//Fk설정
private Delivery delivery;
private LocalDateTime orderDate;
@Enumerated(EnumType.STRING)//enum타입을 String으로 설정(ordinal은 쓰지말것,숫자로 정의하는 거라 중간에 추가되면 에러발생
private OrderStatus status; //주문상태 [ORDER,CANCEL],class가 아닌 enum으로 정의
//enum 이란 관련이 있는 상수들의 집합,String과 같은 문자열이나 숫자들을 나타내는 기본 자료형의 값을 고정할수 있다.
//==연관관계 메서드==//
public void setMember(Member member){
this.member = member;
}
public void addOrderItem(OrderItem orderItem){
orderItems.add(orderItem);
orderItem.setOrder(this);
}
public void setDelivery(Delivery delivery){
this.delivery = delivery;
delivery.setOrder(this);
}
}
fetch = FetchType.LAZY란, 즉시로딩( EAGER )은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어렵다. 특히 JPQL을 실행할 때 N+1 문제가 자주 발생한다. 실무에서 모든 연관관계는 지연로딩( LAZY )으로 설정해야 한다. 연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join 또는 엔티티 그래프 기능을 사용한다 @XToOne(OneToOne, ManyToOne) 관계는 기본이 즉시로딩이므로 직접 지연로딩으로 설정해야 한 다
cascade란 , Order를 저장할때 orderItem과 delivery가 자동으로 저장된다 Order을 사용하지 않으면 orderItem,delivery가 저장되고 Order에 또 저장된다. ex)사용하지 않았을경우 persist(oderItemA) persist(oderItemB) persist(oderItemC) persist(order) 사용했을경우 persist(order)
연관관계 메서드란 양방항 연관관계일때 연관관계 메서드가 있으면 좋다. 양방향으로 세팅해줌
enum 생성
rderStatus라는 enum 생성
public enum OrderStatus {
ORDER,CANCEL
}
Inheritance, DiscriminatorColumn, 추상클래스 만들어서 자식들한테 상속시키기
item 엔티티 생성
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)//table하나에 다 넣는 방법
@DiscriminatorColumn(name="dtype") //Album(A),Movie(M),Book(B)중 무엇을 선택했는지 나오는 방법
@Getter @Setter
public abstract class Item {//추상클래스로 만들기 (abstract)
@Id @GeneratedValue
@Column(name = "item_id")
private Long id;
private String name;
private int price;
private int stockQuantity;
@ManyToMany(mappedBy = "items")
private List<Category> categoryies = new ArrayList<>();
}
상속받기, DiscriminatorValue
item 테이블에 넣을 클래스들 정의
Album클래스
@Entity
@DiscriminatorValue("A")
@Getter @Setter
public class Album extends Item {
private String artist;
private String etc;
}
Book클래스
@Entity
@DiscriminatorValue("B")
@Getter
@Setter
public class Book extends Item {
private String author;
private String isbn;
}
Movie클래스
@Entity
@DiscriminatorValue("M")
@Getter
@Setter
public class Movie extends Item {
private String director;
private String actor;
}
아키텍처
계층형 구조 사용 controller,web : 웹 계층 service : 비지니스 로직,트랜잭션 처리 repository : JPA를 직접 사용하는 계층, 엔티티 매니저 사용 domain : 엔티티가 모여 있는 계층, 모든 계층에서 사용 패키지 구조 jpabook.jpashop *domain *exception *repository *service *web