이전 프로젝트에서 테이블의 공통 칼럼을 BaseEntity로 빼고, extends로 다른 Entity에 삽입해서 사용하는 방식을 접한적이 있었다. 새로운 프로젝트에서도 그 방법으로 Entity를 생성하는데 자꾸 오류가 나서 뭐가 문제인지 찾아보도록하자.
Spring Boot에서 Entity를 만들다보면 중복되는 요소가 분명히 존재한다. 이를 해결하기 위해 사용되는것이 BaseEntity이다.
BaseEntity는 이름만 Entity이지 실제로 Entity처럼 테이블이 따로 존재하지 않는다.따라서 본인의 테이블이 생성되지 않고 Entity끼리만 상속해줄 수 있도록 @MappedSuperClass 어노테이션을 이용 해야한다.
// Base Entity
@MappedSuperclass // base entity에는 @Entity가 오면 안되고 해당 어노테이션을 써야한다.
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "created_at")
@CreationTimestamp
private LocalDateTime createdAt;
@Column(name = "updated_at")
@UpdateTimestamp
private LocalDateTime updatedAt;
}
위의 공통 부분만 뽑아놓은 Base Entity를 필요한 Entity에 extends해서 사용하면 된다.
// User Entity
@Entity
@Table(name = "user")
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class User extends BaseEntity {
@Column(name = "email")
private String email;
@Column(name = "name")
private String name;
@Column(name = "password")
private String password;
@Column(name = "is_withdrawal")
private Boolean isWithdrawal;
@Column(name = "authority_id")
private Long authorityId;
}
그리고 yml에서 hibernate ddl-auto설정을 create로 해야 새로 생성, 이후에 update로 수정하거나, none으로 변경해서 수동으로 table을 생성하는 방법을 사용해도 된다.
spring:
application:
name: TripTogether
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/trip_together
username: root
password: *****
jpa:
hibernate:
ddl-auto: create # -> update로 변경
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.MySQL8Dialect
spring:
jpa:
hibernate:
ddl-auto: update
개발 단계에서 빠르게 테이블을 생성하거나 수정이 쉽기 때문에(어플리케이션을 재시작하는 경우 수정, 생성) 초기에 update로 시작해도 된다!
그러나, 운영환경에서는 예상치 못한 변경이 DB에 반영되므로 none으로 변경해야함
따라서, update로 해도 상관은 없지만 프로젝트 초기에는 기존 칼럼의 삭제나 타입 변동등 수정 가능성이 많기 때문에 create로 시작하고 update로 변경을 하는 것이 좋다.
내 프로젝트의 경우에는 BaseEntity에 @Entity 어노테이션이 들어간 것이 문제였다.
Base Entity에는 @Entity 를 적지 않고 @MappedSuperclass를 기입하고, 그를 상속받는 다른 Entity에는 @Entity 어노테이션을 붙여 명시해주도록 하자.