Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 727
j2emanue Avatar asked Jun 15 '17 09:06

j2emanue


1 Answers

I am not sure this is what all you looking for but In my application I am using described DAO pattern with Spring

So im confused on how many Repositories i would need.

IMHO you will need at least single Repository for each entity as they lead to simple design but since you are making them generic and they are up in hierarchy, can be used simply with child classes/interfaces

Below is the example

Interface to define all basic methods that to use commonly

public interface GenericDAO<T, ID extends Serializable> {


    T findById(ID id, LockModeType lock);

    void save(T entity);

    T update(T entity);

    List<T> findAll();
}

Generic Implementation

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);

}

Implemented 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();
    }

}

Same for 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();
    }
}

Here this generic implementation needs two things to work: an EntityManager and an entity class. A subclass must provide the entity class as a constructor argument. EntityManager is provided by using PersistenceContext or you can use getter-setter methods for the same. Since GenericDAOImpl is abstract threfore you cannot use it directly but Indirectly and most of the commnoly used methods are generic and up in hierarchy which makes them Ideal candidate to be reused.

You can read more about this from book Java Persistence with Hibernate 2nd Edition

like image 111
bananas Avatar answered Nov 03 '22 19:11

bananas