Spring @Transactional issue/challenge 放置在服务层
Spring @Transactional issue/challenge while placing in service layer
我的 Spring 应用程序分层为 Bean、服务和 DAO。所有的@Transactional 注解都在服务层。
这是一个特定场景下的伪代码。
UserBean.java
saveUser() {
userService.manageUser();
}
UserServiceImpl.java
@Transactional
public void manageUser() {
userDAO.createUser();
userDAO.updateParentUser();
}
UserDAOImpl.java
createUser() {
//insert user record in database
}
updateParentUser() {
//update parent user's database record
}
在我的保存用户测试用例中,更新父用户操作在某些情况下可能会由于主键冲突而失败,这在意料之中。
由于@Transactional注解是在服务class中实现的,这种违规异常只会在beanclass中被通知。
在我的服务中获取此 PK 违规通知的选项是什么 class?
[然后我可以在不同的业务流程中从那里处理它。]
如果我在服务 class 中添加新方法并从那里调用 manageUser(),@Transactional 注释将无法正常工作。这是由于 limitation/property of AOP。 Spring 需要外部调用 @Transactional 方法。
- 使用程序化事务管理并在 try catch 块中处理异常
引入委托class并在那里的事务中执行manageUser:
@Transactional(REQUIRED)
public void manageUser() {
try{
delegate.manageUser();
} catch (Exception ex ) {
//handle
}
}
并在委托中 class
@Transactional(REQUIRES_NEW)
public void manageUser() {
}
在您从@Transactional 方法return 之前,create/update 不会被提交。如果 create/update 在此之前被刷新到数据库,那么您 可能 在方法中得到异常,但在您的情况下,它在提交之前不会被刷新。
您可以在提交前强制刷新 create/update。您没有说您使用的是 Hibernate 还是 JPA,但是 session.flush()
或 entityManager.flush()
应该可以解决问题。
我转向了 AspectJ 方法,而不是 Spring 基于代理的 AOP。这使我可以灵活地从同一服务的另一个方法调用 manageUser() 方法 class,我可以在那里处理异常。
我的 Spring 应用程序分层为 Bean、服务和 DAO。所有的@Transactional 注解都在服务层。
这是一个特定场景下的伪代码。
UserBean.java
saveUser() {
userService.manageUser();
}
UserServiceImpl.java
@Transactional
public void manageUser() {
userDAO.createUser();
userDAO.updateParentUser();
}
UserDAOImpl.java
createUser() {
//insert user record in database
}
updateParentUser() {
//update parent user's database record
}
在我的保存用户测试用例中,更新父用户操作在某些情况下可能会由于主键冲突而失败,这在意料之中。
由于@Transactional注解是在服务class中实现的,这种违规异常只会在beanclass中被通知。
在我的服务中获取此 PK 违规通知的选项是什么 class? [然后我可以在不同的业务流程中从那里处理它。]
如果我在服务 class 中添加新方法并从那里调用 manageUser(),@Transactional 注释将无法正常工作。这是由于 limitation/property of AOP。 Spring 需要外部调用 @Transactional 方法。
- 使用程序化事务管理并在 try catch 块中处理异常
引入委托class并在那里的事务中执行manageUser:
@Transactional(REQUIRED) public void manageUser() { try{ delegate.manageUser(); } catch (Exception ex ) { //handle } }
并在委托中 class
@Transactional(REQUIRES_NEW) public void manageUser() { }
在您从@Transactional 方法return 之前,create/update 不会被提交。如果 create/update 在此之前被刷新到数据库,那么您 可能 在方法中得到异常,但在您的情况下,它在提交之前不会被刷新。
您可以在提交前强制刷新 create/update。您没有说您使用的是 Hibernate 还是 JPA,但是 session.flush()
或 entityManager.flush()
应该可以解决问题。
我转向了 AspectJ 方法,而不是 Spring 基于代理的 AOP。这使我可以灵活地从同一服务的另一个方法调用 manageUser() 方法 class,我可以在那里处理异常。