DAO дизайн шаблона - PullRequest
       18

DAO дизайн шаблона

12 голосов
/ 31 марта 2012

Допустим, у нас есть пара сущностей, которые мы хотим сохранить с помощью объектов DAO.Таким образом, мы реализуем правильный интерфейс, чтобы мы получили

class JdbcUserDao implements UserDao{
//...
}

class JdbcAddressDao implements AddressDao{
//...
}

Так что, если я хочу иметь возможность переключать реализации персистентности с JDBC на JPA (например) и наоборот, мне нужно иметь JPAUserDaoи JPAAddressDao ... То есть, если бы у меня было 20 сущностей, и я решил переключить реализации (используя DI-контейнер), мне пришлось бы переключать каждую реализацию Jdbc с помощью JPA в коде.

Теперь, возможно, я неправильно понялкак работает DAO, но ... Если бы у меня просто было

class JdbcDaoImpl implements UserDao,AddressDao{
//...
}

, я бы тогда имел все реализации JDBC в одном классе, и переключение реализаций было бы просто.Кроме того, количество DaoImpl равно количеству интерфейсов Dao.Почему бы просто не сгруппировать их по реализации (jdbc, JTA, JPA ...) и иметь все в одном классе?

Заранее спасибо.

Ответы [ 3 ]

20 голосов
/ 31 марта 2012

Наличие одного класса, реализующего каждый интерфейс DAO во всем приложении, было бы довольно плохим дизайном.

Более типичным шаблоном является наличие интерфейса BaseDAO (также часто называемого GenericDAO) и JPABaseDAO, JDBCBaseDAO и т. Д. Эти базовые классы будут содержать такие методы, как find / get / read, save / сохранить / сохранить, обновить / изменить и удалить / удалить / удалить.

Определенные интерфейсы DAO, такие как UserDAO, наследуются от BaseDAO, а конкретные реализации, такие как JPAUserDAO, расширяются от JPABaseDAO.

Интерфейс BaseDAO может выглядеть следующим образом:

public interface BaseDAO <T> {      
    T getByID(Long ID);
    T save(T type);
    T update(T type);
    void delete(T type);
}

И UserDAO интерфейс:

public interface UserDAO extends BaseDAO<User> {
    List<User> getAllAuthorized();
}

Пример «голых костей» JPABaseDAO, реализующего этот интерфейс:

@Stateless
public class JPABaseDAO<T> implements BaseDAO<T> {

    @PersistenceContext
    private EntityManager entityManager;

    private final Class<T> entityType;

    @SuppressWarnings("unchecked")
    public JPABaseDAO() {
        this.entityType = ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
    }

    @Override
    public T getByID(Long ID) {
        return entityManager.find(entityType, ID);
    }

    @Override  
    public T save(T type) {
        return entityManager.persist(type);        
    }

    @Override  
    public T update(T type) {        
        return entityManager.merge(type);
    }

    @Override
    public void delete(T type) {
        entityManager.remove(entityManager.contains(type) ? type : entityManager.merge(type));
    }

}

И пример реализации UserDAO, который наследуется от него:

@Stateless
public class JPAUserDAO extends JPABaseDAO<User> implements UserDAO {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public List<User> getAllAuthorized() {
        return entityManager.createNamedQuery("User.getAllAuthorized", User.class)
                            .getResultList();
    }
}

На практике базовый класс часто может прозрачно делать некоторые другие вещи, например, проверять, реализует ли объект какой-либо интерфейс Auditable, и автоматически устанавливать дату и пользователя, который его изменил, и т. Д.

При использовании EJB для реализации ваших DAO одной из стратегий изменения реализаций будет помещение всех реализаций JDBC в один пакет, а всех реализаций JPA - в другой. Затем включите только один пакет реализации в вашу сборку.

1 голос
/ 31 марта 2012

Весь смысл внедрения зависимостей состоит в том, чтобы упростить переключение между реализациями и отделить пользователя от поставщика.Следовательно, все структуры DI предоставляют некоторый способ «сгруппировать» несколько реализаций (здесь ваша JDBC-группа и ваша JPA-группа) и переключать их в одном месте.

Кроме того: Обычно число потребителей (в вашем случае: некоторая бизнес-логика, работающая с пользователями и адресами) обычно больше, чем количество DAO, которые DI-инфраструктура в любом случае отменит для вас.Предположим: 50 бизнес-компонентов, два интерфейса и две реализации для каждого интерфейса (всего 4): даже 50 основных DI позаботятся о 50. Использование группировки сократит оставшийся остаток вдвое за вас.

0 голосов
/ 01 февраля 2014

Определенно существуют возможности для реализации шаблона DAO широко технологически независимым способом, так что становится возможным переключение технологии постоянства или даже смешивание нескольких технологий. В этой статье представлена ​​одна схема реализации, включая исходный код на github.

http://codeblock.engio.net/?p=180

...