Saya mengalami masalah saat memublikasikan acara dari agregat-root di aplikasi Spring Boot. Yang pada dasarnya saya inginkan adalah menerbitkan acara "Pembaruan" setiap kali beberapa informasi tentang seseorang diubah. Kode untuk ini cukup mudah:

@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();
  }
}

Saya mengelola instance Person melalui manajer:

@Service
@Transactional
class PersistentPersonManager implements PersonManager {

 // other methods are omitted

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

}

Namun ketika saya memanggil manajer (manager.save(person.updateInformation(...)) acaranya sepertinya "hilang": setelah memanggil metode save() semua peristiwa masih ada tetapi ketika Spring memanggil getModificationEvents() koleksinya kosong. Peristiwa itu tampaknya telah menghilang di suatu tempat di antaranya (dengan hanya kode Spring yang dieksekusi).

Karena ini cukup mendasar, saya pasti melewatkan sesuatu yang penting tetapi terjebak dalam kebiasaan.

Jadi bagaimana saya kembali ke jalur di sini?

0
portux 30 Desember 2017, 19:34

1 menjawab

Jawaban Terbaik

Saya berasumsi Anda menggunakan JPA di sini.

Untuk JPA, operasi save sebenarnya melakukan merge pada JPA EnityManager.

Untuk entitas terpisah merge memuat/menemukan entitas dengan id yang sama dari database atau sesi saat ini dan menyalin semua bidang (yang diubah). Ini mengabaikan bidang sementara seperti peristiwa.

Anda berurusan dengan entitas yang terpisah karena Anda membuat entitas baru setiap kali Anda memanggil updateInformation.

Jadi inilah yang terjadi:

  1. Anda memuat entitas (e1) dari database. Tidak ada acara yang terdaftar.

  2. Dengan memanggil updateInformation Anda membuat entitas baru yang terpisah (e2). Anda juga mendaftarkan acara dengan e2.

  3. Saat memanggil save JPA menemukan e1 yang cocok dan menyalin semua perubahan dari e2 ke dalamnya, kecuali peristiwa. Jadi e1 masih belum memiliki acara yang terdaftar.

  4. Peristiwa dipicu, tetapi tidak ada karena hanya e1 yang digunakan.

Untuk memperbaikinya: Jangan membuat instance baru entitas di updateInformation.

2
Jens Schauder 31 Desember 2017, 12:58