테이블 설계 시 공통으로 들어가는 생성일자, 수정일자, 생성자, 수정자 등을 자동으로 입력해주는 기능
Auditing 기능 활성화에는 2가지 방법이 있다.
@EnableJpaAuditing
@Configuration
public class JpaAuditingConfiguration {
}
@EnableJpaAuditing
@SpringBootApplication
public class FinalApplication {
public static void main(String[] args) {
SpringApplication.run(FinalApplication.class, args);
}
}
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
🚨 에러
@WebMvcTest
테스트 시 JPA metamodel must not be empty! 에러가 발생했다.
@WebMvcTest
테스트는 JPA생성과 관련된 기능이 전혀 존재하지 않는 테스트 어노테이션이다.
테스트를 돌릴때는 기본적으로 Application이 돌면서 작동한다. 따라서@EnableJpaAuditing
을 Application위에 올리면 Jpa관련된 빈들이 올라오기를 요구한다. 이때, mockMvc를 사용한 테스트는 mvc와 관련한 빈들만 찾아서 올리므로 JPA관련 빈을 찾지 못해서 JPA metamodel must not be empty 에러가 발생한다.
❗️ 해결
configuration 클래스를 생성하여 분리하거나 테스트 코드 클래스마다@MockBean(JpaMetamodelMappingContext.class)
추가해주면 된다.
@Getter
@Setter
@ToString
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createAt;
@LastModifiedDate
@Column
private LocalDateTime lastModifiedAt;
}
@MappedSuperclass
: JPA Entity클래스가 해당 추상 클래스를 상속할 경우 자식클래스에게 매핑 정보 전달(부모 필드를 컬럼으로 인식)@EntityListeners
: 엔티티를 DB에 적용하기 이전, 이후에 콜백 리스너를 요청@CreatedDate
, @LastModifiedDate
: 인스턴스가 생성, 수정되는 것을 감지하여 감지된 일자를 저장@CreatedBy
, @LastModifiedBy
: 생성자, 수정자@Column(updatable = false)
: SQL UPDATE문에 해당 컬럼을 포함할지 여부(읽기 전용 필드라고 생각하면 된다.)@Builder
@Entity
@Getter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class Post extends BaseEntity {
@Id@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "post_id")
private Long id;
private String body;
private String title;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "user_id")
private User user;
}
extends 해주면 Auditing 기능이 적용된다
생성자와 수정자는 특정테이블에서만 필요한 경우가 많다. 따라서 아래와 같이 Base타입을 분리하여 원하는 타입을 선택해서 상속받으면 된다.
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
}
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity extends BaseEntity {
@CreatedBy
@Column(updatable = false)
private String createdBy;
@LastModifiedBy
private String lastModifiedBy;
}