관리 메뉴

제뉴어리의 모든것

JPA Auditing 본문

Spring Boot/JPA

JPA Auditing

제뉴어리맨 2022. 9. 4. 19:10

JPA Auditing이란?

Java에서 ORM 기술인 JPA를 사용하여 도메인을 관계형 데이터베이스 테이블에 매핑할 때 공통적으로 도메인들이 가지고 있는 필드나 컬럼들이 존재합니다. 대표적으로 생성일자, 수정일자, 식별자 같은 필드 및 컬럼이 있습니다.

도메인마다 공통으로 존재한다는 의미는 결국 코드가 중복된다는 말과 일맥상통합니다.
데이터베이스에서 누가, 언제하였는지 기록을 잘 남겨놓아야 합니다. 그렇기 때문에 생성일, 수정일 컬럼은 대단히 중요한 데이터 입니다.

그래서 JPA에서는 Audit이라는 기능을 제공하고 있습니다. Audit은 감시하다, 감사하다라는 뜻으로 Spring Data JPA에서 시간에 대해서 자동으로 값을 넣어주는 기능입니다. 도메인을 영속성 컨텍스트에 저장하거나 조회를 수행한 후에 update를 하는 경우 매번 시간 데이터를 입력하여 주어야 하는데, audit을 이용하면 자동으로 시간을 매핑하여 데이터베이스의 테이블에 넣어주게 됩니다.

1. Auditi 사용 예제 코드

1. build.grade에 의존성 추가

dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.projectlombok:lombok')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
}

기본적으로 스프링 부트에서 gradle로 의존성을 관리하게 될 경우 spring-boot-starter-data-jpa만 추가해도 됨.

 

참고로 자바 1.8 이상부터는 기존의 문제가 있던 Date, Calander 클래스를 사용하지 않고 LocalDate, LocalDateTime 클래스를 사용합니다. 또한 LocalDateTime 객체와 테이블 사이의 매핑이 안되던 이슈는 하이버네이트 5.2 버전부터 해결이 되었습니다.

 


++ 추가 (2022. 10. 06)

위에 의존성을 넣고 Gradle을 새로고침 하니까 아래와 같은 에러가 발생하였다.

 

Could not find method compile() for arguments [org.springframework.boot:spring-boot-starter-web] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler. 

 

그래서 아래와 같이 바꿔주니까 잘 된다.

implementation'org.springframework.boot:spring-boot-starter-web'
implementation'org.projectlombok:lombok'
implementation'org.springframework.boot:spring-boot-starter-data-jpa'

원인은 Gradle 이 버전업이 되면서 complie 이 사라진것이다.

참조 : https://velog.io/@g0709-19/Gradle-Could-not-find-method-compile-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95


2. 각 Entity에서 상속받을 Auditable 클래스 생성 

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable {

    // Entity가 생성되어 저장될 때 시간이 자동 저장됩니다.
    @CreatedDate
    private LocalDateTime createdDate;

    // 조회한 Entity 값을 변경할 때 시간이 자동 저장됩니다.
    @LastModifiedDate
    @Column(nullable = false, name = "LAST_MODIFIED_AT")
    private LocalDateTime modifiedDate;

}

 

어노테이션설명

@MappedSuperclass JPA Entity 클래스들이 해당 추상 클래스를 상속할 경우 createDate, modifiedDate를 컬럼으로 인식
@EntityListeners(AuditingEntityListener.class 해당 클래스에 Auditing 기능을 포함
@CreatedDate Entity가 생성되어 저장될 때 시간이 자동 저장
@LastModifiedDate 조회한 Entity의 값을 변경할 때 시간이 자동 저장

 

3. Entity에 Auditable 클래스 상속하기

@NoArgsConstructor
@Getter
@Setter
@Entity
public class Stamp extends Auditable { // Auditable 추상 클래스 상속

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long stampId;

    @Column(nullable = false)
    private Integer stampCount = 0; //멤버 생성시 같이 생기므로, 처음은 0개. 한잔에 1개씩 증가

    @OneToOne
    @JoinColumn(name = "MEMBER_ID", nullable = false)
    private Member member; //++ 도장에 대한 멤버 정보 연결

//   아래와 같이 엔티티마다 일일히 넣어줘야 했던 필드를 주석 처리.
//    @Column(nullable = false)
//    private LocalDateTime createdAt = LocalDateTime.now();
//
//    @Column(nullable = false, name = "LAST_MODIFIED_AT")
//    private LocalDateTime modifiedAt = LocalDateTime.now();
}

위 코드에서 중요한 점은 앞서서 생성한 Auditable 클래스를 상속하였다는 것입니다.

그럼 해당 클래스는    

private LocalDateTime createdDate;

private LocalDateTime modifiedDate;

위의 멤버필드를 상속 받으므로 Entity에 따로 선언해주지 않아도 됩니다.

 

 

4. JPA Auditing 활성화

@EnableJpaAuditing  //JPA Auditing 활성화
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

위 코드에서 봐야할 부분은

@EnableJpaAuditing 으로 인해 JPA Auditing을 활성활 하였다는 점입니다.

 

5. 생성된 테이블 확인

결과 화면에서 볼 수 있듯이,

Stamp Entity에 필드를 선언하지 않았음에도 

CREATED_DATE, LAST_MODIFIED_AT 필드가 생성되었음을 확인할 수 있다. 

그리고 데이터 또한 자동으로 잘 입력된다.

 

참조 : https://webcoding-start.tistory.com/53