우리가 필요한 Entity
에
@MappedSuperclass
public abstract class BaseEntity {
private LocalDateTime createdDate;
private LocalDateTime lastModifiedDate;
}
생성 날짜와 수정날짜가 항상 필요하다고 하자!
그렇다면 이 BaseEntity
를 상속한 클래스는 항상 저장할 때마다 createdDate
를 사용자가 직접 입력해야 하고, 수정할 떄마다 lastModifiedDate
를 입력해야 할까?
그것은 아니다.
그 문제를 해결할 수 있는 방법 2가지가 있다.
@MappedSuperclass
@Getter
public abstract class BaseEntity{
@Column(updatable = false)
private LocalDateTime firstCreatedDate;
private LocalDateTime lastModifiedDate;
@PrePersist
public void prePersist(){
firstCreatedDate=lastModifiedDate=LocalDateTime.now();
}
@PreUpdate
public void preUpdate(){
lastModifiedDate=LocalDateTime.now();
}
}
BaseEntity
를 위와 같이 만들어 준다. 실제 DB 에 들어가는 클래스가 아니므로 실수로 사용할 수 있는 가능성을 방지하고자 abstract
를 붙였다.
@PrePersist
는 본래 Entity
가 생성될 때 DB에 저장되기 전에 실행하는 메서드이지만 이 경우 이 BaseEntity
를 상속받은 클래스가 생성되기 전에 실행이 된다.
main 함수에
EntityManagerFactory emf=Persistence.createEntityManagerFactory("hello");
EntityManager em=emf.createEntityManager();
EntityTransaction tx=em.getTransaction();
tx.begin();
try{
Member member=new Member();
System.out.println("------1-----");
em.persist(member);
System.out.println("------2------");
em.flush();
em.clear();
tx.commit();
}catch (Exception e){
tx.rollback();
}
finally {
em.close();
}
emf.close();
}
위와 같은 코드가 있고 BaseEntity
에 아래와 같은 출력문을 포함시켰다.
@PrePersist
public void prePersist(){
System.out.println("---prePersist-----");
createdDate=lastModifiedDate=LocalDateTime.now();
}
이에 대한 쿼리로
------1-----
---prePersist-----
Hibernate:
/* insert jpa_basic_dionisos198.Member
*/ insert
into
Member
(id, createdBy, createdDate, lastModifiedBy, lastModifiedDate, LOCKER_ID, name)
values
(null, ?, ?, ?, ?, ?, ?)
------2------
이런 순서로 나가는 것을 보았을때 BaseEntity를 상속받은 클래스(Member)가 insert 하기 직전에 @PrePersist
가 실행된다는 것을 알 수 있다.
@PreUpdate
역시 엔티티가 update 하기 전에 항상 실행되는 메서드로
자동으로 createdDate
와 lastModifiedDate
를 집어 넣기에 적합한 메서드이다.
참고로 이렇게 특정 상황이 발생할 때 실행되는 메서드를 콜백 메서드라고 한다.
<결과 화면>
편리하게 jpa를 사용할 수 있게 스프링 데이터 JPA를 사용할 경우 또 다른 방법을 사용할 수 있다.
먼저 아래와 같이 main 메서드 위에 @EnableJpaAuditing
이란 어노테이션을 붙인다.
@SpringBootApplication
@EnableJpaAuditing
public class TestingJpaFunctionApplication {
public static void main(String[] args) {
SpringApplication.run(TestingJpaFunctionApplication.class, args);
}
}
audit는 회계를 감사하다 , 검사하다 등의 뜻을 가지고 있는데 @EnableJpaAuditing
을 붙임으로써 자동적으로 Entity 감사를 활성화 할 수 있다.
@MappedSuperclass
@EntityListeners(value= AuditingEntityListener.class)
@Getter
public abstract class BaseEntity{
@CreatedDate
@Column(updatable = false)
private LocalDateTime firstCreatedDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
}
위와 같이 BaseEntity위에 @EntityListeners(value=AuditingEntityListener.class
를 붙여주어서 사용할 수 있다.
이 BaseEntity
를 상속한 클래스에서 이제 자동으로 firstCreatedDate
와 lastModifiedDate
가 채워진다.