【问题标题】:Spring Data MongoDB Cross-Store plugin and JPA PrePersist and PreUpdateSpring Data MongoDB Cross-Store 插件和 JPA PrePersist 和 PreUpdate
【发布时间】:2012-08-28 07:59:02
【问题描述】:

我们有一个具有以下设置的应用程序:

Java 6.0 Spring Data JPA 1.1.0.RELEASE Spring Data MongoDB 1.0.2.RELEASE Spring Data MongoDB 跨存储 1.0.2.RELEASE 休眠 JPA 2.0

我们在这个应用程序中有几个使用 JPA PrePersist、PreUpdate、PostPersist 和 PostUpdate 注释的类。下面给出一个例子。

@Entity
public class Person
{
    private String password;

    @PrePersist
    @PreUpdate
    public void beforeSave()
    {
        if(!Security.isEncrypted(this.password))
        {
            this.password = Security.encrypt(this.password);
        }
    }
}

当我们为跨存储插件打开 AspectJ weaving 时,Spring 应用程序上下文无法加载并出现错误:

Caused by: javax.persistence.PersistenceException: You can only annotate one callback method with javax.persistence.PrePersist in bean class: org.example.domain.Person
    at org.hibernate.ejb.event.CallbackResolver.resolveCallback(CallbackResolver.java:110)
    at org.hibernate.ejb.event.EntityCallbackHandler.addCallback(EntityCallbackHandler.java:123)
    at org.hibernate.ejb.event.EntityCallbackHandler.add(EntityCallbackHandler.java:61)
    at org.hibernate.ejb.event.JpaIntegrator.integrate(JpaIntegrator.java:151)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:306)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1744)
    at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:890)
    at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:268)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)

我发现错误的根本原因是 Aspect MongoDocumentBacking 将额外的 PrePersist 和 PreUpdate 方法编织到实体类中。由于这些类已经有带有这些注释的方法,Hibernate Entity Manager 无法验证这些类。

对于跨商店插件应如何与具有使用 JPA 注释的现有代码的应用程序一起使用是否有任何指导?

【问题讨论】:

    标签: java spring-data spring-data-jpa spring-data-mongodb


    【解决方案1】:

    @PreUpdate 和@PostLoad 我遇到了同样的问题。

    在 springsource 中打开了一个关于此的错误: https://jira.springsource.org/browse/DATAMONGO-519

    他们给出了以下解决方案:

    1. 创建 JPA 实体事件侦听器类并将 PrePersist、PreUpdate 等代码移动到这些侦听器中。
    2. 将方面更改为首先搜索实体类是否有任何注释为 RelatedDocument 的字段。
    3. 如果一个实体类有一个或多个被注解为RelatedDocument的字段,检查该类是否已经有EventListeners注解。
    4. 如果 EventListeners 注释已存在,请将跨商店事件侦听器添加到列表中。如果没有,请在类中添加 EventListeners 注释。

    我将所有注释移至实体侦听器,它立即工作,无需更改任何其他内容。 看看下面的链接,好像实体级别只能添加一个同一时间的注解,但是使用实体监听器可以添加很多:http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/listeners.html

    @Entity
    @EntityListeners(ProductEntityListener.class)
    public class Product {
    }
    
    public class ProductEntityListener {
        @PrePersist
        @PreUpdate
        protected void prePersist(Product entity) {
        }
        @PostLoad
        protected void postLoad(Product entity){
        }
    }
    

    【讨论】:

    • 实际上,我 (OP) 是报告 JIRA 并建议将审计内容移至 EntityListener 类的人。 :) 我现在发现整个 Spring Data 项目使用的方法是使用方面将 JPA 生命周期方法注入到实体类中。我们现在面临多个 Spring Data 组件的这个问题。我们有一个庞大的应用程序,在很多情况下我们根本无法将代码移动到实体侦听器中。所以,暂时我们被困住了。
    【解决方案2】:

    我们在这里遇到了同样的问题:

    一个 EntityListener 实现了一个带有通用参数的接口。在调试了引发异常的 Hibernate 代码后,发现无法在此侦听器接口中为实体类型使用泛型。删除泛型参数后它起作用了。

    原因:当在接口中使用泛型参数时,java 编译器(例如)为实现类(具体类型)创建一个 postUpdate(...)-方法和一个用于接口的方法(超级类型)。 Hibernate 检测到这 2 个,但只需要一个。因此,它会引发异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 2023-03-06
      相关资源
      最近更新 更多