【问题标题】:Hibernate Component with Generics带有泛型的休眠组件
【发布时间】:2010-12-18 22:49:23
【问题描述】:

好的,这个问题最好用代码来解释。所以我会尽量给出最简洁的例子。

Timestamped.java

@Embeddable
public class Timestamped<E> {
    private E value;
    private Date timestamp;
    ...
}

Foo.java

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class Foo {
    @Embedded
    @AttributeOverides({
        @AttributeOverride(name="timestamp", column=@Column("VALUE_TS")),
        @AttributeOverride(name="value",     column=@Column("VALUE"))
    })
    private TimestampedValue<E> value;
    ...
}

Bar.java

@Entity
@DiscriminatorValue("BAR")
public class Bar extends Foo<Double> { }

我需要 Bar 为 value.value 使用适当的类型转换器,并为 Foo 的每个子类使用不同的转换器。理想情况下,我只想扩充此代码,但我可以将 Foo 抽象化并将 value 字段移动到每个带有附加注释的子类。

【问题讨论】:

    标签: java hibernate generics components


    【解决方案1】:

    您遇到了擦除问题。 Hibernate 无法知道如何处理泛型类型,因为该信息在运行时不可用。不过也挺好的。

    【讨论】:

      【解决方案2】:

      如果您要做的是创建与许多表相对应的许多类,但对“时间戳”和“值”属性使用相同的列名,那么您想要的是具有这些列的“映射超类” ,而不是嵌入式类。研究@MappedSuperclass注解。

      【讨论】:

      • 我想如果我将字段展平,我会遇到类似的问题。但我非常希望将其保留为组件,因为对象上的多个字段可能具有时间戳和关联的用户。
      • 您也可以将映射的超类用于嵌入。
      【解决方案3】:

      第一种方法行不通 - 你不能持久化“泛化”类。

      您要么必须按照您的建议将 value 移动到具体的子类中,要么编写一个 UserType 来持久化您的 Timestamped 组件。

      【讨论】:

      • 如果移动值字段,如何设置组件字段的类型。是否有某种组件字段覆盖了 @Type 的等效项?
      • 您必须将其声明为具体类型 - 例如private TimestampedValue&lt;Double&gt; 并使用 @AttributeOverrides。 Hibernate 根本无法处理泛型,因此您持久化/注释的所有类都必须显式声明类型参数(或非泛型)。如果您的层次结构很大,编写自定义 UserType 可能是更好的方法。
      • 我最终使用了 ChssPly76 的答案。所以 foo 现在有一个“TimestampedValue value”字段。
      猜你喜欢
      • 2011-10-23
      • 1970-01-01
      • 2018-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-13
      • 1970-01-01
      • 2023-03-17
      相关资源
      最近更新 更多