将异常记录到数据库中
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);
}
我从无状态 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);
}