【问题标题】:Hibernate @ManyToOne of an entity with @IdClass使用@IdClass 休眠一个实体的@ManyToOne
【发布时间】:2020-11-02 02:59:39
【问题描述】:

我刚刚在我的项目中添加了一个新实体,但现在它没有启动。 我认为这与将@ManyToOne 作为复合键的一部分有关,但我不确定。 我将问题归结为以下实体:

A.class:

@Table(name = "A")
@Entity
@IdClass(KeyA.class)
public class A {
    
   @Id
   private String aId;
    
   @Id
   @ManyToOne
   private B b;
    
   public String getaId() {
      return aId;
   }
    
   public void setaId(String aId) {
      this.aId = aId;
   }
    
   public B getB() {
      return b;
   }
    
   public void setB(B b) {
      this.b = b;
   }
}

B.class:

@Table(name = "B")
@Entity
@IdClass(KeyB.class)
public class B {
    
   @Id
   String bId;
    
   @Id
   String bId2;
    
   public String getbId() {
      return bId;
   }
    
   public void setbId(String bId) {
      this.bId = bId;
   }
    
   public String getbId2() {
      return bId2;
   }
    
   public void setbId2(String bId2) {
      this.bId2 = bId2;
   }
}

KeyA.class:

public class KeyA implements Serializable {
    
   private String aId;
   private String b;
}

KeyB.class

public class KeyB implements Serializable{
    
   public String bId;
   public String bId2;
}

抛出异常:

        Error creating bean with name 'entityManagerFactory' defined in class path resource
        [...]
        Caused by: org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.component.PojoComponentTuplizer]
    [...]
    Caused by: java.lang.reflect.InvocationTargetException: null
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_201]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_201]
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_201]
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_201]
        at org.hibernate.tuple.component.ComponentTuplizerFactory.constructTuplizer(ComponentTuplizerFactory.java:104) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
        ... 43 common frames omitted
    Caused by: org.hibernate.PropertyNotFoundException: Could not locate field name [bId] on class [java.lang.String]
        at org.hibernate.internal.util.ReflectHelper.findField(ReflectHelper.java:371) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
        at org.hibernate.property.access.internal.PropertyAccessFieldImpl.<init>(PropertyAccessFieldImpl.java:34) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
        at org.hibernate.property.access.internal.PropertyAccessStrategyFieldImpl.buildPropertyAccess(PropertyAccessStrategyFieldImpl.java:26) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
        at org.hibernate.mapping.Property.getGetter(Property.java:311) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
        at org.hibernate.tuple.component.PojoComponentTuplizer.buildGetter(PojoComponentTuplizer.java:141) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]

我尝试了一切,包括导入最新的 javassist。 我在 Java 1.8 上运行 Spring Boot 2.2.5.RELEASE(它也发生在 11 中)

【问题讨论】:

    标签: java spring-boot hibernate jpa spring-data-jpa


    【解决方案1】:

    你的A复合键

    public class KeyA implements Serializable {
    
        private String aId;
        private String b;
    }
    

    结构好像B 只有一个字符串ID(这里称为b),而实际上它本身有一个复合键

    public class KeyB implements Serializable{
    
        public String bId;
        public String bId2;
    }
    

    因此您必须更改 KeyA 以正确表示该关系:

    public class KeyA implements Serializable {
    
        private String aId;
        private KeyB keyB;
    }
    

    【讨论】:

    • 我认为您的答案是正确的,但 KeyB 应该是 B 实体本身。
    • 不,仅当您的实体没有复合 PK 时才有效
    • 我只是测试了两种方式,它只适用于“private B b;”
    • 有趣,我很确定几年前我也做过同样的事情,它只适用于 PK 级别的 IdClass 引用
    • 我只找到stackoverflow.com/questions/31385658/…,但他们在那里使用 EmbeddedId
    【解决方案2】:

    您应该在 KeyA 中使用与在拥有实体中标记的字段名称/类型完全相同的字段名称/类型,如 @Id

    因此,您应该通过以下方式更正KeyA

    public class KeyA implements Serializable {
    
        private String aId;
        private B b;
    }
    

    documentation中查看更多解释和示例。

    【讨论】:

    • 我明白了,要指示您需要的复合键的复合键。谢谢!
    • @CarlosLópezMarí 我已经更新了答案,看起来 Smutje 的答案可以更正为可行。
    • 奇怪,我再检查一下,可能是休眠的bug。
    • 您是否通过KeyB 的两列加入B
    • 实际上,第二种方法效果更好,因为它修复了第一次检索实体 eith 子项时出现的此错误:stackoverflow.com/questions/35521486/…
    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多