2017-12-30 20 views
0

스프링 부트 응용 프로그램의 aggregate-root에서 이벤트를 게시하는 데 문제가 있습니다. 내가 기본적으로 원하는 것은 사람에 관한 정보가 변경 될 때마다 "Update"이벤트를 게시하는 것입니다. 이 코드는 매우 간단합니다 : 나는 관리자를 통해 Person 인스턴스를 관리하고스프링 데이터 도메인 이벤트가 누락 됨 (?)

@Entity 
public class Person { 
    @Transient 
    private final Collection<AbstractPersonRelatedEvent> events = new ArrayList<>(); 

    Person(Person other) { 
    // copy other fields 
    other.events.foreach(events::add); 
    } 

    // other stuff 

    public Person updateInformation(...) { 
    Person updated = new Person(this); 

    // setting new data on the updated person 

    if (!hasUpdateEventRegistered()) { 
     updated.registerEvent(PersonDataUpdatedEvent.forPerson(updated)); 
    } 
    return updated; 
    } 

    void registerEvent(AbstractPersonRelatedEvent event) { 
    events.add(event); 
    } 

    @DomainEvents 
    Collection<AbstractPersonRelatedEvent> getModificationEvents() { 
    return Collections.unmodifiableCollection(events); 
    } 

    @AfterDomainEventPublication 
    void clearEvents() { 
    events.clear(); 
    } 
} 

: 나는 매니저 (manager.save(person.updateInformation(...))를 호출 할 때

@Service 
@Transactional 
class PersistentPersonManager implements PersonManager { 

// other methods are omitted 

    @Override 
    public Person save(Person person) { 
    return personRepository.save(person); 
    } 

} 

그러나 이벤트가 "실종"가서하는 것 : save() 메서드를 호출 할 때 모든 이벤트가 여전히 존재하지만 Spring이 getModificationEvents()을 호출 할 때 콜렉션은 비어 있습니다. 이벤트는 중간에 사라진 것처럼 보입니다 (스프링 코드 만 실행 됨).

이것은 매우 기본적인 것이므로 필수적인 것을 놓치고 있어야하지만 틀에 박히게됩니다.

그래서 어떻게 다시 돌아올 수 있습니까?

답변

1

여기서 JPA를 사용하고 있다고 가정합니다.

JPA의 경우 save 작업은 실제로 JPA EnityManager에서 merge입니다.

분리 된 엔터티의 경우 merge은 데이터베이스 또는 현재 세션의 동일한 ID를 가진 엔터티를로드/찾기하고 변경된 모든 필드를 복사합니다. 이것은 이벤트와 같은 일시적인 필드를 무시합니다.

updateInformation을 호출 할 때마다 새 엔터티를 만들기 때문에 분리 된 엔터티를 다루고 있습니다. 데이터베이스에서

  1. 당신은 엔티티를로드 (E1 일) :

    그래서 여기에 무슨 일이 일어나고있는 것입니다. 등록 된 이벤트가 없습니다.

  2. updateInformation을 호출하면 새 분리 된 엔터티 (e2)가 생성됩니다. 또한 e2으로 이벤트를 등록하십시오.

  3. save JPA를 호출하는 이벤트 제외에 E2에서 일치 E1 복사 모든 변경 사항을 찾습니다. 따라서 e1에는 아직 이벤트가 등록되지 않았습니다.

  4. 이벤트가 발생하지만 e1 만 사용되므로 이벤트가 발생하지 않습니다.

이 문제를 해결하려면 updateInformation에 엔티티의 새 인스턴스를 만들지 마십시오.