将异常记录到数据库中

Log Exception into DB

我从无状态 ejb 得到了一个方法调用,如下所示

@Stateless
@Local(MyCrudService.class)
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public class MyCrudServiceBean implements MyCrudService {

    @EJB
    private CrudService crudService;

    @Override
    public void writeLogEntry(StatementLog statementLog) {
        try {
            crudService.execute(statement.getSql());
        } catch (Exception e) {
            crudService.writeLogEntry(statementLog);
            throw new MyApplicationException(e.getLocalizedMessage());
        }
    }

    // ...

}

CrudSerivce:

@Stateless
@Local(CrudService.class)
@TransactionAttribute(TransactionAttributeType.MANDATORY)
@Interceptors(GenericFrepDataBaseUserInterceptor.class)
public class CrudServiceBean implements CrudService {

    public static final String PERSISTENCE_UNIT_NAME = "name";

    private EntityManager entityManager;

    @PersistenceContext(unitName = PERSISTENCE_UNIT_NAME)
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public void execute(String sqlString) {
        Query query = entityManager.createNativeQuery(sqlString);
        query.executeUpdate();
    }

    @Override
    public void writeLogEntry(StatementLog statementLog) {
        entityManager.persist(entity);
    }

    // ....
}

Statement 是一个实体,它得到了一个无效的 sql(比如 'invalid sql')。执行时出现以下错误

javax.ejb.EJBTransactionRolledbackException:JBAS011469

如果我调试它,我可以看到这发生在日志记录的行中。

我认为问题在于,因为我遇到异常,事务被回滚。因此无法写入数据库,因为不再有打开的会话。是这样吗?那么最佳做法是什么?自己手动打开一个会话对我来说太难看了。

你的方法log.writeErrorInDb需要启动它自己的事务,这样当主事务回滚时它仍然可以运行。是的,如果您的 Hibernate 会话已经关闭,那么您的日志 class 需要能够打开它自己的会话。然而,最好有一个覆盖整个代码块的事务边界,并将 Hibernate 会话绑定到它,然后将您的日志方法设置为需要一个新事务,以确保它可以在第一个事务被标记为回滚后运行.即两笔交易,但一个会话

根据您的代码,您应该能够注释您的日志方法:

@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void writeLogEntry(StatementLog statementLog) {
    entityManager.persist(entity);
}