【问题标题】:Composite Key in JPA / Hibernate with inherited classJPA / Hibernate中的复合键与继承类
【发布时间】:2011-05-12 02:15:28
【问题描述】:

我在我的类结构上定义了一个复合 ID,如下所示。不幸的是,我总是收到一个休眠错误,抱怨找不到“part2”:

“在实体 MoreClass 中找不到 @IdClass 的属性:part2”

谁能帮我解决这个问题? (或者至少给我指出一个有用的 jpa/hibernate 文档?)

@IdClass(ClassKey.class)
@Entity
public class MoreClass extends LessClass implements Serializable
{
  @Id
  String part1;
}

@MappedSuperclass
public class LessClass implements Serializable
{
   @Id
   String part2;
}

public class ClassKey implements Serializable
{
   String part1;
   String part2;
}

【问题讨论】:

  • 当我得到一些观点,但没有答案时,我应该假设,这个星座是不可能的。我只是在文档中找不到提示......

标签: hibernate jpa composite-primary-key composite-id


【解决方案1】:

居然撞到了same problem

作为:

@Override
@Id
public getPart2() {
   return super.getPart2();
}

似乎有效,我认为这是一个错误。见https://hibernate.atlassian.net/browse/HHH-9114

【讨论】:

    【解决方案2】:

    提到的Michael works 为HHH-9114 bug 提供的解决方法,例如在我的情况下,通过添加到 TwitterListedCount :(请注意,必须添加 @Id @Type 才能使用户类型仍然有效)

    // TODO: https://hibernate.atlassian.net/browse/HHH-9114
    @Override @Id
    public long getTwitterUserId() {
        return super.getTwitterUserId();
    }
    
    @Override @Id
    public DateTime getFetchTime() {
        return super.getFetchTime();
    }
    

    顺便说一句,解决方法有一个nasty side-effect HHH-9350,当与模式生成一起使用时,它会生成重复的复合列:

    CREATE TABLE buzz.twitterlistedcount
    (
      id_fetchtime timestamp without time zone NOT NULL,
      id_twitteruserid bigint NOT NULL,
      _identifiermapper_fetchtime timestamp without time zone NOT NULL,
      _identifiermapper_twitteruserid bigint NOT NULL,
      listedcount integer NOT NULL,
      CONSTRAINT twitterlistedcount_pkey PRIMARY KEY (id_fetchtime, id_twitteruserid)
    )
    WITH (
      OIDS=FALSE
    );
    

    我尝试完全不使用@MappedSuperclass,但仍然会发生错误的模式生成。顺便说一句,我正在使用DefaultComponentSafeNamingStrategy,这可能是错误所在。这可能是一个不同的错误,在Hibernate find with composite key. Invalid column name Exception 中询问

    正确的解决方法是手动添加@Column(name=),这与模式生成很相配:

    @Id
    @Basic()
    @Column(name="twitteruserid")
    private long twitterUserId = 0;
    
    @Id
    @Basic()
    @Column(name="fetchtime")
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime fetchTime = null;
    

    仅供参考,Spring Data JPA 一起使用时,需要MappedSuperclass 中删除@Id@Type 注释。如果不删除这些,则会出现以下错误。它不会改变这个 Hibernate 错误的性质,顺便说一句。

    org.springframework.data.mapping.model.MappingException: Ambiguous mapping! Annotation Id configured on field twitterUserId and one of its accessor methods in class TwitterFollowerCount!
        at org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.populateAnnotationCache(AnnotationBasedPersistentProperty.java:111)
        at org.springframework.data.mapping.model.AnnotationBasedPersistentProperty.<init>(AnnotationBasedPersistentProperty.java:66)
        at org.springframework.data.jpa.mapping.JpaPersistentPropertyImpl.<init>(JpaPersistentPropertyImpl.java:86)
        at org.springframework.data.jpa.mapping.JpaMetamodelMappingContext.createPersistentProperty(JpaMetamodelMappingContext.java:67)
        at org.springframework.data.jpa.mapping.JpaMetamodelMappingContext.createPersistentProperty(JpaMetamodelMappingContext.java:35)
        at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.createAndRegisterProperty(AbstractMappingContext.java:449)
        at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:427)
        at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:607)
        at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:295)
        at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:257)
        at org.springframework.data.mapping.context.AbstractMappingContext.initialize(AbstractMappingContext.java:373)
        at org.springframework.data.jpa.repository.config.JpaRepositoryConfigExtension$JpaMetamodelMappingContextFactoryBean.createInstance(JpaRepositoryConfigExtension.java:216)
        at org.springframework.data.jpa.repository.config.JpaRepositoryConfigExtension$JpaMetamodelMappingContextFactoryBean.createInstance(JpaRepositoryConfigExtension.java:169)
        at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:134)
        at org.springframework.data.jpa.repository.config.JpaRepositoryConfigExtension$JpaMetamodelMappingContextFactoryBean.afterPropertiesSet(JpaRepositoryConfigExtension.java:230)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
        ... 40 more
    

    【讨论】:

      【解决方案3】:

      来自 JPA 规范:

      主键必须定义在作为实体层次结构根的实体类或 映射的超类,它是实体层次结构中所有实体类的(直接或间接)超类。这 主键必须在实体层次结构中只定义一次

      因此,根据 JPA,您无法重新定义 @Id。我不会称这是一个错误。

      虽然此处作为答案给出的解决方法可能有效,但对于其他 JPA 框架,它可能不起作用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-19
        • 1970-01-01
        • 1970-01-01
        • 2011-05-15
        • 2012-01-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多