首先,我使用Eclipse,JBoss应用服务器和sql server数据库。我正在开发的项目是处理Java bean。我正在使用hibernate来创建和更新数据库。
我想要实现的目标:每次用户创建(持久化)“EntityClass”(见下文)时,我想在数据库的不同表中插入有关创建的信息。
我的(目前没有工作)解决方案:
我正在使用拦截器类拦截像这样的java Session bean中的方法;
@Interceptors(MyInterceptorClass.class)
public EntityClass createEntityClass(EntityClass e) {
em.persist(e);
return e;
}
我的InterceptorClass看起来像这样:
public class MyInterceptorClass{
@AroundInvoke
public Object logMethod(InvocationContext iCtx) throws Exception {
Logger logger = new Logger();
logger.setAction("create");
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
session.save(logger);
session.getTransaction().commit()
return iCtx.proceed();
}
我的Logger类是一个实体java bean,当我的拦截器拦截目标方法时,我希望将其保存到数据库中,如您所见。记录器代码:
@Entity
@Table(name = "auditlog")
public class Logger implements Serializable {
private int auditLogId; //auto-increment in DB
private String action;
...
//setters and getters with proper mapping to the related database table
}
正如你现在可能已经想到的那样,这个投标人抛出了一个例外,说我在托管交易期间无法提交。如果没有开始新的交易,我有什么方法可以做到这一点吗?
我试过了:
*在记录器类
上将事务属性更改为REQUIRES_NEW*使用会话bean @PreDestroy回调方法
保留logger对象我愿意就如何解决这个问题提出建议。
答案 0 :(得分:1)
我通过使用Hibernate Envers进行实体审核来解决这个问题。
http://docs.jboss.org/envers/docs/index.html#quickstart
向用户3360944致信,向我暗示正确的方向。
答案 1 :(得分:0)
Hibernate是对的,你不能在托管事务中调用commit。将事件的日志记录与事件本身联系起来也是一个坏主意,因为永远不会告知您完全回滚的故障。
我建议使用日志记录功能的队列实现或调用Web服务来执行日志记录功能。那些可以在当前功能范围之外操作。
一个功能齐全的方法还可以捕获ctx.proceed()中抛出的任何异常并记录失败,这可能比成功更有趣。