Generic DAO pattern in Hibernate

浪尽此生 提交于 2019-12-02 19:51:56
Arthur Ronald

Umesh I will show you how we implement this functionality

The interface

public interface Repository<INSTANCE_CLASS, PRIMARY_KEY_CLASS> {

    void add(INSTANCE_CLASS instance);
    void merge(INSTANCE_CLASS instance);
    void remove(PRIMARY_KEY_CLASS id);
    INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id);
    INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id, Class fetchingStrategy, Object... args);
    List<INSTANCE_CLASS> findAll();
    List<INSTANCE_CLASS> findAll(Class fetchingStrategy, Object... args);
    List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize);
    List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize, Class fetchingStrategy, Object... args);
    List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria);
    List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria, Class fetchingStrategy, Object... args);
    List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria);
    List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria, Class fetchingStrategy, Object... args);

}

Because you usually will not need all of methods shown above, we create an abstract class with the purpose of being a dummy implementation

public abstract class AbstractRepository<INSTANCE_CLASS, PRIMARY_KEY_CLASS> implements Repository<INSTANCE_CLASS, PRIMARY_KEY_CLASS> {

    public void add(INSTANCE_CLASS instance) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void merge(INSTANCE_CLASS instance) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void remove(PRIMARY_KEY_CLASS id) {
        throw new UnsupportedOperationException("Not supported yet.");
    }


    public INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id, Class fetchingStrategy, Object... args) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List<INSTANCE_CLASS> findAll() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List<INSTANCE_CLASS> findAll(Class fetchingStrategy, Object... args) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize, Class fetchingStrategy, Object... args) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria, Class fetchingStrategy, Object... args) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria, Class fetchingStrategy, Object... args) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}

Now, for instance, if you want a repository which needs only add method, you can use

public class PersonRepository extends AbstractRepository<Person, Integer> {

    public void add(Person instance) {
        /**
          * person implmentatiuon goes here
          */    
    }

}

If other developer try to access other than add method, he or she will get UnsupportedOperationException

Criteria is just a marker interface.

public interface Criteria {}

The purpose of some methods define a parameter Class fetchingStrategy is to match externalized named queries. This way, I avoid hand-coded string which is error-prone. This approach is used by JSR-303 bean validation, for instance, to validate groups of properties. See here

public class Person {
    public static interface PERSON_WITH_ADDRESS {}
}

The externalize named query is shown as follows

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <query name="PERSON_WITH_ADDRESS">
        <![CDATA[
            from 
                Person p
            left join fetch 
                p.address
        ]]>
    </query>
</hibernate-mapping>

So when i want to retrieve all of person with address, i call

PersonRepository<Person, Integer> respository ...

List<Person> personList = repository.findAll(PERSON_WITH_ADDRESS.class);

findAll can be written as

public class PersonRepository extends AbstractRepository<Person, Integer> {

    List<Person> findAll(Class fetchingStrategy, Object... args) {
        if(fetchingStrategy.isAssignableFrom(PERSON_WITH_ADDRESS.class)) {
            sessionFactory.getCurrentSession()
                          .getNamedQuery(fetchingStrategy.getSimpleName())
                          .list();
        }

        throw new UnsupportedOperationException("Not supported yet.");
    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!