일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 교육기획팀
- 30기
- java
- 객체지향 쿼리 언어
- Domain Driven Design
- scheduling messages with rabbitmq
- 교육기획팀원
- delayed message plugin
- JPQL
- ddd
- 영속성
- 밋업프로젝트
- RESTClient
- springboot
- cicd
- 최범균
- jdbc
- GitHub Actions
- JPA
- rabbitmq-delayed-message-exchange
- 이펙티브자바
- 자바 ORM 표준 JPA 프로그래밍
- 한국대학생it경영학회
- Spring
- 큐시즘
- 도메인 주도 개발 시작하기
- kusitms
- reactive operaton
- Spring Batch
- 자동처리
- Today
- Total
코딩은 마라톤
Entity Listener의 활용 (AuditingEntityListener) 본문
Listener : 이벤트를 관찰하고 있다가 이벤트가 발생하면 콜백 메서드를 통해 특정 동작을 수행한다.
JPA에서는 아래의 7가지 콜백 메서드를 제공한다.
@PrePersist : insert 메소드 수행 전 시행
@PreUpdate : merge 메소드 호출 전 시행
@PreRemove : delete 메소드 호출 전 시행
@PostPersist : insert 메소드 수행 후 시행
@PostUpdate : merge 메소드 수행 후 시행
@PostRemove : delete 메소드 수행 후 시행
@PostLoad : select 조회가 일어난 직후에 실행
보통 @PrePersist와 @PreUpdate를 많이 사용한다. 특히 auditing(감시)할 때 사용한다.
예시
엔티티의 생성 시간(createdAt)과 수정 시간(updatedAt)을 설정할 때, setter를 이용하여 날짜 데이터를 입력할 수 있다.
그러나 단순한 날짜 데이터를 등록 / 수정하는 코드가 반복되기 때문에
Listener를 사용함으로써 DRY(Dont Repeat yourself) 원칙에 따라 중복을 최소화할 수 있고 코드의 재사용성을 높일 수 있다.
기존 (setter)
User user = new User();
user.setEmail("han@abc.com");
user.setName("han");
user.setCreatedAt(LocalDateTime.now());
user.setUpdatedAt(LocalDateTime.now());
보완 (Listener)
@Entity
@EntityListeners(value = AuditingEntityListener.class)
public class User {
...
@Column(updatable = false)
@CreatedDate // 자동으로 시간 값을 지정
private LocalDateTime createdAt;
@Column
@LastModifiedDate // 자동으로 시간 값을 지정
private LocalDateTime updatedAt;
}
Spring에서 제공해주는 기본 EntityListener인 AuditingEntityListener 클래스를 이용한다.
생성 시간에는 @CreatedDate, 수정 시간에는 @LastModifiedDate 어노테이션을 붙여준다.
(생성과 수정에 누가 관여했는지 보여주는 @CreatedBy, @LastModifiedBy 또한 존재한다.)
@SpringBootApplication
@EnableJpaAuditing // Auditing 활성화
public class BookmanagerApplication {
public static void main(String[] args) {
SpringApplication.run(BookmanagerApplication.class, args);
}
}
Main 클래스에 @EnableJpaAuditing을 사용하면 활성화된다.
결과
@Test
void userHistoryTest(){
User user = new User();
user.setEmail("han@abc.com");
user.setName("han");
// insert
userRepository.save(user);
// update
user.setName("New Han");
userRepository.save(user);
userHistoryRepository.findAll().forEach(System.out::println);
}

엔티티가 생성되거나 수정될 때 setter를 이용해 반복해서 수행하지 않고 AuditingEntityListener를 이용하여 자동으로 시간이 설정되게 할 수 있다.
*추가 보완*
여러 엔티티에 @CreatedDate, @LastModifiedDate를 각각 다는 것 또한 중복되기 때문에,
1. 기본 엔티티를 만든다.
2. 기본 엔티티에 엔티티리스너를 연결한다.
3. 각 엔티티에서 기본 엔티티를 상속 받는다.
위와 같은 방식을 진행하는 것을 추천한다.
@Data
@MappedSuperclass // 해당 클래스의 필드를 상속받는 엔티티의 컬럼으로 포함시키는 어노테이션
@EntityListeners(value = AuditingEntityListener.class)
public class BaseEntity {
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
}
기본 엔티티(BaseEntity)를 만들고 엔티티리스너(AuditingEntityListener)를 연결한다.
각 엔티티에서의 createdAt과 updatedAt이 중복되는 것을 막기 위해 기본 엔티티에 시간을 추가하고,
@MappedSuperclass를 사용하여 해당 클래스의 필드를 상속받는 엔티티의 컬럼으로 포함시킨다.
@Entity
@NoArgsConstructor
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
//@EntityListeners(value = AuditingEntityListener.class)
public class UserHistory extends BaseEntity implements Auditable {
@Id
@GeneratedValue
private Long id;
private Long userId;
private String name;
private String email;
// @CreatedDate
// private LocalDateTime createdAt;
//
// @LastModifiedDate
// private LocalDateTime updatedAt;
}
BaseEntity를 상속받기 때문에 @EntityListener와 createdAt 그리고 updatedAt은 사용하지 않는다.
또한 상속 받을 때 @Data의 에러가 발생한다.
(이 클래스가 java.lang.Object를 확장하지 않은 경우에도 상위 클래스를 호출하지 않고 equals/hashCode 구현을 생성합니다. 의도적인 경우에는 타입에 '(call Super=false)'를 추가하세요. )
따라서 @ToString과 @EqualsAndHashcode 어노테이션에 (callSuper = true)라는 조건을 설정하여 상속을 통한 에러를 처리한다.
결과

'Backend > JPA' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍] 5장. 연관관계 매핑 기초 (0) | 2024.02.04 |
---|---|
[자바 ORM 표준 JPA 프로그래밍] 4장. 엔티티 매핑 (0) | 2024.02.02 |
[자바 ORM 표준 JPA 프로그래밍] 3장. 영속성 관리 (0) | 2024.01.29 |
[자바 ORM 표준 JPA 프로그래밍] 2장. Java + Gradle 설정 (1) | 2024.01.28 |
[자바 ORM 표준 JPA 프로그래밍] 1장. JPA 소개 (1) | 2024.01.27 |