이번 주제는 JPA Auditing 기능을 Rest API에 추가하는 것이다. 사실 우리가 데이터베이스를 업데이트 하거나 사용하다보면 사실 데이터 내용이 수정되는 경우가 생긴다. 물론, 최초 생성 과정에서도 보통 createdAt으로 저장하는 경우가 있다. Django에서는 auto_now_add=True
를 이용하는데 Spring에서는 어떤 방식을 사용하는지 알아보도록 하겠다.
[Spring] JPA 와 AWS 연동하기 저번에 생성해놓은 AWS 과정을 따라하면서 세팅하면 된다.
추가적인 유효성 검사 세팅
implementation 'org.springframework.boot:spring-boot-starter-validation'
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Getter
@Setter
public abstract class Auditable<U> {
@CreatedBy
protected U createdBy;
@CreatedDate
@Temporal(TemporalType.TIMESTAMP)
protected Date createdDate;
@LastModifiedBy
protected U lastModifiedBy;
@LastModifiedDate
@Temporal(TemporalType.TIMESTAMP)
protected Date lastModifiedDate;
}
여기를 보게 되면 Auditable 객체가 생겨났는데 다른 모델에다가 추가하게 되면 그 모델들은 이제 생성, 수정 과정에서 누가, 언제 했는지에 대한 정보를 저장할 수 있게 된다.
@Entity
@Table(name="user")
@EntityListeners(AuditingEntityListener.class)
@Getter
@Setter
public class User extends Auditable<String> {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "last_name", nullable = false)
private String lastName;
@Column(name = "email_address", nullable = false)
private String emailId;
}
@Repository
public interface UserRepository extends JpaRepository <User, Long>{
}
@RestController
@RequestMapping("/api/v1")
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/users")
public List<User> getAllUsers() {
return userRepository.findAll();
}
@GetMapping("/users/{id}")
public ResponseEntity<User> getUserById(
@PathVariable(value = "id") Long userId
) throws ResourceNotFoundException {
User user = userRepository.findById(userId)
.orElseThrow(() -> new ResourceNotFoundException("User not found : " + userId));
return ResponseEntity.ok().body(user);
}
@PostMapping("/users")
public User createUser(@Valid @RequestBody User user) {
return userRepository.save(user);
}
@PutMapping("/users/{id}")
public ResponseEntity<User> updateUser(
@PathVariable(value = "id") Long userId,
@Valid @RequestBody User userDetails) throws ResourceNotFoundException {
User user = userRepository.findById(userId)
.orElseThrow(() -> new ResourceNotFoundException("User not found :: " + userId));
user.setEmailId(userDetails.getEmailId());
user.setLastName(userDetails.getLastName());
user.setFirstName(userDetails.getFirstName());
user.setLastModifiedDate(new Date());
final User updatedUser = userRepository.save(user);
return ResponseEntity.ok(updatedUser);
}
@DeleteMapping("/users/{id}")
public Map<String, Boolean> deleteUser(
@PathVariable(value = "id") Long userId) throws ResourceNotFoundException {
User user = userRepository.findById(userId)
.orElseThrow(() -> new ResourceNotFoundException("User not found :: " + userId));
userRepository.delete(user);
Map<String, Boolean> response = new HashMap<>();
response.put("deleted", Boolean.TRUE);
return response;
}
}
public class AuditorAwareImpl implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
return Optional.of("exist");
}
}
@SpringBootApplication
@EnableJpaRepositories(basePackageClasses = UserRepository.class)
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class SpringJpaAuditingApplication {
@Bean
public AuditorAware<String> auditorAware() {
return new AuditorAwareImpl();
}
public static void main(String[] args) {
SpringApplication.run(SpringJpaAuditingApplication.class, args);
}
}
여기서 @EnableJpaAuditing(auditorAwareRef = "auditorAware")
를 설정하지 않으면 아래 테스트 결과에서 볼 수 있듯이 null값이 나오기 때문에 설정해줘야 한다.
아래의 생성 시간과 누가 수정했는지 저장할 수 있다. 나는 일단 createdBy, lastModifiedBy는 "exist"로 설정하였다.
처음에는 설정을 잘 못해서 null 값이 출력되었지만 수정 후 잘 나올 수 있게 되었다.
최종 코드 spring-jpa-auditing에서 확인할 수 있습니다.