【问题标题】:Overriding @Id defined in a @MappedSuperclass with JPA使用 JPA 覆盖在 @MappedSuperclass 中定义的 @Id
【发布时间】:2015-07-08 16:53:01
【问题描述】:

我有一个 AbstractEntity 类,它由我的应用程序中的所有实体扩展,基本上充当标识符提供者。

@MappedSuperclass
public class AbstractEntity implements DomainEntity {

    private static final long serialVersionUID = 1L;

    /** This object's id */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected long id;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name="creation_date", nullable = false, updatable=false)
    private Date creationDate = new Date();

    /**
     * @return the id
     */
    public long getId() {
        return this.id;
    }

    /**
     * @param id the id to set
     */
    public void setId(long id) {
        this.id = id;
    }
}

我现在有一个案例,我需要为我的几个实体类定义一个单独的 Id,因为它们需要有一个自定义序列生成器。如何做到这一点?

@Entity
@Table(name = "sample_entity")
public class ChildEntity extends AbstractChangeableEntity {

    @Column(name = "batch_priority")
    private int priority;

    public int getPriority() {
        return priority;
    }

    public void setPriority(int priority) {
        this.priority = priority;
    }

}

【问题讨论】:

  • 一种选择可能是覆盖需要自定义的子类中的生成器名称,但这意味着您对所有实体使用相同类型的生成器(序列生成器)。查看this post 了解更多信息。如果您/我们可以覆盖子类中的整个生成器,那将是理想的,但我认为它目前无法工作。

标签: java hibernate jpa hibernate-mapping mappedsuperclass


【解决方案1】:

你不能这样做,正如this GitHub example所证明的那样。

在基类中定义@Id 后,您将无法在子类中覆盖它,这意味着最好将@Id 责任留给每个具体的具体类。

【讨论】:

    【解决方案2】:

    拆分你的基类。

    定义除 ID 之外的所有常用字段:

    @MappedSuperclass
    public  abstract class AbstractEntityNoId implements DomainEntity {
     private static final long serialVersionUID = 1L;
    
        @Temporal(TemporalType.TIMESTAMP)
        @Column(name="creation_date", nullable = false, updatable=false)
        private Date creationDate = new Date();
    }
    

    使用默认 ID 生成器进行上述扩展:

    @MappedSuperclass
    public abstract class AbstractEntity extends AbstractEntityNoId {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        protected Long id;
    
        public Long getId(){
           return id;
        }
    }
    

    需要自定义 ID 生成的类扩展了前者,而其他类扩展了后者。

    使用上述方法,除了需要生成自定义 ID 的实体之外,无需更改现有代码。

    【讨论】:

    • 但是我想保持层次结构,我想要的只是以某种方式隐藏基类提供的标识符
    • 正如已经指出的那样,你不能。使用上述内容,您无需更改任何现有代码,除了那些需要自定义 ID 生成的实体的超类。一切仍然是 DomainEntity 的一个实例。
    【解决方案3】:

    在某些情况下不可行的解决方案之一是使用 get 方法上的注释而不是字段。它将为您提供更大的灵活性,特别是覆盖您想要的任何内容。

    在代码中:

    @MappedSuperclass
    public class AbstractEntity implements DomainEntity {
    
        private static final long serialVersionUID = 1L;
    
        protected long id;
    
        private Date creationDate = new Date();
    
        /**
         * @return the id
         */
        /** This object's id */
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        public long getId() {
            return this.id;
        }
    
        /**
         * @param id the id to set
         */
        public void setId(long id) {
            this.id = id;
        }
    
        @Temporal(TemporalType.TIMESTAMP)
        @Column(name="creation_date", nullable = false, updatable=false)
        public Date getCreationDate () {
            return this.creationDate ;
        }
    }
    

    还有你的子类:

    @Entity
    @Table(name = "sample_entity")
    public class ChildEntity extends AbstractChangeableEntity {
    
    
    private int priority;
    
    @Override
    @Id
    @GeneratedValue(strategy = GenerationType.ANOTHER_STRATEGY)
    public long getId() {
        return this.id;
    }
    
    @Column(name = "batch_priority")
    public int getPriority() {
            return priority;
        }
    public void setPriority(int priority) {
            this.priority = priority;
        }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-08
      • 1970-01-01
      • 2013-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-24
      • 1970-01-01
      相关资源
      最近更新 更多