如何在没有Hibernate Envers的情况下审核JPA

时间:2011-10-13 14:09:18

标签: jpa eclipselink audit entitylisteners show-sql

我需要为我的Java Web App制作审核模块。我使用EclipseLink,而不是Hibernate(不能使用Envers)。我搜索了很多方法来获取JPA正在执行的SQL或JPQL,所以我可以记录这样的事情:

System.out.println("User " + user + " from " + ip_address + " executed " + jpa_statement + " at " + new Date());

实际上,我会将此信息保存到历史数据库的表中。因此,我可以随时轻松检索此信息。这就是为什么“ SHOW SQL ”参数对我来说还不够。我真的需要SQL字符串,所以我可以在我的源代码中操作它。

我在JPA spec中发现了 EntityListener 功能,并认为它是放置我的日志代码的最佳位置。例如,postUpdate方法可以记录对象更新的时间。但我的问题是我无法执行已执行的SQL。

这是我的意思的一个例子:

public class AuditListener {    
  @PostUpdate
  public void postUpdate(Object object) {
    User user = (User)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user");
    String ip_address =  (User)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("ip_address");
    String jpa_statement = object.getSQL();
    System.out.println("User " + user + " from " + ip_address + " executed " + jpa_statement + " at " + new Date());
  }

}

但是“object.getSQL()”不存在。那么如何获取SQL语句呢?

如果有人能指出我正确的方向,我将不胜感激!

3 个答案:

答案 0 :(得分:13)

EclipseLink完全支持历史记录跟踪。

请参阅, http://wiki.eclipse.org/EclipseLink/Examples/JPA/History

JPA事件不包含更改的内容,只包含对象。

EclipseLink还支持DesriptorEvents(请参阅DescriptorEventListener),它也定义了postUpdate但包含描述更改的ObjectChangeSet,还有包含SQL和DatabaseRecord的UpdateObjectQuery。

答案 1 :(得分:6)

审计的好处很好,但我认为,可以有一个更好的审计解决方案。在Envers中有几个 不足之处: 每个表有两个db表。但很少使用第二张表。对于600多个表的大型企业项目来说,这是个问题。 Envers仅适用于数据库更改。当我需要解决其他应用程序组件的审计时,我需要不同的审计解决方案。 对馆藏的审核并不理想。 何时更改数据库模式我也必须更改审计表。我可以丢失一些审计信息,或者我有很多工作要将新的审计信息更新到新模式。 将审计信息保存到同一个数据库是耗费时间和空间的。

我开始研究小型审计库,其中的信息存储在MongoDB数据库中: 用于所有hibernate对象的一个​​集合。存储对象的每个值。 审计是在不同的线程中完成的。 集合(ID列表)也存储。 相同的MongoDB数据库用于其他应用程序日志。

有人对这个或类似解决方案有过一些经验吗?

答案 2 :(得分:3)

我通常建议将应用程序服务器用于审计,许多人具有审计功能。例如,我最近做了一个项目,其中审计数据存储在单独的应用程序服务器上的单独数据库中。我们使用Glassfish审计模块功能。将审计的关注与申请分开。