[백엔드 첫 걸음] API 조회 기능 확인 • Jpa Auditing으로 생성시간/수정시간 자동화

khyojun·2022년 8월 17일
1
post-thumbnail

❗ 조회 기능.

📂main/resource/application.properties

spring.jpa.show_sql=true
spring.h2.console.enabled=true
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.hikari.jdbc-url=jdbc:h2:mem:testdb
spring.datasource.password=
spring.datasource.hikari.username=sa
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

다음과 같은 코드를 추가하며 이번 조회 기능은 실제로 톰캣을 실행하며 확인을 해본다.
앞에서 언급한것처럼 로컬 환경에서는 H2 데이터베이스를 사용하기에 직접 접근하기위하여서 웹 콘솔을 활용을 하게 된다. 그래서 위와 같은 코드를 추가하여 준다.

추가한 뒤 다음 링크로 접속을 하게 된다. http://localhost:8080/h2-console 접속을 하게 된다면 다음과 같은 화면이 뜨게 된다.

그 이후 SELECT문을 사용하여서 테이블의 내용을 확인하여 본다면 다음과 같이 데이터가 현재는 등록이 되어있지 않은 상태로 있다는 것을 알 수 있는데...

그리하여서 insert문을 활용하여서 데이터를 추가하고

insert into posts (author, content, title) values ('author', 'content', 'title');

그 이후 조회가 되는지 확인하여보기위하여서 이전 API에서 작성한것처럼 http://localhost:8080/api/v1/{id}였던것처럼 id자리에 현재 테이블에 등록이 되어있던 하나의 테이블의 id인 1을 넣어준다.


🔍 JPA Auditing으로 생성시간/수정시간 자동화하기

보통 엔티티에서는 해당 데이터의 생성시간과 수정시간을 포함을 한다. 언제 만들어졌는지, 언제 수정되었는지는 나중에 유지보수의 측면에서 상당히 중요한 정보이기 떄문이다. 그래서 기본적으로는 매번 DB에 삽입하기 전, 갱신하기 전 날짜 데이터를 등록/수정하는 코드가 여기저기 들어가게 된다.

📌Ex)

//생성일 추가 코드 예제
public void savePosts(){
	...
    posts.setCreateDate(new LocalDate());
    postsRepository.save(posts);
	...
}

즉, 이런 코드들이 계속해서 들어가야 한다는 점이다. 그러면 당연히 코드도 복잡해지고 어질어질~~할 것이다.
그래서 이 문제를 해결하기 위하여서 JPA Auditing을 사용한다.

LocalDate 사용

이전에 보게 되면 날짜와 관련된 클래스들이 있다는 것들을 알 수 있는데 예를 들자면은 Calendar, Date와 같은 클래스 말이다.
그런데 Java8부터 LocalDate LocatDateTime이 등장을 했는데 앞서 말하였던 Calendar, Date와 같은 클래스들의 문제점들을 제대로 고친 타입이다.

🏸 JAVA8이 나오기 전까지 사용했던 Date와 Calendar 클래스는 다음과 같은 문제점들이 있었다고 한다.

  1. 불변(변경이 불가능한) 객체가 아닙니다.
    • 멀티스레드 환경에서 언제든 문제가 발생할 수 있습니다.
  2. Calendar는 월(Month) 값 설계가 잘못되었습니다.
    • 10월을 나타내는 Calendar.OCTOBER의 숫자 값은 '9'입니다.
    • 당연히 '10'으로 생각했던 개발자들에게는 큰 혼란이 왔습니다.

이후 더 많은 내용들은 Naver D2 - Java의 날짜와 시간 API를 참고하면 좋다.(재밌는 내용들도 되게 많다.)(https://d2.naver.com/helloworld/645609)


이제 본격적으로 한 번 구현을 해보도록 하자.

📂 main/java/domain/BaseTimeEntity.java

package com.khyojun.admin.springboot.domain;

import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDate;
import java.time.LocalDateTime;

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

   @CreatedDate
   private LocalDateTime createdDate;

   @LastModifiedDate
   private LocalDateTime modifiedDate;
}

🔍 BaseTimeEntity 클래스는 모든 Entity의 상위 클래스가 되어서 Entity들의 createdDate, modifiedDate를 자동으로 관리하는 역할을 한다.

  1. @MappedSuperclass
    • JPA Entity 클래스들이 BaseTimeEntity를 상속할 경우 필드들(createdDate, modifiedDate)도 칼럼으로 인식하도록 한다.
  2. @EntityListeners(AuditingEntityListener.class)
    • BaseTimeEntity 클래스에 Auditing 기능을 포함시킨다.
  3. @CreatedDate
    • Entity가 생성되어 저장될 때 시간이 자동 저장이 된다.
  4. @LastModifiedDate
    • 조회한 Entity의 값을 변경할 때 시간이 자동 저장이 된다.
  5. Auditing: 엔티티를 생성하거나 변경한 사람과의 발생한 시점을 투명하게 추적 : 변경 시점 추적
  • Spring Data Jpa를 보면 정보를 캡처하는데 Entity Listener와 함께 제공이 된다고 한다. 그래서 AuditingEntityListener내부를 등록을 해야한다.

이렇게 한 이후로 Entity클래스에 BaseTimeEntity를 상속받게 한다.

...
public class Posts extends BaseTimeEntity{
	...
}

마지막으로 JPA Auditing 어노테이션들을 모두 활성화할 수 있도록 Application클래스에 활성화 어노테이션 하나를 추가한다.

@EnableJpaAuditing
@SpringBootApplication
public class Application{
	public static void main(String[] args){
    	SpringApplication.run(Application.class, args);
    
    }

}

자 그러면 위 코드들은 작성이 완료되었고 이제 테스트 코드를 한 번 만들어보도록 하자.

📂 test/java/domain/PostsRepositoryTest.java

 @Test
   public void BaseTimeEntity_등록() {

       //given
       LocalDateTime now= LocalDateTime.of(2022,8,17,22,0,0);
       postRepository.save(Posts.builder().title("title").content("content").author("author").build());

       //when
       List<Posts> postsList = postRepository.findAll();


       //then
       Posts posts=postsList.get(0);
       System.out.println(">>>>>>>>>>>>> createDate=" + posts.getCreatedDate() + ", modifiedDate="+posts.getModifiedDate());

       Assertions.assertThat(posts.getCreatedDate()).isAfter(now);
       Assertions.assertThat(posts.getModifiedDate()).isAfter(now);
   } 

위 코드의 내용들을 분석해보자면 우선은 지금 현재의 시간을 기준으로 나중에 assertThat을 사용하여서 지금 등록을 한 시간보다 뒤에 시간이 맞는지 확인하게 된다.

참고

  1. 이동욱 저자의 <스프링 부트와 AWS로 혼자 구현하는 웹 서비스>
  2. https://docs.spring.io/spring-data/jpa/docs/1.7.0.DATAJPA-580-SNAPSHOT/reference/html/auditing.html
  3. https://d2.naver.com/helloworld/645609
  4. https://www.baeldung.com/spring-boot-h2-database
profile
코드를 씹고 뜯고 맛보고 즐기는 것을 지향하는 개발자가 되고 싶습니다

0개의 댓글