【问题标题】:Hibernate, save the previous state of an objectHibernate,保存对象之前的状态
【发布时间】:2010-12-27 23:30:08
【问题描述】:

是否有任何普遍接受的、经过验证的使用休眠的方法来保存数据库中实体更改的历史记录?

我们需要跟踪相当多的对象,并且我们希望能够撤消对对象的更改。

我尝试使用hibernate的拦截器,但是对象的旧状态只有在做merge()时才可用。大多数情况下,我们会使用update()saveOrUpdate()...

我目前让 warp-persist 和 Guice 一起管理会话。

【问题讨论】:

    标签: hibernate session history undo


    【解决方案1】:

    我已经使用拦截器完成了此操作(基于EmptyInterceptor 创建我自己的)。我能够在 onFlushDirty() 中获得所有更改(合并、保存、saveOrUpdate 和删除)。

    我使用的EmptyInterceptor的方法:

    @Override
    public boolean onFlushDirty(Object object, Serializable id,
        Object[] newValues, Object[] oldValues, String[] properties,
        Type[] types) throws CallbackException {
    
    @Override
    public boolean onSave(Object object, Serializable id, Object[] newValues,
        String[] properties, Type[] types) throws CallbackException {
    
    @Override
    public void onDelete(Object object, Serializable id, Object[] newValues,
        String[] properties, Type[] types) throws CallbackException {
    

    在 onFlushDirty() 中我必须查询实体的先前状态:

    Connection c = sessionFactory.getCurrentSession().connection();
    Session session = sessionFactory.openSession(c);
    
    BaseEntity newBaseEntity = (BaseEntity) object;
    BaseEntity oldBaseEntity = (BaseEntity) session.get(newBaseEntity.getClass(), newBaseEntity.getId());
    

    【讨论】:

    • oldValues 参数似乎为空,当 onFlushDirty() 在执行 update()saveOrUpdate() 时被调用
    • 我以为它们是为我填充的,但是当我仔细查看代码时,我发现我实际上是从 onFlushDirty() 内部的会话中查询实体的当前状态。所以我就是这样解决这个问题的。
    • 我认为您需要详细说明“查询当前状态部分”。我看到您正在查询旧实体,但它如何用于创建更改的属性。
    【解决方案2】:

    JBoss envers 或许正是您要找的。​​p>

    Envers 项目旨在实现对持久类的轻松审计/版本控制。您所要做的就是使用@Audited 注释您想要审计的持久类或其某些属性。对于每个被审计的实体,将创建一个表,其中将保存对该实体所做的更改的历史记录。然后,您可以轻松检索和查询历史数据。

    与 Subversion 类似,该库具有修订的概念。基本上,一笔交易就是一次修订(除非交易没有修改任何经审计的实体)。由于修订是全局的,具有修订号,您可以查询该修订的各种实体,检索该修订的数据库的(部分)视图。您可以找到具有日期的修订号,反之,您可以获得提交修订的日期。

    【讨论】:

      【解决方案3】:

      来自 JBoss 的 Hibernate Envers 可能是您正在寻找的:

      Envers 项目旨在实现对持久类的轻松审计/版本控制。您所要做的就是使用@Audited 注释您想要审计的持久类或其某些属性。对于每个被审计的实体,将创建一个表,其中将保存对该实体所做的更改的历史记录。然后,您可以轻松检索和查询历史数据。

      【讨论】:

        【解决方案4】:

        有一个 JBoss 开发的自动版本控制和审计项目:envers。 我可以推荐使用它,我之前已经手动实现过审计,当您开始处理更复杂的用例时,它会变得非常混乱。

        【讨论】:

        • 我去看看 envers。我以前偶然发现过它,但现在不记得了。
        【解决方案5】:

        我也遇到了同样的问题。一种解决方法是 lock() 使用前一个状态,然后 merge() 使用新状态,而不是 update() 仅使用新状态。

        然后休眠知道之前/之后,它在拦截器/事件侦听器中可用。

        HTH。

        【讨论】:

        • 所以saveOrUpdate() 确实被merge() 取代了?
        • 我假设,因为您使用的是 update(),所以您有分离的实例。如果是这样,您的对象是否处于对其进行更改之前的状态?如果是这样,您可以使用上述方法。我有类似的情况,我将分离的实例传送到远程 GUI,它会进行更改并将它们发送回。但是,我也让 GUI 发回“未更改”状态。然后对于我所做的每次更新.. session.lock( 不变 ); session.merge(更改);
        猜你喜欢
        • 1970-01-01
        • 2021-03-03
        • 1970-01-01
        • 1970-01-01
        • 2014-10-26
        • 2014-05-16
        • 1970-01-01
        • 2012-05-06
        • 2011-01-19
        相关资源
        最近更新 更多