Entity Listener 를 사용하여
User 테이블에 변경사항이 생길 경우
해당 히스토리를 저장하는 실습!
JPA 엔티티에 대한 이벤트 리스너를 등록
하는 어노테이션이다.
이 어노테이션을 사용하여
엔티티의 생명주기 이벤트를 수신하고
이벤트가 발생할 때 특정 동작을 수행할 수 있다.
아래 나타날 코드에서는 @EntityListener 어노테이션과,
@EntityListener 어노테이션에 할당 할
UserEntityListener 클래스를 작성하고 테스트한다.
해당 엔티티가 영속화 될 때
UserHistory 엔티티를 동작시키는 이벤트를 발생시키기 위해
@EntityListeners(value = UserEntityListener.class)
어노테이션을 붙여준다.
@ToString(callSuper = true)
@Getter
@Setter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(value = UserEntityListener.class) // 엔티티 리스너 부착!
@Table(name = "Users")
public class User extends BaseEntity {
private String name;
private String email;
}
@ToString(callSuper = true)
@Entity
@Getter
@Setter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class UserHistory extends BaseEntity{
@Enumerated(EnumType.STRING) private UserStatus status;
private Long userId;
private String name;
private String email;
@Column(name = "USER_CREATED_AT") private LocalDateTime userCreatedAt;
@Column(name = "USER_UPDATED_AT") private LocalDateTime userUpdatedAt;
}
JPA 엔티티의 생명주기에
콜백 메서드를 작성할 수 있게 해주는 어노테이션이 있다.
1 . JPA 엔티티 생명주기 에서 각각 영속화 되기 전
에 반응하는
Pre
어노테이션들
@PrePersist
@PreUpdate
@PreRemove
2 . JPA 엔티티 생명주기 에서 각각 영속화 된 후
에 반응하는
Post
어노테이션들
@PostPersist
@PostUpdate
@PostRemove
여기에서
Persist
는 create 될 때,
Update
는 update 될 때,
Remove
는 delete 될 때 반응한다.
이 중에서도
실무에서 자주 사용되는 어노테이션은
@PrePersist
와 @PreUpdate
라고 한다.
이러한 어노테이션을 이용해서
User 엔티티가 업데이트 될 때
UserHistory를 업데이트하는 UserEntityListener를 작성해본다.
public class UserEntityListener {
private UserHistoryRepository userHistoryRepository;
@PrePersist
public void prePersist(Object o) {
save((User) o, UserStatus.CREATE);
}
@PreUpdate
public void preUpdate(Object o) {
save((User) o, UserStatus.UPDATE);
}
@PreRemove
public void preRemove(Object o) {
save((User) o, UserStatus.DELETE);
}
private void save(User user, UserStatus status) {
if (userHistoryRepository == null)
userHistoryRepository = BeanUtils.getBean(UserHistoryRepository.class);
userHistoryRepository.save(
UserHistory.builder()
.status(status)
.userId(user.getId())
.name(user.getName())
.email(user.getEmail())
.userCreatedAt(user.getCreatedAt())
.userUpdatedAt(user.getUpdatedAt())
.build()
);
}
}
EntityListener 객체는 Bean 등록이 불가능해서 ,
UserHistoryRepository 객체를 주입받을 수 없기 때문에,
BeanUtil을 만들어서
BeanUtil을 통해 UserHistoryRepository를 가져와 사용한다.
@Component
public class BeanUtils implements ApplicationContextAware {
static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
BeanUtils.applicationContext = applicationContext;
}
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
}
@Test
void userHistoryTest() {
User user = User.builder()
.name("zhyun")
.email("gimwlgus@gmail.com")
.build();
// new insert
userRepository.save(user);
// update
user.setEmail("zhyun@gmail.com");
userRepository.save(user);
// delete
userRepository.deleteById(2001L);
// userHistory 데이터 확인
userHistoryRepository.findAll().forEach(System.out::println);
}
UserHistory(super=BaseEntity(id=1, createdAt=2023-06-16T00:38:30.273039, updatedAt=2023-06-16T00:38:30.273039), status=CREATE, userId=null, name=zhyun, email=gimwlgus@gmail.com, userCreatedAt=2023-06-16T00:38:30.253169, userUpdatedAt=2023-06-16T00:38:30.253169)
UserHistory(super=BaseEntity(id=2, createdAt=2023-06-16T00:38:30.429954, updatedAt=2023-06-16T00:38:30.429954), status=UPDATE, userId=2001, name=zhyun, email=zhyun@gmail.com, userCreatedAt=2023-06-16T00:38:30.253169, userUpdatedAt=2023-06-16T00:38:30.429954)
UserHistory(super=BaseEntity(id=3, createdAt=2023-06-16T00:38:30.454453, updatedAt=2023-06-16T00:38:30.454453), status=DELETE, userId=2001, name=zhyun, email=zhyun@gmail.com, userCreatedAt=2023-06-16T00:38:30.253169, userUpdatedAt=2023-06-16T00:38:30.429954)
보고 배운 인강
오 링크가 404가 되었다..!
이럴땐 어떡해야 하지;
일단 저장..🙈;
보고 배운 인강이 판매가 중단된 것 같다.
사이트를 다 뒤져봤는데 안보임!!
여기서 사용한 코드는
강현호 강사님이 알려주신 내용을 학습한 후에 작성한 코드이다!