Repository design pattern - should there be one repo for every Dao?

时间:2017-06-15 09:33:27

标签: java repository-pattern dao mvp

i have a few DAOs in my app which access a database for CRUD operations. Lets say there News, weather and , sports DAO. So im confused on how many Repositories i would need. should i just use one repository say DataRepository and let me hold my database and all dao's. and encapsulate methods for the CRUD operations in it ? or should each DAO have its own repository ?

I mean a repository should return only data objects that the calling layer understands. so its like a encapsulation over the DAOs but im not sure if i should create one per DAO or just have one repo per app, etc.

If you read this article we begin to understand that the pattern is over engineered or over abstracted. Its turned into hiding detail vs minimizing query statements.

But it seems There should be a Repo per DAO as the interface itself looks like this:

interface Repository<T> {
void add(T item);
void remove(Specification specification);
List<T> query(Specification specification);

}

where T can be the type/table of data DAO accesses. Just need clarification now. Can you imagine i have 30 different types, so then i need 30 different Repo implementations. this is ridiculous. It seems the repository pattern itself is like a DAO, no different. im so confused.

1 个答案:

答案 0 :(得分:3)

我不确定这是你要找的所有内容但在我的应用程序中我使用DAO模式描述了Spring

  

所以我很困惑我需要多少个存储库。

恕我直言,你需要每个实体至少有一个单独的存储库,因为它们会导致简单的设计,但由于你使它们成为通用的并且它们处于层次结构中,因此可以简单地用于子类/接口

以下是示例

用于定义通常使用的所有基本方法的接口

public interface GenericDAO<T, ID extends Serializable> {


    T findById(ID id, LockModeType lock);

    void save(T entity);

    T update(T entity);

    List<T> findAll();
}

通用实施

public abstract class GenericDAOImpl<T, ID extends Serializable> implements GenericDAO<T, ID> {

    @PersistenceContext
    protected EntityManager em;

    private final Class<T> entityClass;

    public GenericDAOImpl(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    @Override
    public T findById(ID id, LockModeType lock) {
        return em.find(entityClass, id, lock);
    }

    @Override
    public void save(T entity) {
        em.persist(entity);

    }

    @Override
    public T update(T entity) {
        return em.merge(entity);
    }

    @Override
    public List<T> findAll() {
        CriteriaQuery<T> c = em.getCriteriaBuilder().createQuery(entityClass);
        c.select(c.from(entityClass));
        return em.createQuery(c).getResultList();
    }
.
.
.
}

Foo class

@Entity
public class Foo implements Serializable {

    private static final long serialVersionUID = 1L;
    private Long id;
    private String text;
}

Foo Repositiry

public interface FooRepositiry extends GenericDAO<Foo, Long> {

    Foo findTextById(Long id);

}

实施Foo Repositiry

@Transactional
@Repository
public class FooRepoImpl extends GenericDAOImpl<Foo, Long> implements FooRepositiry {

    public FooRepoImpl() {
        super(Foo.class);
    }

    @Override
    public Foo findTextById(Long id) {
        CriteriaQuery<Foo> c = em.getCriteriaBuilder().createQuery(Foo.class);
        // .
        // .
        // .
        return em.createQuery(c).getSingleResult();
    }

}

Bar class

相同
@Transactional
@Repository
public class BarRepoImpl extends GenericDAOImpl<Bar, Long> implements BarRepo {

    public BarRepoImpl() {
        super(Bar.class);
    }

    @Override
    public List<Bar> findAllBarWithText(String text) {
        CriteriaQuery<Bar> c = em.getCriteriaBuilder().createQuery(Bar.class);
        return em.createQuery(c).getResultList();
    }
}

这里的通用实现需要两件事:EntityManager和一个 实体类。子类必须将实体类作为构造函数参数提供。 EntityManager是使用PersistenceContext提供的,或者您可以使用getter-setter方法。因为GenericDAOImpl是抽象的,所以你不能直接使用它,但间接地和大多数使用的commnoly方法都是通用的,并且在层次结构中,这使它们成为重用的理想候选者。

您可以在书籍Java Persistence with Hibernate 2nd Edition

中阅读更多相关信息