【问题标题】:Hibernate: MyInterceptor#onFlushDirty is never called休眠:从未调用 MyInterceptor#onFlushDirty
【发布时间】:2015-02-20 12:43:50
【问题描述】:

问题: 为什么从不调用MyInterceptor#onFlushDirty

我在 xml 配置中扩展 AbstractEntityManagerFactoryBean,例如

<bean id="myEntityManagerFactory" parent="abstractEntityManagerFactoryBean" abstract="true">
  <property name="entityInterceptor">
    <bean class="xxxx.MyInterceptor"/>
  </property>
</bean>
<bean id="abstractEntityManagerFactoryBean" class="xxxx.MyEntityManagerFactoryBean"/>

MyEntityManagerFactoryBean

public class MyEntityManagerFactoryBean extends AbstractEntityManagerFactoryBean implements LoadTimeWeaverAware {
  private Interceptor entityInterceptor;

  public Interceptor getEntityInterceptor() {
    return entityInterceptor;
  }

  public void setEntityInterceptor(Interceptor interceptor) {
    entityInterceptor = interceptor;
  }
}

我的拦截器:

public class MyInterceptor extends EmptyInterceptor {

    public MyInterceptor() {
        System.out.println("init"); // Works well 
    }
    // PROBLEM - is never called
    @Override
    public boolean onFlushDirty(Object entity,
                                Serializable id,
                                Object[] currentState,
                                Object[] previousState,
                                String[] propertyNames,
                                Type[] types) {

        if (entity instanceof File) {
            .....
        }
        return false;
    }
}

更新:[解释为什么自定义脏策略看起来不像我的方式]

每次我更改 Folder 实体中的某些内容时,我都想更新 modified 时间戳,但 folderPosition 除外。同时folderPosition 应该是持久的而不是瞬态的(意味着导致实体变脏)。

由于我使用 Spring Transactional 和 Hibernate 模板,因此存在一些细微差别:

1) 我无法在每个 setter 结束时更新修改后的时间戳,例如:

public void setXXX(XXX xxx) {
  //PROBLEM: Hibernate templates collect object via setters, 
  //means simple get query will cause multiple 'modified' timestamp updates
  this.xxx = xxx;
  this.modified = new Date();
}

2) 我不能手动调用 setModified,因为它有大约 25 个字段,并且每个字段的 setXXX 分散在整个应用程序中。而且我无权进行重构。

@Entity
public class Folder {

  /**
   * GOAL: Changing of each of these fields except 'folderPosition' should cause 
   * 'modified' timestamp update
   */
  private long id;
  private String name;
  private Date created;
  private Date modified;
  private Integer folderLocation;

  @PreUpdate
  public void preUpdate() {
     //PROBLEM : change modified even if only location field has been changed!
     //PROBLEM: need to know which fields have been updated!
     modified = new Date(); 
  }   
  ....
}

【问题讨论】:

  • 你能用这个 spring 配置显示你想填充的自定义 EntityManager 类吗
  • @Vihar 我有点进步。但是我的拦截器仍然无法按预期工作。你可以看看我更新的问题吗?
  • @Vihar 你的意思是我现在需要删除构造函数吗?
  • @Vihar 之前的错误是由于getInterceptor/setInterceptorMyEntityManagerFactoryBean 缺席引起的
  • 离题,但始终建议在复杂方法上添加@Override。只是为了确保您不会因为拼写错误而意外声明新方法。

标签: java spring hibernate jpa orm


【解决方案1】:

您需要扩展findDirty 方法而不是onFlushDirty。请查看this tutorial 以获取详细说明,并参考 GitHub 工作示例。

【讨论】:

  • 感谢您如此全面的披露!我从中学到了很多。你可以看看我的问题的更新部分吗?
  • 只需覆盖 findDirty,调用 super() 并从结果中删除 folderLocation。
  • 完成。有关详细信息,请查看我的书,High-Performance Java Persistence
猜你喜欢
  • 2014-09-29
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 2010-11-24
  • 2018-07-12
  • 1970-01-01
  • 2017-04-11
  • 2023-03-24
相关资源
最近更新 更多