从Hibernate捕获生成的SQL

时间:2018-08-16 15:54:20

标签: java spring hibernate

我需要捕获对某些数据的更改。我正在寻找以下细节:

  1. 发生更改的表名
  2. 列已更改
  3. 以前的值
  4. 更新后的值

我向我们的技术负责人建议,使用DB触发器可以轻松实现这一目标。有人告诉我,我们不控制数据库,也没有添加触发器的方法。

我目前正在使用带有自定义注释的Spring AspectJ,并包装我的服务以尝试捕获在调用“保存”方法后执行的生成的SQL(我认为解析SQL比尝试用Objects捕获要容易得多),但是我还没有找到捕获生成的SQL的方法。

我尝试了p6Spy并能够查看SQL并将其打印到控制台,但被告知我们无法将数据库驱动程序包装在PROD环境中。

是否缺少我想要的Spring课程?

编辑:我们正在使用Spring存储库来保存数据。

编辑2:我正在研究EventListener,但是似乎无法让他们听我的活动。

@Component
public class EventListner implements PreInserEventListener, PreUpdateEventListener {
   @Override
   @EventListener
   public boolean onPreUpdate(PreUpdateEvent event){
     // do something

     return false;
   }

   @Override
   @EventListener
   public boolean onPreInsert(PreUpdateEvent event){
     // do something
   }
   return false
}

我在Listener周围有断点,但从未到达断点。


  

This question似乎可以解决我的问题

2 个答案:

答案 0 :(得分:0)

如果您完全确定每个插入/更新/删除操作都是通过JPA完成的,并且没有任何批量SQL,那么您应该看看envers

因此,您可以在要保留历史的实体(所有列)或实体列上使用@Audited

这将创建1个带时间戳更改的修订表(以及其他您想要的数据,例如进行更改的用户的uid),以及每个实体1个表,其中包含修改后的数据的旧值。

对于每个数据,您都可以检索历史记录和以前的值。

另一种方法是像更改数据捕获(CDC)工具一样在数据库上添加工具,并将这些事件推送到另一个数据存储库。 在+方面,将检测到所有内容(甚至本机SQL也直接在DB上运行)。缺点是,您的数据库需要正确支持这种工具。例如,kafka-connect之类的工具可以按您希望的方式工作,但是某些实现太简单了(例如,对于要进行select * from xxx的过程的SAP hana而言)。

答案 1 :(得分:0)

我最终决定使用Hibernate拦截器来解决问题。完美地工作!

public class TableInterceptor extends EmptyInterceptor {

   @Override
   public boolean onFlushDirty(Object entity, Serializable id,
                               Object[] currentState, Object[] previousState,
                               String[] propertyNames, Type[] types){

         // do comparison logic on fields and save to DB
   }
}

我引导了拦截器,将其注入我的LocalContainerEntityManagerFactoryBean