【发布时间】:2012-07-25 08:16:42
【问题描述】:
在我基于 struts2、spring IoC 和 Transasctions、jpa、Hibernate 的应用程序中,我想引入一个“审计日志功能”,它将记录所有重要事件,例如:用户已创建/更新,或有人开了一张票...
我想将此日志保留在数据库中,因此我将拥有一个 DAO。为此,我还创建了一个服务类“AuditLogService”,它将具有事务行为“传播=“REQUIRES_NEW”,因为无论记录的事件是否成功,我都想记录该事件。
问题是,如果我的用户服务中有这样的东西:
@Override
public boolean saveUser(UserDto userDto) {
User u = new User();
u.setFirstName(userDto.getFirstName());
u.setLastName(userDto.getLastName());
u.setUserName(userDto.getUserName());
u.setPassword(userDto.getPassword());
u.setIsLdapUser(userDto.getIsLdapUser());
u.setId(userDto.getId());
u.setAgentId(userDto.getAgentId());
Boolean eventStatus = true;
String event="";
try{
if (u.getId()!=null){
dao.update(u);
event = "UPDATE_USER";
}else{
dao.create(u);
event = "CREATE_USER";
}
}catch (Exception e) {
e.printStackTrace();
eventStatus = false;
return false;
}
finally {
AuditLogEvent ale = auditLogEventDao.getAuditLogEvent(event);
auditLogService.addAuditLogEvent(ale, eventStatus,u.toString());
}
return false;
}
在提交保存用户方法之前执行审计日志方法并报告事件为真,但实际上该事件为假。
知道我该如何解决这个问题吗?或者这种方法可能不是最好的......?
-
更新!
在迈克尔的建议之后,我也将我的服务转变为一个方面@Aspect @Service class AuditLogAspectImpl implements AuditLogAspect { @Autowired private AuditLogDao dao; @Autowired private UserDao userDao; @Override @AfterReturning(pointcut = "execution(* xxx.yy.services..*.save*(..))", returning = "retVal") public boolean afterLogEvent(JoinPoint joinPoint,Object retVal){ }}
现在我有了像这里这样的方法签名。一切正常,我可以检测操作是否失败或成功,我可以将其记录到日志文件中,但是如果我想通过 dao 类将其记录到数据库中的表中,则当操作失败并且事务滚动时返回我的审核条目未插入。
首先我认为发生这种情况是因为这两个操作,需要审计的实际方法和审计事件都在相同的事务上下文中运行,如果其中一个被回滚,则整个事务是,并且我创建了一个方面日志记录部分的新事务。但这似乎行不通。
知道为什么吗?
【问题讨论】:
标签: spring spring-transactions