2013-04-29 51 views
7

我無法使用連接表(https://stackoverflow.com/a/7603036 & https://en.wikibooks.org/wiki/Java_Persistence/ManyToMany#Mapping_a_Join_Table_with_Additional_Columns)實現多對多關係。當我嘗試重現它時,持久單元無法構建EntityManagerFactory。 Envers似乎無法讀取映射的屬性,雖然它看起來不錯。我究竟做錯了什麼?用額外的列(和Envers)實現多對多關係的正確方法是什麼?休眠/ Envers無法讀取映射的屬性

Product.java

@Entity 
@Audited 
public class Product extends UserModel { 
... 
    @OneToMany(mappedBy = "product", orphanRemoval = true, cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    public List<ProductForm> forms = new ArrayList<ProductForm>(); 
... 
} 

Form.java

@Entity 
@Audited 
public class Form extends UserModel { 
... 
    @OneToMany(mappedBy = "form", fetch = FetchType.LAZY) 
    public List<ProductForm> products = new ArrayList<ProductForm>(); 
... 
} 

ProductForm.java

@Entity 
@Table(name = "Product_Form") 
@IdClass(ProductForm.ProductFormId.class) 
public class ProductForm { 
    @Id 
    @JoinColumn(name = "product_id") 
    @ManyToOne 
    public Product product; 

    @Id 
    @JoinColumn(name = "form_id") 
    @ManyToOne 
    public Form form; 

    public ProductForm(Product product, Form form) { 
     this.product = product; 
     this.form = form; 
    } 

    @Embeddable 
    @SuppressWarnings("serial") 
    public class ProductFormId implements Serializable { 
     @Column(name = "product_id") 
     public Long product; 

     @Column(name = "form_id") 
     public Long form; 
    } 
} 

堆棧跟蹤

play.api.UnexpectedException: Unexpected exception[PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build EntityManagerFactory] 
    at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$1.apply(ApplicationProvider.scala:142) ~[play_2.10-2.1.1.jar:2.1.1] 
    at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$1.apply(ApplicationProvider.scala:106) ~[play_2.10-2.1.1.jar:2.1.1] 
    at scala.Option.map(Option.scala:145) ~[scala-library.jar:na] 
    at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:106) ~[play_2.10-2.1.1.jar:2.1.1] 
    at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:104) ~[play_2.10-2.1.1.jar:2.1.1] 
    at scala.util.Either$RightProjection.flatMap(Either.scala:523) [scala-library.jar:na] 
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build EntityManagerFactory 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:930) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:72) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final] 
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63) ~[hibernate-jpa-2.0-api-1.0.1.Final.jar:1.0.1.Final] 
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47) ~[hibernate-jpa-2.0-api-1.0.1.Final.jar:1.0.1.Final] 
    at play.db.jpa.JPAPlugin.onStart(JPAPlugin.java:35) ~[play-java-jpa_2.10-2.1.1.jar:2.1.1] 
Caused by: org.hibernate.MappingException: Unable to read the mapped by attribute for products in models.ProductForm! 
    at org.hibernate.envers.configuration.metadata.CollectionMetadataGenerator.getMappedBy(CollectionMetadataGenerator.java:642) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.metadata.CollectionMetadataGenerator.addOneToManyAttached(CollectionMetadataGenerator.java:187) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.metadata.CollectionMetadataGenerator.addCollection(CollectionMetadataGenerator.java:169) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.addValueInSecondPass(AuditMetadataGenerator.java:223) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.addValue(AuditMetadataGenerator.java:245) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.addProperties(AuditMetadataGenerator.java:258) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 

PS我嘗試添加@AuditMappedBy(mappedBy = "product")產品:

play.api.UnexpectedException: Unexpected exception[PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build EntityManagerFactory] 
    at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$1.apply(ApplicationProvider.scala:142) ~[play_2.10-2.1.1.jar:2.1.1] 
    at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$1.apply(ApplicationProvider.scala:106) ~[play_2.10-2.1.1.jar:2.1.1] 
    at scala.Option.map(Option.scala:145) ~[scala-library.jar:na] 
    at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:106) ~[play_2.10-2.1.1.jar:2.1.1] 
    at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:104) ~[play_2.10-2.1.1.jar:2.1.1] 
    at scala.util.Either$RightProjection.flatMap(Either.scala:523) [scala-library.jar:na] 
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build EntityManagerFactory 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:930) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:72) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final] 
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63) ~[hibernate-jpa-2.0-api-1.0.1.Final.jar:1.0.1.Final] 
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47) ~[hibernate-jpa-2.0-api-1.0.1.Final.jar:1.0.1.Final] 
    at play.db.jpa.JPAPlugin.onStart(JPAPlugin.java:35) ~[play-java-jpa_2.10-2.1.1.jar:2.1.1] 
