【问题标题】:How to get JIRA like change history using hibernate envers audit log?如何使用hibernate envers审计日志获得JIRA之类的更改历史记录?
【发布时间】:2019-08-20 10:17:08
【问题描述】:

我试图在 UI 上显示 JIRA 之类的更改历史记录。我正在使用Spring Data JPA,并且我已经使用 Envers (v5.3.7) 配置了审计跟踪。我可以使用 AuditQuery 获取特定实体的所有修订列表,通过其主键值。

是否有一种简单的方法可以计算修订版之间的“增量”并识别已更改的属性? (有新旧价值)

我在我的实体类中添加了@Audited(withModifiedFlag = true) 注释。它在<entity>_aud 表中为每个属性添加了一列,指示该属性是否已更改。我正在尝试弄清楚如何使用这些额外的列。

【问题讨论】:

  • Envers 6.0 附带了一个新的 API,它允许您使用 withModifiedFlag=true 属性设置并能够获取实体的修订列表,它会告诉您更改了哪些字段该修订版,因此您不需要使用拦截器或自定义表;只是恩弗斯。

标签: jira hibernate-envers


【解决方案1】:

如果您需要 JIRA 之类的东西,您必须自己构建它。

我建议你使用 Hibernate 拦截器:

http://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#events

正如您在以下示例中所见,您可以获取当前和之前的状态,然后可以创建增量并将其存储在您自己的变更日志表中:

public static class LoggingInterceptor extends EmptyInterceptor {
    @Override
    public boolean onFlushDirty(
        Object entity,
        Serializable id,
        Object[] currentState,
        Object[] previousState,
        String[] propertyNames,
        Type[] types) {
            LOGGER.debugv( "Entity {0}#{1} changed from {2} to {3}",
                entity.getClass().getSimpleName(),
                id,
                Arrays.toString( previousState ),
                Arrays.toString( currentState )
            );
            return super.onFlushDirty( entity, id, currentState,
                previousState, propertyNames, types
        );
    }
}

【讨论】:

  • 感谢西蒙为我指明了正确的方向。我没有使用 EmptyInterceptor,而是使用了 org.hibernate.event.spi.PreUpdateEventListener。它对我有用。我在这个线程上发布我的代码。
【解决方案2】:

这是我的代码

import javax.annotation.PostConstruct;
import javax.persistence.EntityManagerFactory;

import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PreUpdateEvent;
import org.hibernate.event.spi.PreUpdateEventListener;
import org.hibernate.internal.SessionFactoryImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class AuditListener implements PreUpdateEventListener {   
    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @PostConstruct
    private void init() {
        SessionFactoryImpl sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);
        EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);

        // You can also add listener for a specific entity-type instead of event-group
        // In my case I needed global event listener
        registry.getEventListenerGroup(EventType.PRE_UPDATE).appendListener(this);
    }

    @Override
    public boolean onPreUpdate(PreUpdateEvent event) {
        String[] propertyNames = event.getPersister().getPropertyNames();
        Object[] oldValues = event.getOldState();
        Object[] newValues = event.getState();
        for (int index = 0; index < propertyNames.length; index++) {
            String propertyName = propertyNames[index];
            Object oldValue = oldValues[index];
            Object newValue = newValues[index];

            // This is just sample code
            boolean changed = oldValue != newValue;
            if (changed) {
                System.out.println("Audit log -> Property: " + propertyName + ", Old value: " + oldValue + ", New value: " + newValue);

                // Actual code that persists audit log
                ...
                ...
            }
        }
        return false;
    }
}

【讨论】:

  • 如何为特定实体类型添加监听器?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-04
  • 2023-03-24
  • 1970-01-01
相关资源
最近更新 更多