Programming/JAVA

[JPA] @CreatedBy, @LastModifiedBy 를 위한 AuditorAware 적용

통통만두 2022. 3. 30. 19:47
반응형

spring-data-commons 에는 @CreatedBy, @LastModifiedBy 라는 어노테이션이 있습니다. 물론, @CreatedDate, @LastModifiedDate가 자매품(?)으로 있긴하지만, 생성시간과 업데이트시간은 해당 어노테이션을 지정하는 것만으로도 끝나지만, 생성자, 수정자는 별도의 셋팅 과정이 필요합니다. 이 과정에서 Spring Security 셋팅이 필수로 필요합니다. Spring Security 셋팅 없이도 할 수 있겠지만 요즘 백엔드와 프론트엔드도 분리되고 JWT 토큰으로 인증을 하기에 더더욱 필요한 것 같습니다.

아래는 JPA, Spring Secutiry 환경에서 작성된 코드입니다.

MemberEntity.java

@Getter
@ToString
@Builder
@Entity(name = "회원 테이블")
@Table(name = "tb_member")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@EntityListeners(AuditingEntityListener.class)
public class MemberEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_seq", nullable = false)
    private Long memberSeq;

    @Column(name = "member_id", nullable = false, length = 50)
    private String memberId;

    @Column(name = "co_name", nullable = false, length = 50)
    private String coName;

    @Column(name = "real_name")
    private String realName;

    @Column(name = "status", nullable = false, length = 4)
    private String status;

    @CreatedBy
    @Column(name = "create_member_seq", nullable = false, updatable = false)
    private Long regMemberSeq;

    @LastModifiedBy
    @Column(name = "mod_member_seq")
    private Long modMemberSeq;

    @CreatedDate
    @Column(name = "create_date", nullable = false, updatable = false)
    private LocalDateTime regDate;

    @LastModifiedDate
    @Column(name = "mod_date")
    private LocalDateTime modDate;

    public void updateRealName(String value) {
        this.realName = value;
    }
}

JPA를 다 알고 계시다는 가정하에 사용되는 어노테이션은 따로 설명하지 않겠습니다. @CreatedBy, @LastModifiedBy 어노테이션만 기억하시고 해당 필드에 지정해주시면 됩니다.

 

반응형

 

AuthenticationUserDto.java

@ToString
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class AuthenticationUserDto {
    private String memberId;
    private Long memberSeq;
    private String name;
}

Spring Secutiry Filter 에서 넘어온 JWT TokenAuthenticationToken객체로 변환하고 DetailDTO를 만들어서 실어놨습니다.

 

AuditorAwareImpl.java

@Slf4j
public class AuditorAwareImpl implements AuditorAware<Long> {
    @Override
    public Optional<Long> getCurrentAuditor() {
        AuthenticationToken authenticationToken = (AuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        if (authenticationToken == null || !authenticationToken.isAuthenticated()) {
            log.debug("Not found AuthenticationToken");
            return null;
        }

        AuthenticationUserDto authenticationUserDto = (AuthenticationUserDto) authenticationToken.getDetails();
        log.debug("Found AuthenticationToken: {}", authenticationUserDto);
        return Optional.of(authenticationUserDto.getMemberSeq());
    }
}

SecurityContextHolder에서 객체가 있는지 확인을 하고 없으면 null을 있으면 Spring Secutiry Filter에서 인증된 객체에 넣어둔 DTO를 꺼내서 @CreatedBy, @LastModifiedBy 어노테이션이 붙은 필드에 넣을 값을 가지고 옵니다.

 

JpaAuditConfiguration.java

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class JpaAuditConfiguration {
    @Bean
    public AuditorAware<Long> auditorProvider() {
        return new AuditorAwareImpl();
    }
}

 

TestController.java

@Operation(summary = "Test 2", description = "테스트 투")
    @GetMapping("/{memberSeq}")
    public ResponseEntity<ResultEntity> test2(@PathVariable("memberSeq") Long memberSeq) throws Exception {
        ResultEntity result = ResultEntity.builder()
                .success(true)
                .build();

        MemberEntity member = memberRepository.findById(memberSeq).get();
        member.updateRealName("정우성4");
        memberRepository.save(member);

        return new ResponseEntity<>(result, HttpStatus.OK);
    }

제 환경에 맞는 컨트롤러라 크게 신경안쓰셔도 되고 해당 부분에서 insert, update를 하신 후 토큰에 들어 있는 값이 잘 들어가는지 DB에서 확인해보시면 됩니다.

Spring Secutiry Filter을 통해서 요청 헤더에서 토큰 꺼내서 유효성 체크하고 인증하고, 인증된 객체를 생성하는 부분은 생략하였으니 참고부탁드리겠습니다. 기회가 되면 해당 부분은 별도의 포스팅으로 작성하도록 하겠습니다.

 

참고

https://www.baeldung.com/database-auditing-jpa

반응형