Доменные объекты, использующие объекты Hibernate? - PullRequest
0 голосов
/ 17 января 2020

В моей нынешней борьбе с DDD в приложении Spring Boot я в тупике. Я знаю, что мои доменные объекты не должны иметь никакого отношения к уровню инфраструктуры (где живут объекты Hibernate). Конечно, мой уровень домена использует данные объекта Hibernate для выполнения своих операций.

Поэтому на моем уровне приложений мои службы загружают объект Hibernate и передают его в объекте домена.

Вот пример моей доменной сущности:

package com.transportifygame.core.domain.objects;

import com.transportifygame.core.domain.OperationResult;
import com.transportifygame.core.domain.constants.Garages;
import com.transportifygame.core.domain.exceptions.garages.NotAvailableSpotException;
import com.transportifygame.core.infrastructure.entities.CompanyEntity;
import com.transportifygame.core.infrastructure.entities.GarageEntity;
import com.transportifygame.core.infrastructure.entities.LocationEntity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@RequiredArgsConstructor
@AllArgsConstructor

public class Garage {

    private GarageEntity garage;

    public static Integer getAvailableSlots(Garages.Size size) {
        switch (size) {
            case SMALL:
                return Garages.Slots.SMALL;
            case MEDIUM:
                return Garages.Slots.MEDIUM;
            case LARGE:
                return Garages.Slots.LARGE;
            case HUGE:
                return Garages.Slots.HUGE;
        }

        return 0;
    }

    public static Double getGaragePriceToBuy(Garages.Size size) {
        switch (size) {
            case SMALL:
                return Garages.Prices.BUY_SMALL;
            case MEDIUM:
                return Garages.Prices.BUY_MEDIUM;
            case LARGE:
                return Garages.Prices.BUY_LARGE;
            case HUGE:
                return Garages.Prices.BUY_HUGE;
        }

        return 0.0;
    }

    public static OperationResult<GarageEntity, Object> buy(
        Garages.Size size,
        CompanyEntity company,
        LocationEntity location
    ) {
        // As we had changed the company object, we have to refresh
        var newGarage = new GarageEntity();
        newGarage.setCompany(company);
        newGarage.setLocation(location);
        newGarage.setSize(size.ordinal());
        newGarage.setSlotsAvailable(Garage.getAvailableSlots(size));

        return new OperationResult<>(newGarage, null);
    }

    public static void hasAvailableSpot(GarageEntity garage) throws NotAvailableSpotException {
        if (garage.getSlotsAvailable() == 0) {
            throw new NotAvailableSpotException();
        }
    }

    public static OperationResult<GarageEntity, Object> addFreeSlot(GarageEntity garage) {
        garage.setSlotsAvailable(garage.getSlotsAvailable() - 1);

        return new OperationResult<>(garage, null);
    }

    public static OperationResult<GarageEntity, Object> removeFreeSlot(GarageEntity garage) {
        garage.setSlotsAvailable(garage.getSlotsAvailable() + 1);

        return new OperationResult<>(garage, null);
    }

}

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

Использует ли он фабрики для создания сущности домена, основанной на сущности гибернации? И объект домена должен отражать свойства объекта Hibernate?

Я также читал, что некоторые люди используют этот подход для добавления логики c объекта домена в объект Hibernate, но я думаю, что это не правильно способ сделать это.

1 Ответ

0 голосов
/ 26 января 2020

Я бы порекомендовал ознакомиться с шаблоном репозитория DDD. Короче говоря, хранилище должно имитировать c коллекцию в памяти для извлечения и хранения объектов вашего домена.

Таким образом, вы можете в конечном итоге разработать приложение в режиме гибернации двумя способами:

  1. написать высокоуровневый интерфейс репозитория, который предоставляет «find», «save» и т. Д. c для вашей доменной сущности. интерфейс репозитория и возвращаемые сущности должны быть «logi чистого домена c». то есть: никаких постоянных или спящих проблем. в вашем случае это будет объект Garage со всеми реализованными там бизнес-методами. в рамках реализации репозитория (которая может находиться в другом слое / пакете) вы будете иметь дело с представлением строки гибернации (объектами гибернации) и менеджером сущностей, чтобы получить контракт интерфейса. в вашем случае это где Garage объект отображается на (немой) GarageEntity и сохраняется через EntityManager или Session.

  2. вы можете принять некоторую утечку постоянство / спящий режим в вашем домене. это привело бы к тому, что в одном доменном объекте Garage будут содержаться все бизнес-логики c И аннотации hibernate / jpa (или xml) в одном и том же исходном файле (xml может быть отдельным). в этом случае репозиторий может быть прямой реализацией репозитория jpa.

в любом случае лог c в DDD всегда одинаков:

в службе приложений (некоторые GarageService - точка входа в использование case) хранилище запрашивается для объекта домена, на котором выполняется бизнес-операция. затем служба приложений снова сохраняет измененный объект в хранилище.

...