Прежде всего, следует ли вам использовать слой DAO или нет, это спор, который начался с момента появления JPA и EntityManager, который многие люди считают самим DAO. Ответ на этот вопрос зависит от типа приложения, которое вы разрабатываете, но в большинстве случаев вы захотите:
- Использовать критерии JPA или пользовательские запросы . В этом случае вы, вероятно, не хотите смешивать свою бизнес-логику с созданием запроса. Это привело бы к крупным методам и нарушило бы принцип единственной ответственности .
- Повторно используйте ваш код JPA в максимально возможной степени . Допустим, вы создали запрос критерия, который возвращает список сотрудников, возраст которых составляет от 40 до 65 лет и которые работают в компании более 10 лет. Возможно, вы захотите повторно использовать этот тип запроса где-то еще на уровне службы, и если это так, то наличие его в службе усложнит эту задачу.
При этом, если все, что у вас есть в приложении, - это операции CRUD, и вы не думаете, что вам может понадобиться повторно использовать какой-либо код JPA, слой DAO, вероятно, является чем-то излишним, поскольку он будет действовать как простая оболочка EntityManager. , что звучит неправильно.
Во-вторых, я бы посоветовал использовать транзакции, управляемые контейнером, когда это возможно. Если вы используете EJB-контейнер, такой как TomEE или JBoss, это позволит избежать большого количества кода, предназначенного для программного создания и управления транзакциями.
В случае, если вы используете контейнер en EJB, вы можете воспользоваться декларативным управлением транзакциями. Примером использования DAO может быть создание компонентов уровня обслуживания как EJB, так и ваших DAO.
@Stateless
public class CustomerService {
@EJB
CustomerDao customerDao;
public Long save(Customer customer) {
// Business logic here
return customerDao.save(customer);
}
}
@Stateless
public class CustomerDao {
@PersistenceContext(unitName = "unit")
EntityManager em;
public Long save(Customer customer) {
em.persist(customer);
return customer.getId();
}
public Customer readCustomer(Long id) {
// Criteria query built here
}
}
В приведенном выше примере конфигурация транзакции по умолчанию ОБЯЗАТЕЛЬНА, что означает, что при отсутствии транзакции в компоненте вызывающей стороны EJB создаст новую транзакцию. Если вызывающая сторона уже создает транзакцию (CustomerService), вызываемый компонент (CustomerDao) наследует транзакцию. Это можно настроить с помощью аннотации @ TransactionAttribute .
Если вы не используете контейнер EJB, я думаю, что ваш пример, приведенный выше, вероятно, будет эквивалентен.
РЕДАКТИРОВАНИЕ : ради простоты я использовал EJB без интерфейса выше, но было бы неплохо использовать интерфейс для них, например, для их создания. более проверяемый.