Подход для (общего) хранилища DDD с JPA / Spring: выглядит ли это неправильно? - PullRequest
3 голосов
/ 10 февраля 2010

Я довольно новичок в DDD и JPA.

Я работаю над общим репозиторием с JPA и Spring. Мне очень нравятся подходы, раскрытые в статьях DDD: универсальный репозиторий и Шаблоны реализации JPA: объекты доступа к данным . Моя цель - создать репозиторий perfect в доменно-управляемом дизайне с использованием JPA и Spring.

Я использую внутренний универсальный репозиторий для соблюдения договора домена с хранилищем данных , следуя концепции первой статьи.

public interface IInternalGenericRepository<K, E> {
    List<E> read(String query, Object[] params);
    void persist(E entity);
    void remove(E entity);
}

public class InternalGenericRepository<K, E> implements IInternalGenericRepository<K, E> {

    // Injected through DI in Spring
    @PersistenceContext
    private EntityManager em;

    private final Class<E> entityClass;

    public List<E> read(String query, Object[] params) {
        Query q = em.createQuery(query);
        for (int i = 0; i < params.length; i++) {
            q.setParameter(i + 1, params[i]);
        }
        return q.getResultList();
    }

    public void persist(E entity) {
        em.persist(entity);
    }

    // ...
}

Тогда репозиторий для конкретной сущности (например, организации) выглядит следующим образом.

public interface IOrganizationRepository {
    List<Organization> organizationByCityName(String city);

    void create(Organization o);
}


@Repository
public class OrganizationRepository implements IOrganizationRepository {

    @Autowired
    IInternalGenericRepository<Long, Organization> internalRepository;

    public List<Organization> organizationByCityName(String city) {
        Object[] params = new Object[1];
        params[0] = city;
        return internalRepository.read("select o from Organization o where o.city.name like ?1",
                params);
    }

    @Override
    public void create(Organization o) {
        internalRepository.persist(o);
    }
}

Похоже, это хороший способ реализовать DDD Repository с JPA и Spring. Затем в мой сервисный слой внедряется репозиторий Organization.

Мне бы хотелось иметь внешние взгляды, чтобы избежать недостатков или заблуждений. Как вы думаете, и как это можно улучшить?

Спасибо.


Редактировать:

  • @ Autowired во внутреннем репозитории - спасибо axtavt за указание на это.
  • read () может быть улучшено

1 Ответ

1 голос
/ 10 февраля 2010

Прежде всего, это не сработает, потому что Spring не может внедрить EntityManager во внутренний объект, созданный с помощью new. Итак, вы должны написать что-то вроде этого:

public class OrganizationRepository implements IOrganizationRepository { 

    @PersistenceContext
    public void setEntityManager(EntityManager em) {
        internalRepository.em = em;
    }
    ...
}

Также ваш read метод выглядит слишком общим. Он пропускает некоторые важные варианты использования, такие как getSigleResult и setFirstResult / setMaxResults.

Лично я предпочитаю вторую статью apporach, потому что при использовании композиции у вас будет EntityManager в OrganizationRepository для реализации функций, пропущенных в IInternalGenericRepository.

...