Caused by: org.hibernate.MappingException: @AuditMappedBy points to a property that doesn't exist: models.ProductForm.product 
    at org.hibernate.envers.configuration.ClassesAuditingData.forcePropertyInsertable(ClassesAuditingData.java:84) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.ClassesAuditingData.updateCalculatedFields(ClassesAuditingData.java:70) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.EntitiesConfigurator.configure(EntitiesConfigurator.java:85) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.AuditConfiguration.<init>(AuditConfiguration.java:114) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.AuditConfiguration.getFor(AuditConfiguration.java:164) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.event.EnversIntegrator.integrate(EnversIntegrator.java:64) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 

編輯

當我添加@AuditedProductForm是STI會得到相同的錯誤,下面是最新的堆棧跟蹤。

play.api.UnexpectedException: Unexpected exception[PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build EntityManagerFactory] 
    at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$1.apply(ApplicationProvider.scala:142) ~[play_2.10-2.1.1.jar:2.1.1] 
    at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$1.apply(ApplicationProvider.scala:106) ~[play_2.10-2.1.1.jar:2.1.1] 
    at scala.Option.map(Option.scala:145) ~[scala-library.jar:na] 
    at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:106) ~[play_2.10-2.1.1.jar:2.1.1] 
    at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:104) ~[play_2.10-2.1.1.jar:2.1.1] 
    at scala.util.Either$RightProjection.flatMap(Either.scala:523) [scala-library.jar:na] 
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build EntityManagerFactory 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:930) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:72) ~[hibernate-entitymanager-4.2.0.Final.jar:4.2.0.Final] 
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63) ~[hibernate-jpa-2.0-api-1.0.1.Final.jar:1.0.1.Final] 
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47) ~[hibernate-jpa-2.0-api-1.0.1.Final.jar:1.0.1.Final] 
    at play.db.jpa.JPAPlugin.onStart(JPAPlugin.java:35) ~[play-java-jpa_2.10-2.1.1.jar:2.1.1] 
Caused by: org.hibernate.MappingException: Unable to read the mapped by attribute for products in models.ProductForm! 
    at org.hibernate.envers.configuration.metadata.CollectionMetadataGenerator.getMappedBy(CollectionMetadataGenerator.java:642) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.metadata.CollectionMetadataGenerator.addOneToManyAttached(CollectionMetadataGenerator.java:187) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.metadata.CollectionMetadataGenerator.addCollection(CollectionMetadataGenerator.java:169) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.addValueInSecondPass(AuditMetadataGenerator.java:223) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.addValue(AuditMetadataGenerator.java:245) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
    at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.addProperties(AuditMetadataGenerator.java:258) ~[hibernate-envers-4.2.0.Final.jar:4.2.0.Final] 
+2

你有沒有解決這個問題? – 2014-07-31 14:19:30

回答

0

就Hibernate而言,您有三個具有一對多關聯的實體。

因此,使審計「加入」實體應該做的訣竅:添加@AuditedProductForm

+0

我早些時候嘗試過,'@ Audited'沒有幫助。我仍然無法讀取models.ProductForm!中的產品的映射屬性錯誤。我用堆棧跟蹤更新了我的問題... – sami 2013-04-30 16:55:26

0

你要去的是我所見過的稱爲「關聯實體」的東西。我有幾個,一般來說我建議不要使用複合ID,因爲他們周圍往往會有很多邊緣情況。

取而代之的是給關聯實體自己的id,在這對外鍵上放置一個唯一的索引,然後爲兩個關聯的實體添加關聯(並且省略它們的id)。下面是一個精簡的例子:

@Entity 
class A { 
    @Id 
    private Integer aId; 

    @OneToMany(mappedBy="a") 
    private AtoB aToB; 
} 

@Entity 
class B { 
    @Id 
    private Integer bId; 

    @ManyToOne 
    @JoinColumn(name="b") 
    private AtoB aToB; 
} 

@Entity 
class AtoB { 

    @Id 
    private Integer aToBId; 

    @ManyToOne 
    @JoinColumn(name="aId") 
    private A a; 

    @OneToMany(mappedBy="aToB") 
    private B b; 
} 

這是否有意義?