您好我正在尝试将异常记录到数据库
中public void a(){
try{
String c = b();
}catch (Throwable ex){
com.log.Logger.log(ex);
throw new UserDefinedException(ex);
}
}
public String b(){
throw new NullPointerException("Transaction Logger")
}
我有一个LoggerImpl类,它将异常的详细信息记录到DB中。 只记录UserDefinedException,而不是Null Pointer Exception。任何人都可以帮助我。
LogEntry.java
private long id;
private String desc;
// getters and setters
Logger.java
public long log(Throwble ex){
LogEntry entry = new LogEntry();
entry.setDesc(ex.getMessage());
LoggerImpl log = new LoggerImpl();
log.insertLog(entry);
return entry.getId();
}
LoggerImpl.java
@Transactional(propogation = PROPOGATION.REQUIRES_NEW)
public void insertLog(LogEntry log){
insert.update(//fields);
}
Id使用序列增量器生成
我正在使用JTA事务管理器。
答案 0 :(得分:1)
你得到了这样的结果,因为在你的情况下,LoggerImplementation类不是由Spring容器管理的,容器不会为insertLog(..)方法启动新的事务(因为它应该是这样)。要使这个类得到管理,你应该将它注入你的bean中。我建议你进行这样的重构。这将有效。
而不是让Logger和LoggerImpl类创建实现此接口的Logger接口和LoggerImpl类。
public interface Logger {
long log(Throwable ex);
}
@Transactional
@Component
public final class LoggerImpl implements Logger {
@PersistenceContext
private EntityManager entityManager;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public long log(Throwable ex) {
LogEntry entry = new LogEntry();
entry.setDescription(ex.getMessage());
entityManager.persist(entry);
return entry.getId();
}
}
然后简单地将您的异常Logger注入必要的服务类。例如:
@Transactional(rollbackFor=Exception.class)
@Service
public class TestService {
@Autowired
private Logger logger;
public void a() throws UserDefinedException {
try {
b();
} catch (Throwable ex) {
logger.log(ex);
throw new UserDefinedException(ex);
}
}
public String b() {
throw new NullPointerException("Transaction Logger");
}
}
现在外部事务将被回滚,但内部新事务将把数据写入数据库。
注意TestService类的 @Transactional 注释中的 rollbackFor 属性。这是必要的,因为默认情况下Spring不会回滚chacked异常的事务。这描述了你所获得的行为。在您的情况下,外部事务仅针对运行时异常进行回滚。这就是为什么当您尝试记录NullPointerException时,将回滚整个事务并且不会将您的日志记录添加到数据库中。但是当您尝试记录UserDefinedException时,事务已成功提交,尽管已经抛出错误并且您的日志记录已写入数据库。