Наличие одного класса, реализующего каждый интерфейс 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 - в другой. Затем включите только один пакет реализации в вашу сборку.