Транзакции уровня сервиса JPA - PullRequest
1 голос
/ 30 июня 2019

У меня есть многоуровневое приложение MVC, использующее JPA 2, Hibernate (без Spring или каких-либо дополнительных фреймворков).

Теперь транзакции выполняются только на уровне DAO, например:

public class AccountDao {
    private EntityManagerFactory emf;

    public AccountDao(EntityManagerFactory emf) {
        this.emf = emf;
    }

    public void saveAccount(Account account) {
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        try {
            em.persist(account);
            em.getTransaction().commit();
        } catch (Exception ex) {
            em.getTransaction().rollback();
        } finally {
            em.close();
        }
    }
}

Но я хочу получить транзакцию на уровне сервиса:

public class AccountService {
    private AccountDao accountDao;
    private UserDao userDao;

    //needed the method to be in transaction
    public void transferUserAccount(){
        User user = // ...
        userDao.saveUser(user);

        Account account = //
        accountDao.saveAccount(account);
        //rest logic that has to be executed atomically
    }
}

Одно из возможных решений - заключить код в метод transferUserAccount() в другой try/catch/finally с помощью em.getTransaction().begin() (или создать собственную аннотацию @Transactional, которая будет это делать под капотом), но я не уверен, как JPA обрабатывает вложенные транзакции. Также такое решение раскрывает специфические для DAO вещи, такие как менеджер сущностей. на уровень обслуживания.

В любом случае, подходит ли решение с вложенной транзакцией в transferUserAccount()?

Есть ли другие решения для таких случаев? Заранее спасибо!

1 Ответ

0 голосов
/ 30 июня 2019

Если вы не хотите просачивать управление транзакциями в свой сервис, я бы предложил дополнительно разделить DAO так, чтобы у DAO было два атрибута DAO / репозитория (один для User, один для Account), создайте транзакцию в DAO-методе и передайте EntityManager в User - и Account -DAO / репозиторий.

Другой вариант - создать метод transferAccount(Account account, user from, user to) в AccountDao, создать там transaction, выполнить всю логику, а затем вызвать userDao.save(from, em), userDao.save(to, em) и save(account, em) оттуда.

...