【问题标题】:Hibernate inheritance with different primary key具有不同主键的休眠继承
【发布时间】:2018-04-19 07:40:14
【问题描述】:

我正在尝试使用 TABLE_PER_CLASS 策略创建继承,但我想为每个表设置不同的主键,这可能吗?

我有一个类 Register,它有数百万个实例,其中一些实例是“特殊的”,并且对于它们的列和额外列有不同的规则。

@MappedSuperclass

public abstract class Register {


    @Id
    @Column(nullable = false, unique = true, updatable = false)
    private Long userId;


    private Date checked;

    @Column(nullable = false)
    private RegisterState tipo;
}


@Entity
@AttributeOverrides({ @AttributeOverride(name = "userId", column = @Column(nullable = false, unique = false, updatable = false)) })
public class PotencialRegister extends Register implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;


    @Column(length = 64, nullable = false, unique = false)
    private String referer;
}

对于基本寄存器,我不需要 Id 属性,因为我有一个唯一的列,但对于专用实体,该列不是唯一的,所以我添加了一个额外的属性。

问题是hibernate使用父id创建了复合主键(生成的schema是):

create table PotencialRegister (
        id integer not null,
        userId bigint not null,
        checked datetime(6),
        tipo integer not null,
        referer varchar(64) not null,
        primary key (id, userId)
    )  

    create table Register (
        userId bigint not null,
        checked datetime(6),
        tipo integer not null,
        primary key (userId)
    )  

列是正确的,schama 是我想要的,但我想从 PotencialRegister 主键中删除“id”成员。

【问题讨论】:

  • 您是否仍然看到以下答案中提供的任何问题?

标签: java hibernate inheritance mappedsuperclass table-per-class


【解决方案1】:

您可以创建另一个没有@Id 列的类,并将该类用作每种Register 的基类。

所以你的 Register 类看起来像:

@MappedSuperclass

public abstract class Register {

    @Column(nullable = false, unique = true, updatable = false)
    private Long userId;

    private Date checked;

   @Column(nullable = false)
    private RegisterState tipo;
}

现在对于您的普通注册,您可以执行以下操作:

 @Entity   
 public class NormalRegister extends Register implements Serializable{

    @Id
    public Long getUserId(){
      return super.userId;
    }

     public void setUserId(Long uId){
        super.userId=uId;
      }

   }

接下来您将 PotencialRegister 类定义为:

@Entity
@AttributeOverrides({ @AttributeOverride(name = "userId", column = @Column(nullable = false, unique = false, updatable = false)) })
public class PotencialRegister extends Register implements Serializable {

    private Integer id;


    @Column(length = 64, nullable = false, unique = false)
    private String referer;

    @Id
    public Long getUserId(){
      return super.userId;
    }

     public void setUserId(Long uId){
        super.userId=uId;
      }

}

有了这个你在基类中没有Id,所有子类都可以定义自己的Id属性

【讨论】:

  • 如果您觉得答案有帮助,请分享赏金积分。如果您需要任何进一步的说明,请询问。
  • 实际上它并没有解决我的问题,因为我不想拥有“id”列......完美的主键是 userId,如果我把它放在我的抽象类中我遇到的问题,如果我起飞,并放入每个扩展类,我会遇到不兼容
  • 我了解您的问题在于 PotenicalRegister 类,其中您的实现 id 和 userId cols 成为主键的一部分,因为它是从抽象类继承的。使用我的解决方案,您可以根据需要定义主键,抽象类中没有主键,寄存器类的每个实现都可以有它的 pwn 主键。
  • 请告诉我您在每个扩展类中添加@Id 属性时遇到的不兼容问题,以便我们为您提供解决方案。
  • 从基类中删除 @Id 时出现异常。我无法弄清楚我缺少什么。你能帮我吗?创建名为“registerRepository”的 bean 时出错:调用 init 方法失败;嵌套异常是 java.lang.IllegalArgumentException:此类 [....Register] 未定义 IdClass
【解决方案2】:

在每个类层次结构的表中,Version 和 Id 属性都假定是从根类继承的。如果我没有错,那么您不能在单个类/类层次结构中使用多个 Id 属性。在您的基类中,您可以将表中通用的属性放在表中,并仅在特定类(代表单个表)中使用 Id 属性。

【讨论】:

    【解决方案3】:

    您不能将 userId 重新定义为主键:https://hibernate.atlassian.net/browse/HHH-11771。 所以我相信你应该考虑将 userId 从抽象类移动到带有适当注释的实现。

    【讨论】:

      猜你喜欢
      • 2016-10-04
      • 2023-03-14
      • 2019-07-05
      • 2013-09-15
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      • 2020-12-18
      • 2011-04-03
      相关资源
      最近更新 更多