我们有一个具有以下设置的应用程序:
Java 6.0 Spring Data JPA 1.1.0.RELEASE Spring Data MongoDB 1.0.2.RELEASE Spring Data MongoDB跨存储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编织,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注释的现有代码的应用程序的指导?
答案 0 :(得分:0)
我遇到了与@PreUpdate和@PostLoad相同的问题。
在泉源中有一个错误: https://jira.springsource.org/browse/DATAMONGO-519
他们给出了以下解决方案:
我将所有注释移动到实体监听器,它立即工作,无需更改任何其他内容。 看看以下链接,似乎只能在实体级别添加同一时间的一个注释,但可以使用实体侦听器添加许多注释: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){
}
}
答案 1 :(得分:0)
我们在这里遇到了同样的问题:
EntityListener 使用泛型参数实现了一个接口。在调试抛出异常的Hibernate代码之后,结果证明在这个侦听器接口中不能使用Generics作为实体类型。删除通用参数后,它可以工作。
原因:在接口中使用泛型参数时,java编译器为实现类(具体类型)创建(例如)一个 postUpdate(...)方法,并为接口创建一个 postUpdate(...)方法(超级型)。 Hibernate检测到那些2,但只需要一个。结果它抛出异常。