0

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

Java 6.0 Spring Data JPA 1.1.0.RELEASE Spring Data MongoDB 1.0.2.RELEASE Spring Data MongoDB Cross-Store 1.0.2.RELEASE Hibernate 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 注释的现有代码的应用程序一起使用的任何指导?

4

2 回答 2

0

@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){
    }
}
于 2012-12-22T12:31:18.043 回答
0

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

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

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

于 2018-04-06T09:45:58.787 回答