본문 바로가기
JPA

[JPA] @Embeddable , @Embedded

by onejunu 2020. 8. 6.
class User{

    private int age;
    private int money;
    private String name;
    private String 초등학교;
    private String 중학교;
    private String 대학교;

...
}

 

User 가 가지고있는 속성이 너무 지저분하고 한눈에 알아보기 힘들다.

 

이때 초등학교,중학교,대학교 는 학교라는 공통적인 속성안에 포함되어 있는 것이므로 학교라는 클래스를 따로 만들어서 관리하면 되지 않을까?

 

class User{

    private int age;
    private int money;
    private String name;
    private 학교 학교정보;

...
}

 

좀더 심플해졌다. 하지만 문제가 있는데 학교정보라는 값이 공유가능한지가 문제이다. 왜냐하면 기존의 값타입들은 공유가 불가능하기 때문에 애초에 신경쓰지 않아도 되었다. 하지만 학교정보는 객체이므로 기본적으로 참조값을 지닌다. 만약 누군가 똑같은 학교정보를 지닌 사람이 갑자기 학교정보를 변경한다고 가정해보자. 그러면 같은 학교정보를 가진 사람의 정보가 모두 같이 바뀐다면 이같은 참사는 없을 것이다.

 

이로써 값타입으로 사용하겠다는 어노테이션이 존재한다. 

바로 @Embedable 과 @Embedded이다. 

 

@Embedable은 정의 부분에 사용하면되고 @Embedded는 사용되느 곳에 쓰면 된다. 

 

@Embedable
class 학교{
    private String 초등학교;
    private String 중학교;
    private String 대학교;
    ...
}


class User{

    private int age;
    private int money;
    private String name;
    
    @Embedded
    private 학교 학교정보;

...
}

 

주의점)

 

만약 User의 학교정보를 수정하고 싶다면 객체를 new 로 생성해서 아예 새로 갈아끼워야한다. 그래야 참조로 인한 부작용이 사라진다.

 

이를 원천적으로 막기 위해 학교 객체를 아래와 같이 정의한다.

 

@Embedable
class 학교{
    private String 초등학교;
    private String 중학교;
    private String 대학교;
    
    
    //setter 없음
    
    protected 학교(){}  //기본생성자를 막음
    
    public 학교(String 초등학교, String 중학교, String 대학교) {
        this.초등학교 = 초등학교;
        this.중학교 = 중학교;
        this.대학교 = 대학교;
    
    }
}

 

기본생성자와 setter만 막아도 사이드이펙트를 막을 수있다.

댓글