将异常记录到DB中 - Java Spring

时间:2013-02-09 09:56:40

标签: spring

您好我正在尝试将异常记录到数据库

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事务管理器。

1 个答案:

答案 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时,事务已成功提交,尽管已经抛出错误并且您的日志记录已写入数据库。