Подтвердить что ты не робот

Схема проектирования DAO

Итак, скажем, у нас есть пара объектов, которые мы хотим сохранить с помощью объектов 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...) и иметь все под одним классом?

Спасибо заранее.

4b9b3361

Ответ 1

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

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

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

Интерфейс

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

Пример bare bones для 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 в другой. Тогда просто включите только один пакет реализации в свою сборку.

Ответ 2

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

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

Ответ 3

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

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