JoJun's
Jun's Devlog
JoJun's
전체 방문자
오늘
어제
  • 분류 전체보기 (51)
    • Java (16)
      • SpringBoot (12)
      • Java (4)
    • Linux (11)
      • CentOS (4)
      • 명령어(CentOS) (5)
      • Docker (2)
    • DataBase (15)
      • 튜닝 기법 (1)
      • MSSQL (7)
      • SQLD,SQLP (6)
    • 알고리즘 (4)
      • 정렬 (1)
      • 해시 (1)
      • 완전탐색 (1)
      • 탐욕법 (1)
    • 인프라 (3)
    • Web (2)
    • 개인공간 (0)

블로그 메뉴

  • 홈

공지사항

인기 글

태그

  • cors
  • 알고리즘
  • MSSQL
  • docker
  • @Component
  • Java
  • log4j2
  • Dockerfile
  • 파일그룹
  • springboot

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
JoJun's

Jun's Devlog

[SpringBoot] JPA Entity Listener 엔티티 이벤트 리스너
Java/SpringBoot

[SpringBoot] JPA Entity Listener 엔티티 이벤트 리스너

2022. 4. 26. 12:06
728x90
반응형

YOPLE서비스를 개발하면서 Entity가 저장될 때 또는 조회할 때의 이벤트를 캐치하여 처리를 해야 하는 이슈가 발생했다.

그러던 중 JPA에서 아주 편안한 기능을 제공한다는것을 알게 되었고 포스트로 기록을 남긴다.

 

JPA에서는 Entity에 이벤트가 발생할 때 특정 처리를 할 수 있게 지원한다.

 

Entity Listener

 

Chapter 6. Entity listeners and Callback methods

@PostPersistExecuted after the entity manager persist operation is actually executed or cascaded. This call is invoked after the database INSERT is executed.

docs.jboss.org

 

위 링크 하이버네이트에서는 JPA Entity에 이벤트가 발생할 때 콜백처리를 할 수 있도록 지원해주는 서비스를 EntityListener라고 정의하였다.

 

Entity Event??

엔티티 객체의 이벤트라면 "저장", "조회", "수정", "삭제"의 이벤트를 말한다.   

이벤트 콜백은 JPA에서 어노테이션으로 지원하며 어노테이션의 Target은 Method다.

- Event 실행 전 

  • @PrePersist       : Entity Save ( Insert )가 실행되기 전
  • @PreUpdate      : Entity Save ( Merge )가 실행되기 전
  • @PreRemove     : Entity Delete가 실행되기 전

- Event 실행 이후.

  • @PostPersist      : Entity Save ( Insert )가 실행되고 난 후
  • @PostUpdate     : Entity Save ( Merge )가 실행되고 난 후
  • @PostRemove    : Entity Delete가 실행되고 난 후
  • @PostLoad        : Entity Find가 실행되고 난 후

 

JPA의 사이클 특성상 변수명을 맞추거나 할 필요 없이 Method를 타겟으로하는 어노테이션 기반이므로 메서드명을 자유롭게 작명해도 좋다.

 

해당 글에서는 위의 Entity Listener가 어떻게 작동되는지 몇가지 예로 알아보자.

 

@PostLoad

@PostLoad는 find즉  SELECT 이벤트가 실행되고 난 후에 실행되는 콜백이다.

 

아래는 Entity User의 코드이다.

/**
 * Class       : User
 * Author      : RedJunhee
 * Description : Class Description
 * History     : [2022-04-26] - RedJunhee - Class Create
 */
@Entity
@Table(name = "users")
@Getter
public class User {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @Column(name = "name")
    private String name;

    @Column(name="birthdate")
    private LocalDateTime dateOfBirth;

    @Transient
    private int age;

    @Column(name = "lastUpdate", columnDefinition = "DATETIME")
    private LocalDateTime lastUpdate;

    @Column(name = "signUpDate", columnDefinition = "DATETIME")
    private LocalDateTime signUpDate;

