【发布时间】: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/finally 和 em.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