Small Asteroid Blog

[Spring] MongoTemplate 사용 시 @LastModifiedDate가 적용되지 않는 이유와 해결 방법 본문

백엔드/Spring

[Spring] MongoTemplate 사용 시 @LastModifiedDate가 적용되지 않는 이유와 해결 방법

작은소행성☄️ 2024. 12. 2. 22:37
728x90
 

MongoTemplate과 Spring Data MongoDB Auditing 

  • Spring Data MongoDB는 @LastModifiedDate, @CreatedDate 등의 어노테이션을 통해 엔티티의 생성 및 수정 시간을 자동으로 기록할 수 있도록 Auditing 기능을 제공한다.
  • 하지만, mongoTemplate.updateFirst()와 같은 직접적인 업데이트 메서드를 사용할 경우, 이 기능이 자동으로 적용되지 않는다.
  • 이는 MongoTemplate이 @LastModifiedDate를 처리하는 AuditingEntityListener를 트리거하지 않기 때문이다.

두개 동시 사용 관련된 내용

 

 

 

문제 발생: MongoTemplate에서 @LastModifiedDate가 자동으로 업데이트되지 않음

  • 일반적으로 @LastModifiedDate는 save() 또는 repository를 사용할 때 자동 적용됩니다.
  • 그러나 mongoTemplate.updateFirst() 또는 mongoTemplate.updateMulti()를 사용할 경우, Auditing 기능이 동작하지 않습니다.
@Document(collection = "your_collection")
public class YourEntity {

    @Id
    private String id;

    private String someField;

    @LastModifiedDate
    private LocalDateTime lastModifiedDate;

    // getters and setters
}

위와 같은 엔티티를 mongoTemplate.updateFirst()를 이용해 업데이트하면, lastModifiedDate가 자동으로 변경되지 않습니다.

 

 

 

해결 방법

1. 업데이트 시 직접 필드 추가하기

MongoTemplate을 사용할 때, @LastModifiedDate를 명시적으로 설정해야 합니다.

import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;

@Service
public class YourService {

    @Autowired
    private ReactiveMongoTemplate mongoTemplate;

    public Mono<UpdateResult> updateEntity(String id, String newValue) {
        Query query = new Query(Criteria.where("id").is(id));
        Update update = new Update()
                .set("someField", newValue)
                .set("modifiedDate", LocalDateTime.now()); // lastModifiedDate를 명시적으로 설정

        return mongoTemplate.updateFirst(query, update, YourEntity.class);
    }
}

 

 

2. Auditing 가능하게 변경

Auditing 기능을 사용하려면 mongoTemplate 대신 save() 메서드를 사용하는 구조로 바꾸는 것이 좋다.

import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

@Service
public class YourService {

    @Autowired
    private YourEntityRepository repository;

    public Mono<YourEntity> updateEntity(String id, String newValue) {
        return repository.findById(id)
            .map(entity -> {
                entity.setSomeField(newValue);
                // Auditing으로 lastModifiedDate가 자동 갱신됨
                return entity;
            })
            .flatMap(repository::save);
    }
}

 

 

 

3. Auditing과 mongoTemplate 병합

mongoTemplate를 계속 사용하면서 @LastModifiedDate를 적용하려면 ReactiveIsNewAwareAuditingHandler를 직접 호출해야 한다.

3-1) Custom Auditing Handler 생성

import org.springframework.data.auditing.ReactiveIsNewAwareAuditingHandler;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.stereotype.Component;

@Component
public class CustomAuditingHandler {

    private final ReactiveIsNewAwareAuditingHandler auditingHandler;

    public CustomAuditingHandler(PersistentEntities entities) {
        this.auditingHandler = new ReactiveIsNewAwareAuditingHandler(entities);
    }

    public <T> T markAudited(T entity) {
        auditingHandler.markModified(entity);
        return entity;
    }
}

 

 

2. MongoTemplate 업데이트 시 Auditing 적용

mongoTemplate을 유지하면서 @LastModifiedDate를 적용 하는 방법으로 다소 복잡한 구조를 띈다.

import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

@Service
public class YourService {

    @Autowired
    private ReactiveMongoTemplate mongoTemplate;

    @Autowired
    private CustomAuditingHandler auditingHandler;

    public Mono<UpdateResult> updateEntity(String id, String newValue) {
        Query query = new Query(Criteria.where("id").is(id));
        Update update = new Update().set("someField", newValue);

        // Auditing 적용
        YourEntity entity = new YourEntity();
        entity.setId(id);
        auditingHandler.markAudited(entity);

        update.set("lastModifiedDate", entity.getLastModifiedDate());

        return mongoTemplate.updateFirst(query, update, YourEntity.class);
    }
}

 

 

728x90
반응형