WEB JAVA SPRING/PROJECT

[Day-5] 엔티티 클래스 개발2

sshhhh 2023. 8. 25.

<엔티티 클래스 개발2>

 

#파일구조

 


 

Category

//카테고리 엔티티
@Entity
@Getter @Setter
public class Category {

    //pk
    @Id @GeneratedValue
    @Column(name="category_id")
    private Long id;

    private String name;

    
    @ManyToMany  // Category엔티티도 List로 items을 가지고, item엔티티도 List로 Category를 가진다.
    //일대다 다대일로 풀어내는 중간테이블이 존재하기 때문에 테이블로 매핑해줘야한다
    @JoinTable(name = "category_item", //중간테이블 이름 정하기
            //매핑
            joinColumns = @JoinColumn(name = "category_id"),//중간테이블과 category테이블 join (fk)
            inverseJoinColumns = @JoinColumn(name = "item_id") //중간테이블에서 item테이블 join (fk)
              )
    private List<Item> items = new ArrayList<>();


    //밑의 둘은 같은 엔티티를 셀프로 양방향 연관관계 매핑
    @ManyToOne
    @JoinColumn(name ="parent_id") //fk
    private Category parent;

    //자식 여러명 가능
    @OneToMany(mappedBy = "parent") //  private Category parent; 여기로 이동
    private  List<Category> child = new ArrayList<>();


}

 


 

이제 작성 끝 실행하기

테이블 생성 완료!

 


 

Address (주소 값 타입)

 

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

-> @Setter 를 제거하고, 생성자에서 값을 모두 초기화해서 변경 불가능한 클래스를 만들자.

//주소
//@Embeddable //JPA의 내장 타입 Member에 썼으니 안써도..
@Getter
public class Address {

    private String city;
    private String street;
    private String zipcode;

/*
JPA 스펙상 엔티티나 임베디드 타입( @Embeddable )은 
자바 기본 생성자(default constructor)를
public 또는 protected 로 설정해야 한다. 
->> JPA가 이런 제약을 두는 이유는 
JPA 구현 라이브러리가 객체를 생성할 때 리플랙션 같은 기술을 사용할 수 있도록 지원해야 하므로
*/

    protected Address() {
    }
    
    public Address(String city, String street, String zipcode) {

      this.city = city;
        this.street = street;
        this.zipcode = zipcode;
    }
}

 


#실무에서는?

실무에서는 가급적 Getter는 열어두고, Setter는 꼭 필요한 경우에만 사용하는 것을 추천
> 이론적으로 Getter, Setter 모두 제공하지 않고, 꼭 필요한 별도의 메서드를 제공하는게 가장 이상적이다. 

하지만 실무에서 엔티티의 데이터는 조회할 일이 너무 많으므로, Getter의 경우 모두 열어두는 것이 편리하다.
 Getter는 아무리 호출해도 호출 하는 것 만으로 어떤 일이 발생하지는 않는다. 

하지만 Setter는 문제가 다르다. Setter를 호출하면 데이터가 변한다. 

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


Setter를 막 열어두면 가까운 미래에 엔티티가 도대체 왜 변경되는지 추적하기 점점 힘들어진다. 


그래서 엔티티를 변경할 때는 Setter 대신에 변경 지점이 명확 하도록 변경을 위한 비즈니스 메서드를 별도로 제공하자. 혹은 나중에 리펙토링으로 제거하자.



실무에서는 @ManyToMany 를 사용하지 말자
> @ManyToMany 는 편리한 것 같지만, 중간 테이블( CATEGORY_ITEM )에 컬럼을 추가할 수 없고, 
세밀하게 쿼리를 실행하기 어렵기 때문에 실무에서 사용하기에는 한계가 있다. 

중간 엔티티( CategoryItem ) 를 만들고 @ManyToOne , @OneToMany 로 매핑해서 사용한다.
정리하면 대다대 매핑을 일대다, 다대일 매핑으로 풀어내 사용하자.



 

 

강의 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1/dashboard

댓글