JPA Auditing

JPA Auditing์ด๋?
Java์์ ORM ๊ธฐ์ ์ธ JPA๋ฅผ ์ฌ์ฉํ์ฌ ๋๋ฉ์ธ์ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ๋งคํํ ๋ ๊ณตํต์ ์ผ๋ก ๋๋ฉ์ธ๋ค์ด ๊ฐ์ง๊ณ ์๋ ํ๋๋ ์ปฌ๋ผ๋ค์ด ์กด์ฌํฉ๋๋ค. ๋ํ์ ์ผ๋ก ์์ฑ์ผ์, ์์ ์ผ์, ์๋ณ์ ๊ฐ์ ํ๋ ๋ฐ ์ปฌ๋ผ์ด ์์ต๋๋ค.
๋๋ฉ์ธ๋ง๋ค ๊ณตํต์ผ๋ก ์กด์ฌํ๋ค๋ ์๋ฏธ๋ ๊ฒฐ๊ตญ ์ฝ๋๊ฐ ์ค๋ณต๋๋ค๋ ๋ง๊ณผ ์ผ๋งฅ์ํตํฉ๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋๊ฐ, ์ธ์
ํ์๋์ง ๊ธฐ๋ก์ ์ ๋จ๊ฒจ๋์์ผ ํฉ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์์ฑ์ผ, ์์ ์ผ ์ปฌ๋ผ์ ๋๋จํ ์ค์ํ ๋ฐ์ดํฐ ์
๋๋ค.
๊ทธ๋์ JPA์์๋ Audit
์ด๋ผ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ณ ์์ต๋๋ค. Audit์ ๊ฐ์ํ๋ค, ๊ฐ์ฌํ๋ค
๋ผ๋ ๋ป์ผ๋ก Spring Data JPA์์ ์๊ฐ์ ๋ํด์ ์๋์ผ๋ก ๊ฐ์ ๋ฃ์ด์ฃผ๋ ๊ธฐ๋ฅ์
๋๋ค. ๋๋ฉ์ธ์ ์์์ฑ ์ปจํ
์คํธ์ ์ ์ฅํ๊ฑฐ๋ ์กฐํ๋ฅผ ์ํํ ํ์ update๋ฅผ ํ๋ ๊ฒฝ์ฐ ๋งค๋ฒ ์๊ฐ ๋ฐ์ดํฐ๋ฅผ ์
๋ ฅํ์ฌ ์ฃผ์ด์ผ ํ๋๋ฐ, audit์ ์ด์ฉํ๋ฉด ์๋์ผ๋ก ์๊ฐ์ ๋งคํํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ
์ด๋ธ์ ๋ฃ์ด์ฃผ๊ฒ ๋ฉ๋๋ค.
1. Auditi ์ฌ์ฉ ์์ ์ฝ๋
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
๋ง ์ถ๊ฐํด๋ Audit์ ํ๋๋ฐ๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
์ฐธ๊ณ ๋ก ์๋ฐ 1.8 ์ด์๋ถํฐ๋ ๊ธฐ์กด์ ๋ฌธ์ ๊ฐ ์๋ Date, Calander ํด๋์ค๋ฅผ ์ฌ์ฉํ์ง ์๊ณ LocalDate, LocalDateTime ํด๋์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ํ LocalDateTime ๊ฐ์ฒด์ ํ ์ด๋ธ ์ฌ์ด์ ๋งคํ์ด ์๋๋ ์ด์๋ ํ์ด๋ฒ๋ค์ดํธ 5.2 ๋ฒ์ ๋ถํฐ ํด๊ฒฐ์ด ๋์์ต๋๋ค.
BaseTimeEntity.java
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseTimeEntity{
// Entity๊ฐ ์์ฑ๋์ด ์ ์ฅ๋ ๋ ์๊ฐ์ด ์๋ ์ ์ฅ๋ฉ๋๋ค.
@CreatedDate
private LocalDateTime createdDate;
// ์กฐํํ Entity ๊ฐ์ ๋ณ๊ฒฝํ ๋ ์๊ฐ์ด ์๋ ์ ์ฅ๋ฉ๋๋ค.
@LastModifiedDate
private LocalDateTime modifiedDate;
}
@MappedSuperclass
JPA Entity ํด๋์ค๋ค์ด ํด๋น ์ถ์ ํด๋์ค๋ฅผ ์์ํ ๊ฒฝ์ฐ createDate, modifiedDate๋ฅผ ์ปฌ๋ผ์ผ๋ก ์ธ์
@EntityListeners(AuditingEntityListener.class
ํด๋น ํด๋์ค์ Auditing ๊ธฐ๋ฅ์ ํฌํจ
@CreatedDate
Entity๊ฐ ์์ฑ๋์ด ์ ์ฅ๋ ๋ ์๊ฐ์ด ์๋ ์ ์ฅ
@LastModifiedDate
์กฐํํ Entity์ ๊ฐ์ ๋ณ๊ฒฝํ ๋ ์๊ฐ์ด ์๋ ์ ์ฅ
ํด๋์ค ์์
Posts.java
@Getter
@NoArgsConstructor
@Entity
public class Posts extends BaseTimeEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 500, nullable = false)
private String title;
@Column(columnDefinition = "TEXT", nullable = false)
private String content;
private String author;
@Builder
public Posts(String title, String content, String author) {
this.title = title;
this.content = content;
this.author = author;
}
public void update(String title, String content) {
this.title = title;
this.content = content;
}
}
JPA Auditing ํ์ฑํ
@EnableJpaAuditing
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Posts ํด๋์ค๊ฐ @MappedSuperclass
๊ฐ ์ ์ฉ๋ BaseTimeEntity ์ถ์ ํด๋์ค๋ฅผ ์์ํ๊ธฐ ๋๋ฌธ์ JPA๊ฐ ์์ฑ์ผ์, ์์ ์ผ์ ์ปฌ๋ผ์ ์ธ์ํ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์์์ฑ ์ปจํ
์คํธ์ ์ ์ฅ ํ BaseTimeEntity ํด๋์ค์ Auditing ๊ธฐ๋ฅ์ผ๋ก ์ธํด์ ํธ๋์ญ์
์ปค๋ฐ ์์ ์ ํ๋ฌ์๊ฐ ํธ์ถํ ๋ ํ์ด๋ฒ๋ค์ดํธ๊ฐ ์๋์ผ๋ก ์๊ฐ ๊ฐ์ ์ฑ์์ฃผ๋๊ฒ์ ํ์ธ ํ ์๊ฐ ์์ต๋๋ค.
์คํ๋ง ๋ถํธ์ Entry ํฌ์ธํธ์ธ ์คํ ํด๋์ค์ @EnableJpaAuditing ์ด๋ ธํ ์ด์ ์ ์ ์ฉํ์ฌ JPA Auditing์ ํ์ฑํ ํด์ผํ๋ ๊ฒ์ ์์ง ๋ง์์ผ ํฉ๋๋ค.
ํ
์คํธ ์ํ
@Test
public void BaseTimeEntity_๋ฑ๋ก() throws Exception{
//given
LocalDateTime now = LocalDateTime.of(2019,6,4,0,0,0);
postsRepository.save(Posts.builder()
.title("title")
.content("content")
.author("author")
.build());
//when
List<Posts> postsList = postsRepository.findAll();
Posts posts = postsList.get(0);
System.out.println(">>createdDate="+ posts.getCreatedDate() + ", modifiedDate=" + posts.getModifiedDate());
// then
assertThat(posts.getCreatedDate()).isAfter(now);
assertThat(posts.getModifiedDate()).isAfter(now);
}
๊ฐ๋จํ๊ฒ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ์ฌ ์ค์ ๋ก Auditing ๊ธฐ๋ฅ์ด ํ์ฑํ ๋์ด ํ์ด๋ฒ๋ค์ดํธ๊ฐ ์์ฑ์ผ์, ์์ ์ผ์ ๊ฐ์ ์๋์ผ๋ก ์ฑ์์ฃผ๋์ง ํ์ธํด๋ดค์ต๋๋ค.
์คํ๊ฒฐ๊ณผ

Last updated