【问题标题】:Is it possible to add JPA annotation to superclass instance variables?是否可以将 JPA 注释添加到超类实例变量?
【发布时间】:2010-05-21 14:41:49
【问题描述】:

我正在为两个不同的表创建相同的实体。为了对两个实体做不同的表映射等,但只有一个地方的其余代码 - 一个抽象超类。最好的办法是能够在超类中注释通用的东西,例如列名(因为它们将是相同的),但这不起作用,因为 JPA 注释不被子类继承。这是一个例子:

public abstract class MyAbstractEntity {

  @Column(name="PROPERTY") //This will not be inherited and is therefore useless here
  protected String property;


  public String getProperty() {
    return this.property;
  }

  //setters, hashCode, equals etc. methods
}

我想继承并只指定子特定的东西,比如注释:

@Entity
@Table(name="MY_ENTITY_TABLE")
public class MyEntity extends MyAbstractEntity {

  //This will not work since this field does not override the super class field, thus the setters and getters break.
  @Column(name="PROPERTY") 
  protected String property;

}

有什么想法或者我必须在子类中创建字段、getter 和 setter 吗?

谢谢, 克里斯

【问题讨论】:

    标签: java inheritance jpa annotations


    【解决方案1】:

    这是一个示例,其中包含一些可能会有所帮助的解释。

    @MappedSuperclass:

    • 是一个便利类
    • 用于存储子类可用的共享状态和行为
    • 不可持久
    • 只有子类是可持久化的

    @Inheritance 指定三种映射策略之一:

    1. 单表
    2. 已加入
    3. 每类表

    @DiscriminatorColumn 用于定义将使用哪一列来区分子对象。

    @DiscriminatorValue 用于指定用于区分子对象的值。

    以下代码结果如下:

    可以看到两个表都有id字段,但是只在AbstractEntityId @MappedSuperclass中指定了。

    另外,@DisciminatorColumn 在 Party 表中显示为 PARTY_TYPE。

    @DiscriminatorValue 在 Party 表的 PARTY_TYPE 列中显示为 Person 作为记录。

    非常重要的是,AbstractEntityId 类根本不会持久化。

    我没有指定@Column 注释,而只是依赖默认值。

    如果您添加了一个扩展 Party 的组织实体,并且如果它接下来被持久化,那么 Party 表将具有:

    • id = 2
    • PARTY_TYPE = "组织"

    组织表的第一个条目将具有:

    • id = 2
    • 与组织相关的其他属性值
    @MappedSuperclass @SequenceGenerator(name = "sequenceGenerator", 初始值 = 1,分配大小 = 1) 公共类 AbstractEntityId 实现可序列化 { 私有静态最终长序列版本UID = 1L; @ID @GeneratedValue(generator = "sequenceGenerator") 受保护的长ID; 公共 AbstractEntityId() {} 公共长 getId() { 返回标识; } } @实体 @Inheritance(策略 = InheritanceType.JOINED) @DiscriminatorColumn(name = "PARTY_TYPE", discriminatorType = DiscriminatorType.STRING) 公共类派对扩展 AbstractEntityId { 公共方(){} } @实体 @DiscriminatorValue("人") 公共类人扩展党{ 私有字符串给定名称; 私人字符串familyName; 私有字符串首选名称; @Temporal(TemporalType.DATE) 私人日期 dateOfBirth; 私人字符串性别; 公共人(){} // getter & setter 等 }

    希望这会有所帮助:)

    【讨论】:

      【解决方案2】:

      您可能希望使用 @MappedSuperclass 类注释 MyAbstractEntity,以便 hibernate 将 MyAbstractEntity 的配置导入子级中,您不必覆盖该字段,只需使用父级的。该注释是休眠的信号,它也必须检查父类。否则它假定它可以忽略它。

      【讨论】:

      • (吹毛求疵)他没有提到休眠,是吗?他可能会使用不同的 JPA 提供程序。但当然你的推理仍然适用
      • 而我其实用的是hibernate,只是忘了说:)
      【解决方案3】:

      将超类标记为

      @MappedSuperclass
      

      并从子类中删除该属性。

      【讨论】:

        【解决方案4】:

        使用@MappedSuperclass 注释您的基类应该完全符合您的要求。

        【讨论】:

          【解决方案5】:

          这是旧的,但我最近处理了这个问题并想分享我的解决方案。您可以将注释添加到覆盖的 getter。

          @MappedSuperclass
          public abstract class AbstractEntity<ID extends Serializable> implements Serializable {
          
            @Column(name = "id", nullable = false, updatable = false)
            @Id
            private ID id;
          
            public ID getId() {
              return id;
            }
          
            ...
          
          }
          
          @Entity
          @Table(name = "address")
          public final class Address extends AbstractEntity<UUID> implements Serializable {
          
            ...
          
            @Override
            @GeneratedValue(generator = "UUID")
            @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
            public final UUID getId() {
              return super.getId();
            }
          
            ...
          
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-03-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-09-09
            • 2011-09-06
            相关资源
            最近更新 更多