События домена с помощью Spring Boot и MongoDB - PullRequest
2 голосов
/ 06 мая 2020

Я работаю с DDD и Spring, используя MongoDB.

Теперь, поскольку MongoDB - это DocumentDB, и проверки схемы отсутствуют, AggregateRoot и класс Document, который сохраняется в MongoDB, являются двумя разными классами, а Repository переводит содержимое между эти два класса при чтении и записи данных в database.

Поскольку класс сущности Root отличается от класса, хранящегося в БД, Spring не запускает DomainEvents из AggregateRoot.

  • Есть ли способ вызвать события объекта Root из репозитория после сохранения данных в базе данных? (возможно, путем явного вызова)

  • Так как MongoDB и агрегаты подходят 1: 1. Значит ли это, что обычно мы не должны создавать два разных класса: один как AggregateRoot, а другой как класс документа для хранения совокупных корней в mongoDB? Разве нам не нужно было бы добавить аннотацию @Document поверх нашего Агрегата, что приведет к утечке кода инфраструктуры в нашей модели домена?

1 Ответ

0 голосов
/ 05 сентября 2020

Через некоторое время я нашел решение, на основании голосов, которые, как я полагаю, другие сталкиваются с той же проблемой, вот решение:

Вопрос: можем ли мы вызвать явный вызов для событий домена?

Ответ: Да, можем. В SpringBoot мы можем использовать / Autowire интерфейс ApplicationEventPublisher, а затем вызвать метод publishEvent(event).

Если вы создаете отдельный класс для коллекции Db и Aggregate, вам нужно будет раскрыть свой DomainEvents и метод для ClearingDomainEvents в вашей совокупности, поскольку AbstractAggregateRoot<T> имеет эти методы как protected. Ниже приведен пример создания события при создании:

public class MyAggregateRootClass extends AbstractAggregateRoot<MyAggregateRootClass> 
{
    public MyAggregateRootClass(String property1, String property2) {

        // set the fields here
        registerEvent(new MyAggregateRootCreated(someArgs));
    }

    public Collection<Object> getDomainEvents() {
        return super.domainEvents();
    }

    public void clearDomainEvents() {
        super.clearDomainEvents();
    }
}

Код репозитория будет выглядеть так:

@Repository
@RequiredArgsConstructor // using lombok here, you can create a constructor if you want
public class MyAggregateRepository {

    private final ApplicationEventPublisher eventPublisher;

    private final AggregateMongoRepository repository;

    public void save(MyAggregateRootClass aggToSave) {

        AggregateDao convertedAgg = new AggregateDao(aggToSave);

        repository.save(convertedAgg);

        // raise all the domain events
        for (Object event : aggToSave.getDomainEvents())
            eventPublisher.publishEvent(event);

        // clear them since all events have been raised
        aggToSave.clearDomainEvents();
    }
}

Значит ли это, что обычно мы не должны создавать два разных класса, один как AggregateRoot, а другой как класс документа для хранения совокупных корней в mongoDB?

Ответ : Нет, это не значит. Целью DDD было бы отделить infrastructure от Domain и сохранить Domain агности c всего кода инфраструктуры. Если они оба одинаковы, то влияние ниже показано:

  • Наличие аннотации @Document на вашем Aggregate Class заставит вас изменить Domain, если вы переключаете фреймворки или меняете местами Mongodb с SQL.
  • В будущем, если ваша схема БД потребуется изменить, вам придется либо также изменить свой совокупный класс, либо вам придется настроить классы адаптеров.
  • Поскольку домен должен меняться только в случае изменения бизнес-требований, а не из-за infrastructure dependencies, проникновение из infrastructure annotations в AggregateRoot было бы не лучшим способом
Итак, когда вы действительно можете просто обойтись без использования одного и того же класса для Aggregate и Db Collection?

Если вы действительно хотите сохранить простоту и использовать один и тот же класс для обоих, а не создавать отдельный класс, убедитесь, что вы уверены в следующем:

  • Если вы абсолютно уверен, что вы никогда не собираетесь переключать БД или менять фреймворки.
  • У вас простая модель домена, и вам не нужно хранить Entities из Aggregate в отдельной коллекции, и вы есть нет возможности, что эти Entities когда-либо вырастут в свои Aggregates

В конце концов, это зависит от обстоятельств. Не стесняйтесь оставлять комментарии, и я постараюсь ответить на все из них, довольно активно в стеке.

...