1

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

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 类,它将异常的详细信息记录到数据库中。只有 UserDefinedException 被记录,而 Null 指针异常没有被记录。任何人都可以帮助我。

日志入口.java

private long id;
private String desc;

// getters and setters

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

4

1 回答 1

2

您得到了这样的结果,因为在您的情况下 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();
    }

}

然后只需将您的异常记录器注入必要的服务类。例如:

@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 不会回滚事务处理异常。这描述了你得到的行为。在您的情况下,仅针对运行时异常回滚外部事务。这就是为什么当您尝试记录 NullPointerException 时,整个事务会回滚并且您的日志记录不会添加到数据库中。但是,当您尝试记录 UserDefinedException 事务时,尽管已引发错误并且您的日志记录已写入数据库,但仍成功提交了事务。

于 2013-02-09T12:32:33.103 回答