JPA / Hibernate 中具有继承类的复合键

发布于 2024-10-03 03:56:18 字数 499 浏览 11 评论 0原文

我在我的类结构中定义了一个复合 id,如下所示。不幸的是,我总是收到一个休眠错误,抱怨未找到“第 2 部分”:

“在实体 MoreClass 中找不到 @IdClass 的属性:第 2 部分”

任何人都可以帮助我解决问题吗? (或者至少给我指出一个有用的 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;
}

i have a composite id defined on my class structure as below. Unfortunatly i always get a hibernate error that complains on the not found "part2":

"Property of @IdClass not found in entity MoreClass : part2"

Can anybody help me on fixing the problem? (or at least point me on a helpful jpa/hibernate doc?)

@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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

So要识趣 2024-10-10 03:56:18

上述提到的 Michael 的 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();
}

顺便说一句,该解决方法有一个令人讨厌的副作用 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 中询问。列名无效异常

正确的解决方法包括手动添加 @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,需要删除@IdMappedSuperclass 的 > 和 @Type 注释。如果不删除这些,将会出现以下错误。顺便说一句,它不会改变这个 Hibernate bug 的性质

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

The mentioned workaround for HHH-9114 bug by Michael works, e.g. in my case by adding to TwitterListedCount : (note that both @Id and @Type must be added for user types to still work)

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

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

BTW, the workaround has a nasty side-effect HHH-9350 when used with schema generation, it generates duplicate composite columns:

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
);

I tried to not use @MappedSuperclass at all, but the wrong schema generation still happens. BTW I'm using DefaultComponentSafeNamingStrategy which may be where the bug lies. This is probably a different bug, asked in Hibernate find with composite key. Invalid column name Exception

The proper workaround involves adding @Column(name=) manually, which works well with schema generation:

@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, when used together with Spring Data JPA, it's required to remove the @Id and @Type annotations from the MappedSuperclass. If these are not removed, there will be errors bellow. It doesn't change the nature of this Hibernate bug, BTW.

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
凉墨 2024-10-10 03:56:18

实际上遇到了同样的问题

作为:

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

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

Actually bumped into the same problem.

As:

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

Does seem to work, I would deem it a bug. See https://hibernate.atlassian.net/browse/HHH-9114.

肩上的翅膀 2024-10-10 03:56:18

来自 JPA 规范:

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

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

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

From the JPA spec:

The primary key must be defined on the entity class that is the root of the entity hierarchy or on a
mapped superclass that is a (direct or indirect) superclass of all entity classes in the entity hierarchy. The
primary key must be defined exactly once in an entity hierarchy.

So according to JPA you can't redefine the @Id. I wouldn't call this a bug.

Although the workaround given as answer here might work, it may happen that for other JPA frameworks it doesn't work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文