Составной ключ в JPA / Hibernate с унаследованным классом - PullRequest
6 голосов
/ 18 ноября 2010

У меня есть составной идентификатор, определенный в моей структуре классов, как показано ниже.К сожалению, я всегда получаю ошибку гибернации, которая жалуется на не найденную "part2":

"Свойство @IdClass не найдено в сущности MoreClass: 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;
}

Ответы [ 3 ]

2 голосов
/ 19 августа 2014

Упомянутый обходной путь для HHH-9114 bug от Michael работает , например, в моем случае добавив к 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();
}

Кстати, обходной путь имеет неприятный побочный эффект 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 с составным ключом.Неверное имя столбца Исключение

Правильный обходной путь включает добавление @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;

FYI, при использовании вместе с Spring Data JPA , необходимо удалить аннотации @Id и @Type из MappedSuperclass.Если они не будут удалены, будут ошибки ниже.Это не меняет природу этой ошибки 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
2 голосов
/ 23 декабря 2010

На самом деле наткнулся на same problem.

Как:

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

Кажется, работает, я бы посчитал это ошибкой.Смотри https://hibernate.atlassian.net/browse/HHH-9114.

1 голос
/ 08 декабря 2015

Из спецификации JPA:

Первичный ключ должен быть определен в классе сущности, который является корнем иерархии сущностей, или в сопоставленном суперклассе, который является (прямым или косвенным) суперклассомвсе классы сущностей в иерархии сущностей.Первичный ключ должен быть определен ровно один раз в иерархии объектов.

Таким образом, согласно JPA, вы не можете переопределить @Id.Я бы не назвал это ошибкой.

Хотя обходной путь, приведенный здесь в качестве ответа, может сработать, может случиться так, что для других платформ JPA это не сработает.

...