简体   繁体   English

JPA服务层事务

[英]JPA service layer transactions

I have MVC layered app using JPA 2, Hibernate (without Spring or any additional framework). 我有使用JPA 2,Hibernate(没有Spring或任何其他框架)的MVC分层应用程序。

Now transactions are achieved only on DAO layer like this: 现在,事务只能在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();
        }
    }
}

But what I want is to obtain transaction on service layer: 但是我想要的是在服务层上获取事务:

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
    }
}

One of possible solution is to wrap code inside transferUserAccount() method in another try/catch/finally with em.getTransaction().begin() (or create custom @Transactional annotation that will do that under the hood), but I am not sure how JPA handles nested transactions. 可能的解决方案之一是使用em.getTransaction().begin()在另一个try/catch/finally em.getTransaction().begin()代码包装在transferUserAccount()方法内(或创建自定义的@Transactional批注,在em.getTransaction().begin()进行此操作),但我不是确定JPA如何处理嵌套事务。 Also such solution exposes the DAO specific things like entity manager into service layer. 同样,这种解决方案将DAO特定的东西(如实体管理器)暴露给服务层。

Anyway, is the solution with nested transaction within transferUserAccount() is appropriate? 无论如何,在transferUserAccount()使用嵌套事务的解决方案是否合适?

Are there any other solutions to handle such cases? 还有其他解决方案来处理此类情况吗? Thanks in advance! 提前致谢!

If you do not want to leak the transaction management into your service, I would suggest to further split the DAO such that the DAO has two DAOs/repositories-attributes (one for User , one for Account ), create the transaction in the DAO-method and pass the EntityManager down to the User - and Account -DAO/repository. 如果您不希望将事务管理泄漏到服务中,我建议进一步拆分DAO,以使DAO具有两个DAO /存储库-属性(一个用于User ,一个用于Account ),在DAO-中创建事务。方法,然后将EntityManager向下传递给User -和Account -DAO /存储库。

Another option would be to create a method transferAccount(Account account, user from, user to) within AccountDao , create the transaction there, perform all your logic and then call userDao.save(from, em) , userDao.save(to, em) and save(account, em) from there. 另一种选择是在AccountDao中创建方法transferAccount(Account account, user from, user to)在其中创建transaction ,执行所有逻辑,然后调用userDao.save(from, em)userDao.save(to, em)并从那里save(account, em)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM