1. @MappedSuperClass
회사 정보를 조회하는 사이트를 구축한다고 해보자.
회사 테이블에도 생성일, 수정일을 넣어야하고
유저에도 개인정보 수정일, 가입일 (createdDate)를 넣어야하는데
지금은 2개의 테이블이지만 생성/수정일을 몇십개의 테이블에 다 넣어야한다면, 저짓을 겁나많이해야된다.
너무귀찮은일임.
@Enttiy
public class Company {
@Id @GeneratedValue
private Long id;
private String name;
private String address;
private LocalDateTime createdDate;
private String createdBy;
private LocalDateTime updatedDate;
private String updatedBy;
}
@Entity
public class User {
@Id @GeneratedValue
private Long userId;
private String name;
private String mobile;
private String email;
private LocalDateTime createdDate;
private String createdBy;
private LocalDateTime updatedDate;
private String updatedBy;
}
보기만 해도 토가나온다.
이것을 안하기위해서 MappedSuperClass 를 써보자
BaseEntity 라는 이름을 써서 만들어줄것임
@MappedSuperClass
public abstract class BaseEntity {
private LocalDateTime createdDate;
private String createdBy;
private LocalDateTime updatedDate;
private String updatedBy;
}
주의할점은 abstract 로 작성해야된다는점임.
이제 이것을 붙여보면
@Enttiy
public class Company extends BaseEntity {
@Id @GeneratedValue
private Long id;
private String name;
private String address;
}
@Entity
public class User extends BaseEntity {
@Id @GeneratedValue
private Long userId;
private String name;
private String mobile;
private String email;
}
짠~
가독성으로만 따져봐도 중요한 변수만 보임!
근데 사이트가 커져서, 회사를 업종별로 select 하고싶어졌다...
별도로 관리를 해줘야한다면? company를 업종별로 나눠야겠지
근데, 어짜피 이름 주소 ...등등 기본적인건 다 쓰니까 그대로두고
업종 + 업종별 unique 컬럼들만 쏙쏙 빼서 관리하고싶다면???
2.@inherited & @DiscriminatorColumn
company 에 pk로 company_id 넣어주고
dtype 이라는 컬럼으로 자식들 구분값 fk로 넣어주는식으로 해야 나중에 select 해올때 dtype 값으로 join 해서 가져오겠지.
이것을 JPA로 구현해보자
일단 기본이 되는 COMPANY 를 생성
@Enttiy
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public class Company extends BaseEntity {
@Id @GeneratedValue
@Column(name = "COMPANY_ID")
private Long id;
private String name;
private String address;
}
새로보는 애노테이션이 있쥬??
@Inheritance 의 InheritanceType 전략에 따라 다양한 테이블을 만들수있음.
지금만드려는건 join 형태의 테이블이니까 JOIN을 쓰지만, SINGLE_TABLE, TABLE_PER_CLASS 전략이 있는데
다른애들은 테이블통째로 만들어서 별로다.
@Inheritance 로 전략을 설정하고
@DiscriminatorColumn으로 부모가 누군지 알려준다. 나대지 못하도록.
글고 부모테이블 (company)에 자식들 구분값을 넣어주는 컬럼을 생성해준다.
DTYPE 이라는 이름으로 자동값으로 생성되는데 이름을 바꿔줘도되지만, 보통은 이걸로 쓰는거같다.
그리고 자식을 만들어주자
@Entity
@DiscriminatorValue("O")
public class Office extends Company {
@Id @GeneratedValue
private Long officeId;
private String businessType;
private String ceo;
}
@Entity
@DiscriminatorValue("S")
public class Store extends Company {
@Id @GeneratedValue
private Long storeId;
private String businessType;
private String cto;
}
@Entity
@DiscriminatorValue("R")
public class Restorant extends Company {
@Id @GeneratedValue
private Long restorantId;
private String businessType;
private String chef;
}
자식은 테이블 따로만들꺼니까 @Entity 달아주고
자식에겐 이름을 지어줘야지.
@DiscriminatorValue 로 이름을 지어준다.
이렇게하면 부모의 DTYPE 컬럼에 discriminatorValue로 설정한 문자들이 박히게된다.
자 여기까지 하면 상속은 왠만한건 다 끝난것같지만? 갑자기 이런녀석도있다.
3. @Embedded
이녀석도 상속하는녀석인데... 대체 님 뭐임?
@MapperSuperClass 형님 어쩔깝쇼??
일단 형님의 특징은 아래와같다.
@Entity 로 선언된 엔티티 클래스는 같은 엔티티클래스 혹은 @MapperSuperClass 로 지정된 클래스만 상속이 가능하다.
형님은 부모클래스는 자식클래스에 매핑정보만 제공하는 역할이다.
또한 단독으로 사용되는 일이 없으므로 추상클래스로 사용하는게 좋고
전체 엔티티에서 공통으로 적용하는 정보를 모을때 사용한다
그럼 샛병아리 @Embedded 는?
@Getter @Setter
@Embeddable
public class Times {
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
}
일단 냅다 만들고
전 쓰여지는 애입니다~ 하는 Embeddable 애노테이션을 달아준다.
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
@Embedded
private Times times;
}
그리고 쓰는곳에서 변수중에 임베디드 할 녀석을 지정해준다.
이렇게되면 @MappedSuperClass 성님처럼 부모노릇은 못하고 노예처럼 사용되게된다 후후
형님은 상속을, 저 햇병아리는 위임을 사용하는것의 차이인데
형님은 감히 우리가 사용하진 못한다. 변경할수가없다.
하지만 임베디드 햇병아리는 변수값을 변경시키거나 사용할때 용이하다. 한 딱까리 한다.
임베디드는 햇병아리답게 사용할때도 좀 복잡하다.
jpql을 쓴다고하면
select u from User u where u.times.createdDate
이렇게 쩜을 겁나찍어줘야됨.
하지만 우리 형님은?
select u from User u where u.createdDate
직관성좋게 한줄이면 된다.
편리함과직관성때문에 조회시에는 형님을, 수정이 필요할때는 임베디드를 사용하면된다.
이해에 도움을 준 블로그
https://velog.io/@rudwnd33/JPA-MappedSuperclass-vs-Embedded-Type
'BackEnd > JAVA' 카테고리의 다른 글
Spring boot Multi module Project (2) - 프로젝트 실행 (1) | 2024.01.22 |
---|---|
Spring boot Multi module Project (1) - 스프링 멀티모듈 프로젝트 생성 (0) | 2024.01.22 |
@Component, @Configuration, @Bean (1) | 2024.01.02 |
@RequestParam, @RequestBody, @ResponseBody (0) | 2024.01.01 |
@Controller, @RestController (0) | 2023.12.31 |