【问题标题】:How to Audit Spring data jpa @Query?如何审计 Spring 数据 jpa @Query?
【发布时间】:2019-01-27 12:35:22
【问题描述】:

为了审核记录所有数据库更改,我们实现了 Hibernate Interceptor(org.hibernate.Interceptor)。 我们可以记录使用 JpaRepository 执行的查询的审计

我们使用过的拦截器——Sample

import java.io.Serializable;
import java.util.Iterator;

import org.hibernate.CallbackException;
import org.hibernate.EntityMode;
import org.hibernate.Interceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;

public class TestInterceptor implements Interceptor {

@Override
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
        throws CallbackException {
    // TODO Auto-generated method stub
    return false;
}

@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
        String[] propertyNames, Type[] types) throws CallbackException {
    // TODO Auto-generated method stub
    return false;
}

@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
        throws CallbackException {
    // TODO Auto-generated method stub
    return false;
}

@Override
public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
        throws CallbackException {
    // TODO Auto-generated method stub

}

@Override
public void onCollectionRecreate(Object collection, Serializable key) throws CallbackException {
    // TODO Auto-generated method stub

}

@Override
public void onCollectionRemove(Object collection, Serializable key) throws CallbackException {
    // TODO Auto-generated method stub

}

@Override
public void onCollectionUpdate(Object collection, Serializable key) throws CallbackException {
    // TODO Auto-generated method stub

}

@Override
public void preFlush(Iterator entities) throws CallbackException {
    // TODO Auto-generated method stub

}

@Override
public void postFlush(Iterator entities) throws CallbackException {
    // TODO Auto-generated method stub

}

@Override
public Boolean isTransient(Object entity) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public int[] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
        String[] propertyNames, Type[] types) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public Object instantiate(String entityName, EntityMode entityMode, Serializable id) throws CallbackException {
    // TODO Auto-generated method stub
    return null;
}

@Override
public String getEntityName(Object object) throws CallbackException {
    // TODO Auto-generated method stub
    return null;
}

@Override
public Object getEntity(String entityName, Serializable id) throws CallbackException {
    // TODO Auto-generated method stub
    return null;
}

@Override
public void afterTransactionBegin(Transaction tx) {
    // TODO Auto-generated method stub

}

@Override
public void beforeTransactionCompletion(Transaction tx) {
    // TODO Auto-generated method stub

}

@Override
public void afterTransactionCompletion(Transaction tx) {
    // TODO Auto-generated method stub

}

@Override
public String onPrepareStatement(String sql) {
    // TODO Auto-generated method stub
    return null;
}

}

但如果我们通过org.springframework.data.jpa.repository.Query 运行查询,则不会调用拦截器。

这是否可以审计/拦截使用 org.springframework.data.jpa.repository.Query 执行的查询

即我的存储库中有以下查询,这不会触发 Hibernate 拦截器

  @Transactional
  @Modifying
  @Query("DELETE from MyEntity my where my.id =?1")
  void deleteById(Long id);

【问题讨论】:

  • Hibernate 拦截器仅适用于实体而不是查询。这与 Spring Data JPA 无关,而是与拦截器的工作方式有关。如果您直接使用EntityManager,也会发生同样的情况。
  • 你能展示你的拦截器吗?我对 JPA EntityListeners 做同样的事情,并且这个查询也调用了 Listener。
  • @Simon Martinelli 我已更新
  • @Simon Martinelli 我也尝试过 JPA EntityListeners,但使用 spring @Query 的直接查询仍然不称为侦听器
  • 为了您的方便,我创建了一个小型演示项目:github.com/simasch/bulk-delete 请检查您是否发现任何差异。

标签: spring hibernate spring-boot spring-data-jpa spring-data


【解决方案1】:

要拦截 Spring 数据查询,请添加此道具:

spring.jpa.properties.hibernate.session_factory.interceptor=com.yourpacakge.TestInterceptor

为了简单起见,我使用了从 EmptyInterceptor 扩展而来的拦截器类。

public class MyInterceptor extends EmptyInterceptor {
    @Override
    public String onPrepareStatement(String sql) {
        System.out.println("Query intercepted: " + sql);
        return super.onPrepareStatement(sql);
    }
}

文档:https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#configurations-session-events

【讨论】:

    猜你喜欢
    • 2020-02-24
    • 1970-01-01
    • 2016-08-22
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 2017-03-07
    相关资源
    最近更新 更多