使用JPA / Spring的(通用)DDD存储库的方法:看起来不对吗?

时间:2010-02-10 19:36:42

标签: java spring jpa domain-driven-design ddd-repositories

我对DDD和JPA很新。

我正在使用JPA和Spring开发通用存储库。我非常喜欢文章DDD: The Generic RepositoryJPA implementation patterns: Data Access Objects中公开的方法。我的目标是使用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);
    }
}

使用JPA和Spring实现DDD Repository似乎是一种很好的方法。然后将OrganizationRepository注入我的服务层。

我希望有外部观点以避免瑕疵或误解。您如何看待以及如何改进?

感谢。


修改:

  • @Autowired on internalRepository - 感谢axtavt指出它。
  • read()可以改进

1 个答案:

答案 0 :(得分:1)

首先,它不起作用,因为Spring无法将EntityManager注入到使用new创建的内部对象中。所以,你必须写这样的东西:

public class OrganizationRepository implements IOrganizationRepository { 

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

此外,您的read方法看起来有点过于通用。它错过了一些重要的用例,例如getSigleResultsetFirstResult / setMaxResults

就我个人而言,我更喜欢第二篇文章apporach,因为使用撰写文章,您最终会在EntityManager中使用OrganizationRepository来实现IInternalGenericRepository中遗漏的功能。