【问题标题】:Hibernate/Envers unable to read the mapped by attributeHibernate/Envers 无法读取映射的属性
【发布时间】:2013-04-23 14:42:24
【问题描述】:

我无法使用连接表 (https://stackoverflow.com/a/7603036 & https://en.wikibooks.org/wiki/Java_Persistence/ManyToMany#Mapping_a_Join_Table_with_Additional_Columns) 实现多对多关系。当我尝试重现它时,持久性单元无法构建 EntityManagerFactory。尽管对我来说看起来不错,但 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]

编辑

当我将@Audited 添加到ProductForm 时仍然出现同样的错误,下面是最新的堆栈跟踪。

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]

【问题讨论】:

标签: hibernate jpa jpa-2.0 hibernate-envers


【解决方案1】:

如果您的问题是由复合键引起的,请尽可能将您的休眠版本更新到 5.2.2。因为这个错误在这个版本中被修复了。

见:https://hibernate.atlassian.net/browse/HHH-7625

【讨论】:

    【解决方案2】:

    您所追求的是我所看到的称为“关联实体”的东西。我有一些,一般来说我建议不要使用复合 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;
    }
    

    这有意义吗?

    【讨论】:

    • 这通过查看 mappedBy 帮助我解决了我的问题。映射的工作直到我升级到休眠 5。
    【解决方案3】:

    就 Hibernate 而言,您拥有三个具有一对多关联的实体。

    因此,审核“加入”实体应该可以解决问题:将 @Audited 添加到 ProductForm

    【讨论】:

    • 我之前尝试过,@Audited 没有帮助。我仍然收到Unable to read the mapped by attribute for products in models.ProductForm! 错误。我用堆栈跟踪更新了我的问题...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-21
    • 2021-08-12
    • 2018-01-07
    • 1970-01-01
    • 2015-09-12
    • 2019-11-09
    • 2021-08-31
    相关资源
    最近更新 更多