【问题标题】:JPA service layer transactionsJPA 服务层事务
【发布时间】:2019-11-11 12:41:04
【问题描述】:

我有使用 JPA 2、Hibernate(没有 Spring 或任何其他框架)的 MVC 分层应用程序。

现在事务只在 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/finallyem.getTransaction().begin() (或创建自定义 @Transactional 注释,将在引擎盖下做到这一点),但我不确定 JPA 如何处理嵌套事务。 这种解决方案也暴露了 DAO 特定的东西,比如实体管理器 进入服务层。

无论如何,在transferUserAccount() 内嵌套事务的解决方案是否合适?

是否有其他解决方案来处理此类情况? 提前致谢!

【问题讨论】:

  • 我会假设用户和帐户之间存在一对五的关联,对吗?如果是这样,您可以在帐户对象内的用户属性中添加适当的级联类型,以在保存/更新帐户时保存/更新相应的用户。
  • @Turing85 是的,你是对的,但还有其他事情应该以原子方式执行。问题是如何在没有 spring 的情况下使用普通 jpa 在服务层实现事务性
  • 如果您不想将事务管理泄漏到您的服务中,我建议进一步拆分 DAO,使 DAO 有两个 DAO/repositories-attributes(一个用于User,一个用于Account),在 DAO 方法中创建事务并将其传递给 User- 和 Account-DAO/repository。
  • @Turing85 你的意思是把EntityManager明确地传递给所有应该在一个事务中完成的dao方法?
  • 不使用spring框架的原因是什么?我写过一次我自己的自定义事务注释,但这一点也不好玩。

标签: java hibernate jpa entitymanager


【解决方案1】:

如果您不想将事务管理泄漏到您的服务中,我建议进一步拆分 DAO,使 DAO 具有两个 DAO/存储库属性(一个用于User,一个用于Account),在 DAO 方法中创建事务并将EntityManager 向下传递给User- 和Account-DAO/repository。

另一种选择是在AccountDao 中创建一个方法transferAccount(Account account, user from, user to),在那里创建transaction,执行所有逻辑,然后从那里调用userDao.save(from, em)userDao.save(to, em)save(account, em)

【讨论】:

    猜你喜欢
    • 2011-08-14
    • 1970-01-01
    • 2017-06-07
    • 2013-05-16
    • 1970-01-01
    • 2018-07-02
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多