如何在没有 Hibernate Envers 的情况下审核 JPA
我需要为我的 Java Web 应用程序制作一个审核模块。我使用 EclipseLink,而不是 Hibernate(不能使用 Envers)。我搜索了很多方法来获取 JPA 正在执行的 SQL 或 JPQL,因此我可以记录如下内容:
System.out.println("User " + user + " from " + ip_address + " executed " + jpa_statement + " at " + new Date());
实际上,我会将这些信息保存到历史数据库的表中。这样我就可以随时轻松检索此信息。这就是为什么“SHOW SQL”参数对我来说还不够。我确实需要 SQL 字符串,因此我可以在源代码中操作它。
我在 JPA 规范中发现了 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语句呢?
如果有人能指出我正确的方向,我将不胜感激!
I need to make an audit module to my Java Web App. I use EclipseLink, not Hibernate (can't use Envers). I searched a lot some way to get the SQL or JPQL that JPA is executing, so I could log something like this:
System.out.println("User " + user + " from " + ip_address + " executed " + jpa_statement + " at " + new Date());
Actually, I'll save this info into a history database's table. So I can easily retrieve this info any time I want. That's why "SHOW SQL" parameters are not enough to me. I really need the SQL string, so I can manipulate it at my source code.
I found at JPA spec the EntityListener feature and thought it was the perfect place to put my logging code. For example, the postUpdate method could log the time the object was updated. But my problem is that I can't have the SQL the was executed.
Here is an example of what I mean:
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());
}
}
But "object.getSQL()" doesn't exists. So how can I get the SQL statement?
If anyone could point me into the right direction, I would appreciate!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
EclipseLink 完全支持历史跟踪。
看,
http://wiki.eclipse.org/EclipseLink/Examples/JPA/History
JPA 事件不包含改变的只是对象。
EclipseLink 还支持 DesriptorEvents(请参阅 DescriptorEventListener),它也定义了 postUpdate,但包含一个描述更改的 ObjectChangeSet,您还拥有包含 SQL 和 DatabaseRecord 的 UpdateObjectQuery。
EclipseLink has full support for history tracking.
See,
http://wiki.eclipse.org/EclipseLink/Examples/JPA/History
JPA events do not contain what was changed, only the object.
EclipseLink also supports DesriptorEvents (see DescriptorEventListener) which also define a postUpdate but include an ObjectChangeSet that describe the changes, you also have the UpdateObjectQuery that contains the SQL and DatabaseRecord.
Envers 的审计很棒,但我认为,可以有更好的审计解决方案。在恩弗斯有几个
缺点:
每个表两个数据库表。但第二个表很少使用。对于我们有 600 多个表的大型企业项目来说,这是一个问题。
Envers 是仅针对数据库更改的解决方案。当我需要解决其他应用程序组件的审计时,我需要不同的审计解决方案。
对馆藏的审计并不理想。
当更改数据库模式时,我也必须更改审计表。我可能会丢失一些审计信息,或者我需要做很多工作才能将旧的审计信息更新到新模式。
将审核信息保存到同一个数据库非常耗时和空间。
我开始研究小型审计库,其中信息存储在 MongoDB 数据库中:
对所有 hibernate 对象使用一个集合。存储对象的每个值。
审计是在不同的线程中完成的。
集合(id 列表)也被存储。
相同的 MongoDB 数据库用于其他应用程序日志。
有人对此或类似解决方案有经验吗?
Envers for auditing is great, but I think, there can be a better solution for auditing. In Envers is a few
shortcomings:
Two db tables for every table. But second table is used rarely. For our large enterprise project where is 600+ tables it is problem.
Envers is solution only for db changes. When I need solve auditing for other application components, I need different auditing solution.
Auditing of collections is not ideal.
When is changed database schema I must change audit tables too. I can lost some auditing informations or I have a lot of work with update old auditing informations to the new schema.
Save auditing informations to the same database is time and space consuming.
I am start working on small auditing library where, informations are stored in MongoDB database:
Is used one collection for all hibernate objects. Is stored every value of object.
Auditing is done in different thread.
Collections (list of ids) are stored too.
The same MongoDB database is used for other application logs.
Has somebody some experience with this or similar solution ?
我通常建议对应用服务器进行审计,很多都有审计能力。例如,我最近做了一个项目,其中审计数据存储在单独的应用程序服务器上的单独数据库中。我们使用 Glassfish 审核模块功能。将审计的关注点与应用程序完全分开。
I usually recommend making the application server to the auditing, many have auditing capability. For example I recently did a project where audit data was stored in a separate database on a separate application server. We use the Glassfish audit module feature. Separated the concern of auditing from the application all together.