오늘 다뤄볼 내용은 지난주에 포스팅한 JPA Auditing 생성일, 수정일에 이은 생성자와 수정자를 자동화하는 auditing에 대해서 포스팅하려고 한다.
JAVA의 ORM(Object Relational Mapping) 기술에 대한 표준 명세를 의미하는 JPA ( Java Persistent API )에서 Auditing이라는 기술을 제공한다. jpa auditing은 도메인에서 공통적으로 쓰이는 필드나 컬럼들에 대해 자동으로 값을 넣어주는 기능이며, 대표적으로는 생성일, 수정일, 생성자, 수정자가 있을 것이다. jpa auditing을 사용하지 않는다면, 도메인을 생성 혹은 업데이트할 때마다 생성 일과 생성자, 수정일과 수정자를 매번 set 해줘야 하는 번거로움이 있는데 jpa auditing을 사용한다면 굳이 그러지 않아도 자동으로 해당 값을 세팅해서 넣어주게 된다. 그리하여 코드의 중복을 줄이고 조금 더 깔끔한 코딩을 할 수 있다.
지난 시간에는 @CreatedDate, @LastModifiedDate를 이용하여 데이터베이스에 인서트, 업데이트되는 시점에 시간이 자동으로 업데이트 되는 기능을 작업해보았다. 만약 해당 내용이 궁금하거나 전체적인 과정이 궁금한 사람은 아래 포스팅을 보고 오면 도움이 될 듯하다.
오늘의 포스팅은 지난번 프로젝트에 이어서 작업 진행할 예정이다.
2021.07.25 - [컴퓨터/java.spring] - [JPA Auditing] 생성일/ 수정일 자동화 하기
[JPA Auditing] 생성일/ 수정일 자동화 하기
오늘 다뤄볼 내용은 지난주에 프로젝트에 적용하게된 JPA Auditing 에 대해서 얘기해보려고 한다. JAVA의 ORM(Object Relational Mapping) 기술에 대한 표준 명세를 의미하는 JPA ( Java Persistent API )에서 Aud..
compunication.tistory.com
아래 코드는 지난번 포스팅에서 만들어 놓은 CommonEntity 클래스이다.
@MappedSuperclass
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@EntityListeners(AuditingEntityListener.class)
public abstract class CommonEntity {
@CreatedDate
@Column(updatable = false, nullable = false)
@Convert(converter = LocalDateTimeConverter.class)
private LocalDateTime createDate;
@LastModifiedDate
@Column(nullable = false)
@Convert(converter = LocalDateTimeConverter.class)
private LocalDateTime updateDate;
}
위의 CommonEntity에 생성자와 수정자에 대한 정보도 같이 기록하기 위하여 아래와 같이 코드를 수정하여 주었다.
@MappedSuperclass
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@EntityListeners(AuditingEntityListener.class)
public abstract class CommonEntity {
@CreatedDate
@Column(updatable = false, nullable = false)
@Convert(converter = LocalDateTimeConverter.class)
private LocalDateTime createDate;
@LastModifiedDate
@Column(nullable = false)
@Convert(converter = LocalDateTimeConverter.class)
private LocalDateTime updateDate;
@CreatedBy
@Column(updatable = false)
private String createBy;
@LastModifiedBy
private String updateBy;
}
위에 코드를 보면 createBy, updateBy 항목이 추가되었고, 각각 @CreatedBy, @LastModifiedBy 어노테이션을 사용하였다.
해당 어노테이션의 설명은 아래와 같다.
- @CreatedBy (org.springframework.data)
생성자를 자동 저장해주는 어노테이션 - @LastModifiedBy (org.springframework.data)
수정자를 자동 저장 해주는 어노테이션
위처럼만 설정해주고 동작하면 아주 좋겠지만...
생성일, 수정일과는 다르게 jpa에서 생성자와 수정자의 경우 어떠한 값이 들어갈지 알 수가 없어서 별도의 설정이 필요하다.
아래는 현재 프로젝트 경로인데 사진과 같이 config 패키지를 하나 만들어주고 AuditConfig라는 클래스 파일을 추가하였다.
보통 java spring boot의 config 관련 설정 파일들은 저 경로에 넣어준다.
그리고 AuditConfig 클래스는 아래와 같다.
@Configuration
public class AuditConfig implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String userId = request.getHeader("uid");
return Optional.of(userId);
}
}
크게 복잡하지 않다.
getCurrentAuditor() 함수 부분이 특정값을 가져와서 위에 설정해준 createBy, updateBy에 값이 들어가고 저장되게 된다.
우선 @Configuration 어노테이션은 간단히 말해서 스프링의 설정 클래스를 선언해주는 어노테이션이라고 보면 될 듯하다.
해당 포스팅은 jpa auditing을 주제로 다루는 포스팅이니 자세히 설명은 안 하겠지만 알아두면 좋으니 별도로 찾아서 공부하면 좋을듯하다.
해당 클래스는 AuditorAware 인터페이스를 구현하고 있다.
AuditorAware 들어가서 보면 그냥 getCurrentAuditor() 요거 하나 있다. 정확한 내부 동작 방식까진 모르지만 이 녀석을 구현해주면 된다.
그래서 위 클래스에서 getCurrentAuditor()를 보면 헤더에서 uid 정보를 가져와서 리턴해주고 있다.
이건 이 기능을 사용하려고 하는 각자가 원하는 위치 해서 원하는 값을 가져와서 리턴해주면 된다.
필자는 단순히 api 호출할 때 헤더 정보에 uid를 담고 그 uid를 기준으로 createBy와 updateBy를 해주기 위해 값을 가져와 리턴해주는 로직이다.
이렇게만 설정해주면 끝이다 그럼 테스트를 해보자.
필자는 테스트 용도로 postMan이라는 프로그램을 자주 사용한다.
아래와 같이 포스트맨으로 헤더 정보를 담아서 요청을 해보자.
그리고 아래는 컨트롤러 소스이다.
@RestController
@RequestMapping("/company")
@RequiredArgsConstructor
public class CompanyController {
private final CompanyRepository companyRepository;
@PostMapping(value = "")
public ResponseEntity<String> insert() {
Company company = Company.builder()
.name("세번째회사")
.build();
this.companyRepository.save(company);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@PutMapping(value = "/{cid}")
public ResponseEntity<String> update(@PathVariable(value = "cid") Long cid) {
Company company = this.companyRepository.findByCid(cid);
company.setName("이름개명한두번째회사");
companyRepository.save(company);
return new ResponseEntity<>(HttpStatus.OK);
}
}
별거는 없고 그냥 company 객체를 만들고 save 하는 로직이다.
블로그 포스팅을 위해 간단하고 빠르게 만들어본 것이다.
insert() api를 호출하고 해당 api는 단순히 company의 name만을 세팅하고 있다.
그럼 company 클래스를 살펴보자.
@Data
@Entity
@Builder
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@EntityListeners(AuditingEntityListener.class)
public class Company extends CommonEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long cid;
private String name;
}
cid와 name 정보가 있고, 아까 위에서 만든 생성일, 생성자, 수정일, 수정자 정보를 가지고 있는 CommonEntity 클래스를 상속받고 있다.
그리고 해당 api 호출 결과 DB에는 아래와 같이 값이 모두 원하는 대로 들어가 있는 것을 볼 수 있다.
지난주에 포스팅한 생성일 / 수정일, 그리고 이번 포스팅인 생성자 / 수정자로 JPA Auditing에 대한 포스팅을 마치도록 하겠다.
오늘 포스팅에서는 설명이 생략된 부분이 많으므로, 지난 포스팅인 생성일 / 수정일 관련 포스팅도 함께 보면 좋을듯하다.
'개발 이야기 > java' 카테고리의 다른 글
[JPA Auditing] 생성일/ 수정일 자동화 하기 (2) | 2021.07.25 |
---|---|
[Java][Spring Boot]어노테이션(Annotation) (0) | 2019.09.30 |
[Java]자료형간의 캐스팅 (0) | 2017.09.28 |
[Java][Spring]MongoDB 연동 및 사용 (0) | 2017.07.27 |
[Java][Spring]SMTP를 이용한 이메일 인증 기능 (6) | 2017.07.20 |