👩🏻‍💻 Programming/SpringBoot

Entity의 Listener

한국의 메타몽 2021. 9. 5. 18:52

 

요약

 

Annotation Description
@PrePersist insert 메소드가 호출되기 전에 실행
@PreUpdate merge 메소드가 호출되기 전에 실행
@PreRemove Delete 메소드가 호출되기 전에 실행
@PostPersist Persist 메소드가 호출된 이후에 실행
@PostUpdate Merge 메소드가 호출된 이후에 실행
@PostRemove Delete 메소드가 호출된 이후에 실행
@PostLoad Select 조회가 실행된 직후에 실행

 

 


 

 

[사용 예시]

    // User.java
    @PrePersist
    public void prePersist(){
        System.out.println(">>>>> prePersist");
    }

    @PostPersist
    public void postPersist(){
        System.out.println(">>>>> postPersist");
    }

    @PreUpdate
    public void preUpdate(){
        System.out.println(">>>> preUpdate");
    }

    @PostUpdate
    public void postUpdate(){
        System.out.println(">>>>> postUpdate");
    }

    @PreRemove
    public void preRemove(){
        System.out.println(">>>>> postRemove");
    }

    @PostRemove
    public void postRemove(){
        System.out.println(">>>>> postRemove");
    }

    @PostLoad
    public void postLoad(){
        System.out.println(">>>> postLoad");
    }

 

 

[JUnit Test Code]

    @Test
    void listenerTest(){
        User user = new User();
        user.setEmail("martin2@fastcampus.com");
        user.setName("martin");

        userRepository.save(user);
        User user2 = userRepository.findById(1L).orElseThrow(RuntimeException::new);
        user2.setName("marrrrrtin");

        userRepository.save(user2);
        userRepository.deleteById(4L);
    }

 

 

[사용 결과]

>>>>> prePersist
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        user
        (created_at, email, name, updated_at, id) 
    values
        (?, ?, ?, ?, ?)
>>>>> postPersist
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.created_at as created_2_1_0_,
        user0_.email as email3_1_0_,
        user0_.name as name4_1_0_,
        user0_.updated_at as updated_5_1_0_,
        addresses1_.user_id as user_id1_2_1_,
        address2_.id as addresse2_2_1_,
        address2_.id as id1_0_2_ 
    from
        user user0_ 
    left outer join
        user_addresses addresses1_ 
            on user0_.id=addresses1_.user_id 
    left outer join
        address address2_ 
            on addresses1_.addresses_id=address2_.id 
    where
        user0_.id=?
>>>> postLoad
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.created_at as created_2_1_0_,
        user0_.email as email3_1_0_,
        user0_.name as name4_1_0_,
        user0_.updated_at as updated_5_1_0_ 
    from
        user user0_ 
    where
        user0_.id=?
>>>> postLoad
Hibernate: 
    select
        addresses0_.user_id as user_id1_2_0_,
        addresses0_.addresses_id as addresse2_2_0_,
        address1_.id as id1_0_1_ 
    from
        user_addresses addresses0_ 
    inner join
        address address1_ 
            on addresses0_.addresses_id=address1_.id 
    where
        addresses0_.user_id=?
>>>> preUpdate
Hibernate: 
    update
        user 
    set
        created_at=?,
        email=?,
        name=?,
        updated_at=? 
    where
        id=?
>>>>> postUpdate
Hibernate: 
    select
        user0_.id as id1_1_0_,
        user0_.created_at as created_2_1_0_,
        user0_.email as email3_1_0_,
        user0_.name as name4_1_0_,
        user0_.updated_at as updated_5_1_0_,
        addresses1_.user_id as user_id1_2_1_,
        address2_.id as addresse2_2_1_,
        address2_.id as id1_0_2_ 
    from
        user user0_ 
    left outer join
        user_addresses addresses1_ 
            on user0_.id=addresses1_.user_id 
    left outer join
        address address2_ 
            on addresses1_.addresses_id=address2_.id 
    where
        user0_.id=?
>>>> postLoad
>>>>> postRemove
Hibernate: 
    delete 
    from
        user 
    where
        id=?
>>>>> postRemove

 

 

현업에서는

 

@PrePersist(insert 메소드가 실행되기 전), @PreUpdate(merge 메소드가 실행되기 전)가 현업에서 많이 사용된다.

실제로 저장되기 이전, 수정되기 이전에 로그를 남기기 위해 사용되며 일명 Auditing, 즉, 감시 역할로 사용된다.

 

예컨데 아래 코드에서

    @PrePersist
    public void prePersist(){
        System.out.println(">>>>> prePersist");
    }

다음과 같이 변경한다면

    @PrePersist
    public void prePersist(){
        System.out.println(">>>>>>prePersist");
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }

그리고 JUnit 테스트 코드에서 다음과 같이 작동시킨다면

    @Test
    void prePersisTest(){
        User user = new User();
        user.setEmail("martin2@fastcampus.com");
        user.setName("martin");
        userRepository.save(user);
        System.out.println(userRepository.findByEmail("martin2@fastcampus.com"));
    }

아래와 같은 결과를 볼 수 있다.

>>>>>>prePersist
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        user
        (created_at, email, name, updated_at, id) 
    values
        (?, ?, ?, ?, ?)
Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.created_at as created_2_1_,
        user0_.email as email3_1_,
        user0_.name as name4_1_,
        user0_.updated_at as updated_5_1_ 
    from
        user user0_ 
    where
        user0_.email=?
Hibernate: 
    select
        addresses0_.user_id as user_id1_2_0_,
        addresses0_.addresses_id as addresse2_2_0_,
        address1_.id as id1_0_1_ 
    from
        user_addresses addresses0_ 
    inner join
        address address1_ 
            on addresses0_.addresses_id=address1_.id 
    where
        addresses0_.user_id=?
User(id=6, name=martin, email=martin2@fastcampus.com, createdAt=2021-09-05T18:49:59.199715, updatedAt=2021-09-05T18:49:59.199739, addresses=[])

 

User가 새로운 데이터를 삽입하는 시점의 시간을 로그로 남길 수 있다.

물론 수동으로 시간을 출력하는 코드를 별개로 짤 수 있지만,

위와 같인 방식으로 작성하면 코드가 보다 간결하고 휴먼 에러를 낮출 수 있다.

'👩🏻‍💻 Programming > SpringBoot' 카테고리의 다른 글

JPA - N대 1 연관관계  (0) 2021.09.12
Entity, DTO, 그리고 DAO  (0) 2021.09.05
Entity의 기본 속성(annotation)  (0) 2021.09.05
Pageable과 Page Request  (0) 2021.09.05
JPA  (0) 2021.08.29