	// 조회 시 자동으로 age 계산 콜백 메서드 정의
    @PostLoad
    public void calculateAge() {

        LocalDateTime now = LocalDateTime.now();

        if ( dateOfBirth != null ) {
            age = now.minusYears(dateOfBirth.getYear()).getYear();
        } else {
            age = 0;
        }
    }

}

 

calculateAge() 메서드는 @PostLoad 어노테이션으로 find를 하게 되면  age를 계산하는 콜백 메서드이다

실제로 SELECT 조회 시 age가 계산되는지 확인해보자.

 

User 테이블에는 아래와 같은 데이터가 존재한다.

ID BIRTHDATE LAST_UPDATE NAME SIGN_UP_DATE
1 2001-01-03 2022-04-04 13:45:33.000 김아무개 1999-05-15 19:33:13.000

 

WebController.Java

import com.map.mutual.side.common.dto.ResponseJsonObject;
import com.map.mutual.side.common.enumerate.ApiStatusCode;
import com.map.mutual.side.common.exception.YOPLEServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
 * Class       : UserController
 * Author      : RedJunHee
 * Description : Class Description
 * History     : [2022-04-26] - RedJunHee - Class Create
 */
@RestController(value = "/web")
public class WebController {

    @Autowired
    private UserService userService;

        @GetMapping("/getuser")
        public ResponseEntity<ResponseJsonObject> smsAuthenticationRequest(
                        @RequestParam(value = "id", required = true) Integer id){

            try {

                User user = userService.getUser(id);

				// 계산된 age 출력
                System.out.println("user age  : " + user.getAge());

            }
            catch(YOPLEServiceException e){
                e.printStackTrace();
                throw e;
            }
            return new ResponseEntity<>(ResponseJsonObject.withStatusCode(ApiStatusCode.OK), HttpStatus.OK);
        }


}

 

UserService.Java

import com.map.mutual.side.common.enumerate.ApiStatusCode;
import com.map.mutual.side.common.exception.YOPLEServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService{

    @Autowired
    UserRepo userRepo;

    public User getUser(Integer id){

		// id 유저 SELECT
        return userRepo.findById(id)
                .orElseThrow(()-> new YOPLEServiceException(ApiStatusCode.SYSTEM_ERROR) );
    }
}

 

UserRepo.Java

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepo extends JpaRepository<User, Integer> {
}

 

자, 준비는 모두 완료되었다.

GET - http://localhost:8080/getuser?id=1 로 실제로 호출해보면 콘솔 창에는 아래와 같이 출력된다.

user age  : 21

 

해당 포스트에서는 @PostLoad만 실제 호출해보았지만 다른 어노테이션도 똑같은 방식으로 사용하면 된다.

 

이런 이벤트 콜백을 지원해주면서 여러 기능이 가능하다

YOPLE서비스에서는 Entity별로 createDate, updateDate와 같은 필드를 가지는 엔티티가 존재하는데 

이런 날짜들은 Entity Event와 빼놓을 수 없는 관계이기에 Listener 기능을 이용해 Entity가 저장될 때, 업데이트될 때

자동적으로 날짜를 바꿔주는 기능으로 많이 사용된다.

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'Java > SpringBoot' 카테고리의 다른 글

[Spring Boot] Spring Cloud GateWay 필터 추가  (0) 2022.06.14
[Spring Boot] Filter  (0) 2022.06.08
[SpringBoot] Exception Handler 예외를 통합관리 하자.!!!  (0) 2022.04.15
[SpringBoot] Log4j2 기본 사용법  (0) 2022.03.07
[SpringBoot] SOP, CORS 이야기  (0) 2022.02.03
    'Java/SpringBoot' 카테고리의 다른 글
    • [Spring Boot] Spring Cloud GateWay 필터 추가
    • [Spring Boot] Filter
    • [SpringBoot] Exception Handler 예외를 통합관리 하자.!!!
    • [SpringBoot] Log4j2 기본 사용법
    JoJun's
    JoJun's
    JoJun's의 기술블로그

    티스토리툴바