Чтобы дать вам представление о том, как будет выглядеть более современный DAO:
@Stateless
public class JPAApplicantDAO implements ApplicantDAO {
@PersistenceContext(unitName = "myPU")
private EntityManager entityManager;
@Override
public Applicant getByID(Long applicantID) {
return entityManager.find(Applicant.class, applicantID);
}
@Override
public void update(Applicant applicant) {
applicant.setLastModifiedDate(new Date());
entityManager.merge(applicant);
}
@Override
public void delete(Applicant applicant) {
Applicant deletedApplicant = applicant;
if (!entityManager.contains(applicant)) {
deletedApplicant = entityManager.merge(applicant);
}
entityManager.remove(deletedApplicant);
}
@Override
public List<Applicant> getBySomethingID(Long somethingID) {
return entityManager.createNamedQuery("Applicant.getBySomethingID", Applicant.class)
.setParameter("somethingID", somethingID)
.getResultList();
}
}
Теперь было предложено отказаться от всей концепции DAO и напрямую использовать менеджера сущностей везде. Я не совсем согласен с этим.
Этот пример DAO показывает 4 различных метода. Первый метод - это простое получение по основному идентификатору объекта. Именно такой метод заставляет людей задуматься, нужна ли абстракция DAO. Но читайте дальше.
Второй метод показывает метод обновления. В этом случае приложение может захотеть сделать что-то дополнительное для объекта, например, установить дату последнего изменения. DAO - вполне естественное место для этого. Да, это может быть сделано и в БД, но тогда DAO все равно будет полезен, поскольку вам, возможно, придется прочитать объект обратно, чтобы узнать об установленной дате.
Третий метод - метод удаления. Из-за специфической проблемы в спецификации JPA вы можете удалить только объект, который находится в присоединенном состоянии. Это означает некоторую дополнительную логику, чтобы проверить, присоединен ли он (содержится в контексте постоянства), а если нет, присоединить (объединить).
Четвертый метод показывает получение данных с помощью (JPQL) запроса. И имя запроса, и имя параметра не являются типобезопасными. DAO удобно скрывает это за типобезопасным Java-методом. Да, вы можете извлечь эти имена в константу, но связь между этим конкретным параметром и этим конкретным запросом все равно не будет применена.
Как правило, DAO допускает определенный объем рефакторинга. В какой-то момент я могу захотеть заменить запрос JPQL критерием запроса. Изменение этого на всех колл-сайтах может быть проблематичным. Тогда есть случай, когда менеджер сущностей как общий DAO просто силен. Я не хочу отправлять их на все клиентские сайты (в случае удаленных клиентов это даже невозможно или очень плохая практика).
Наконец, использование менеджера сущностей из клиентского кода, который сам не является транзакционным, означает, что этот клиент должен беспокоиться о транзакциях. Это добавляет много подробностей в код. С DAO клиентский код становится намного проще:
@Named
@RequestScoped
public class SomeBean {
@EJB
private ApplicantDAO applicantDAO;
public void someMethod() {
applicantDAO.delete(applicant);
}
}