Spring Data JPA - Auditing

목차

참고

https://docs.spring.io/spring-data/jpa/docs/1.7.0.DATAJPA-580-SNAPSHOT/reference/html/auditing.html

Spring Data JPA - Auditing(감사)

데이터가 언제 누구에 의해서 생성, 수정 됐는지 추적할 필요가 있는데
Spring Data JPA 에서는 쉽게 Audit 를 할 수 있는 기능들을 제공한다.

Spring Data JPA Auditing 사용하기

EnableJpaAuditing 어노테이션을 이용해 프로젝트에 Auditing 기능을 사용할 수 있도록 설정한다.

@SpringBootApplication
@EnableJpaAuditing
public class DataJpaApplication {

public static void main(String[] args) {
SpringApplication.run(DataJpaApplication.class, args);
}

// 데이터가 생성 및 수정될 때 생성한 사람과 수정한 사람 정보를 넣기 위한 Bean 을 만들어준다.
@Bean
public AuditorAware<String> auditorProvider(){
return () -> Optional.of(UUID.randomUUID().toString());
}
}
  • @EntityListeners(AuditingEntityListener.class)
    • 해당 클래스에 Auditing 기능을 포함 시킨다.
    • CreatedDate : Entity 가 생성될 때 시간을 자동으로 저장한다.
    • LastModifiedDate : Entity가 수정될 때 시간을 자동으로 저장한다.
    • CreatedBy : Entity 를 생성한 주체를 저장한다.
    • LastModifiedBy : Entity 를 수정한 주체를 저장한다.

EntityListeners : JPA Entity에 이벤트가 발생할 때 Callback 을 처리하고 실행하는 방법

@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class BaseEntity {

@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;

@LastModifiedDate
private LocalDateTime lastModifiedDate;

@CreatedBy
@Column(updatable = false)
private String createdBy;

@LastModifiedBy
private String lastModifiedBy;
}

Auditing 기능 적용하기

@Entity
@Setter
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
@NamedEntityGraph(name = "Member.all", attributeNodes = @NamedAttributeNode("team"))
public class Member extends BaseEntity{

@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id;
private String username;
private int age;

// 여러명의 Member가 한 팀에 가입
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;


public Member(String username){
this.username = username;
}

public Member(String username, int age, Team team) {
this.username = username;
this.age = age;
if (team != null) {
changeTeam(team);
}
}

public Member(String username, int age) {
this.username = username;
this.age = age;
}

public void changeTeam(Team team){
this.team = team;
team.getMembers().add(this);
}

}
@Entity
@Setter
@Getter
@NoArgsConstructor(access= AccessLevel.PROTECTED)
@ToString(of = {"id", "name"})
public class Team extends BaseEntity{

@Id
@GeneratedValue
@Column(name = "team_id")
private Long id;
private String name;

// 한 팀에 여러명의 회원이 가입하는 개념
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();

public Team(String name) {
this.name = name;
}
}

Spring Data JPA Auditing 사용하기

  • 데이터 추가 및 삭제시 사용자 정보를 Auditing 하기 위해서는 AuditorAware Bean 이 필요하다.
  • @CreatedBy@LastModifiedBy 으로 컬럼에 명시하면 데이터 생성, 변경시 사용자 정보를 자동으로 넣어준다.
@SpringBootApplication
@EnableJpaAuditing
public class DataJpaApplication {

public static void main(String[] args) {
SpringApplication.run(DataJpaApplication.class, args);
}

// 데이터가 생성 및 수정될 때 생성한 사람과 수정한 사람 정보를 넣기 위한 Bean 을 만들어준다.
@Bean
public AuditorAware<String> auditorProvider(){
return () -> Optional.of(UUID.randomUUID().toString());
}
}

AuditorAware 인터페이스를 이용한 구현체 생성

public class AuditorAwareImpl implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

if(authentication == null){
return Optional.of(null);
}

String username = authentication.getName();
return Optional.of(username);
}
}

Config Class 에 AuditorAware Bean 을 등록한다.

@Configuration
@EnableJpaAuditing
@RequiredArgsConstructor
@Slf4j
public class JpaConfig {

@Bean
public AuditorAware<String> auditorProvider(){
return new AuditorAwareImpl();
}
}

람다식으로 생성

@Configuration
@EnableJpaAuditing
@RequiredArgsConstructor
@Slf4j
public class JpaConfig {

@Bean
public AuditorAware<String> auditorProvider(){
return () -> {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

if(authentication == null){
return Optional.ofNullable(null);
}

String username = authentication.getName();
return Optional.of(username);
};
}
}
Share