【问题标题】:JPA Error : The entity has no primary key attribute definedJPA 错误:实体没有定义主键属性
【发布时间】:2021-10-18 20:37:25
【问题描述】:

我在我的应用程序中使用 JPA。在其中一张表中,我没有使用主键(我知道这是一个糟糕的设计)。

现在生成的实体如下:

@Entity
@Table(name="INTI_SCHEME_TOKEN")
public class IntiSchemeToken implements Serializable {
    private static final long serialVersionUID = 1L;

    @Column(name="CREATED_BY")
    private String createdBy;

    @Temporal( TemporalType.DATE)
    @Column(name="CREATED_ON")
    private Date createdOn;

    @Column(name="SCH_ID")
    private BigDecimal schId;

    @Column(name="TOKEN_ID")
    private BigDecimal tokenId;

    public IntiSchemeToken() {
    }

    public String getCreatedBy() {
        return this.createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public Date getCreatedOn() {
        return this.createdOn;
    }

    public void setCreatedOn(Date createdOn) {
        this.createdOn = createdOn;
    }

    public BigDecimal getSchId() {
        return this.schId;
    }

    public void setSchId(BigDecimal schId) {
        this.schId = schId;
    }

    public BigDecimal getTokenId() {
        return this.tokenId;
    }

    public void setTokenId(BigDecimal tokenId) {
        this.tokenId = tokenId;
    }



} 

在我的项目中,eclipse IDE在这个类上显示错误标记(红色十字),错误是“实体没有定义主键属性”。

谁能告诉我,如何创建没有主键的实体?

谢谢。

【问题讨论】:

标签: jpa entity


【解决方案1】:

你不能。一个实体必须有一个唯一的、不可变的 ID。它不必定义为数据库中的主键,但字段或字段集必须唯一标识行,并且其值可能不会改变。

因此,如果您的实体中的一个字段或您的实体中的一组字段满足这些条件,请将其(或它们)设为实体的 ID。例如,如果用户无法在同一天创建两个实例,则可以将 [createdOn, createdBy] 设为实体的 ID。

当然,这是一个糟糕的解决方案,您应该真正更改架构并在实体中添加一个自动生成的单列 ID。

【讨论】:

  • +1。如果你从业务逻辑的角度不需要它,只需添加一个人工的 ID 列,让 ORM 快乐,你的生活更轻松。
  • @感谢您的回复。我已将 createdOn 声明为不在数据库中的实体中的主键。现在可以正常使用了。
  • “它不必被定义为数据库中的主键”。我对此表示反对。如果由于存在另一个主键定义而必须这样做,则必须使用它。否则,如果隐含的建议是定义二级索引,那么可以,但完全没有索引,你会杀死你的数据库。
  • 我只是说Hibernate不需要将其Id字段定义为表中的主键。当然,我永远不会使用没有 PK 的表,但这是一个不同的问题。
【解决方案2】:

如果您的主键 (PK) 是在实体类中继承的托管超类,那么您必须在 persistence.xml 文件中包含映射的超类名称。

查看错误报告: https://bugs.eclipse.org/bugs/show_bug.cgi?id=361042

【讨论】:

    【解决方案3】:

    如果你需要定义一个没有主键的类,那么你应该将该类标记为一个 Embeddable 类。否则,您应该为您定义的所有实体提供主键。

    【讨论】:

      【解决方案4】:

      您可以关闭(更改)已添加的验证。

      转到工作区首选项“Java Persistence->JPA->Errors/Warnings”下一个“类型”并将“实体没有主键”更改为“警告”。

      【讨论】:

      • 在这种情况下似乎是理想的解决方案^
      【解决方案5】:

      除了http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#No_Primary_Key,您还可以在Oracle 中使用一些内置列,例如ROWID

      但要小心:

      实体框架不适用于所有类型的数据(例如用于分析而非查询的统计数据)。

      【讨论】:

        【解决方案6】:

        没有 Hibernate 的另一种解决方案

        如果 - 你桌上没有PK - 存在可能是 PK 的列的逻辑组合(如果您可以使用某种 rowid,则不需要) -- 但是有些列是 NULLable 所以你真的不能创建 PK 因为 DB 限制 - 并且你不能修改表结构(会破坏遗留代码中没有明确列出列的插入/选择语句)

        那么你可以试试下面的技巧 - 在数据库中创建具有连接逻辑键列 ('A='||a||'B='||'C='c..) 或 rowid 值的虚拟列的视图 - 通过这个视图创建你的 JPA 实体类 - 用@Id 注解标记虚拟列

        就是这样。更新/删除数据操作也是可能的(不是插入),但如果虚拟键列不是由 rowid 组成的,我不会使用它们(以避免数据库表的全扫描搜索)

        附:链接的问题部分描述了相同的想法。

        【讨论】:

          【解决方案7】:

          您需要创建主键,如果没有找到任何符合条件的字段,则创建自增ID。

          CREATE TABLE fin_home_loan (
            ID int NOT NULL AUTO_INCREMENT,
              PRIMARY KEY (ID));
          

          【讨论】:

            【解决方案8】:

            只需添加虚假的 id 字段。 在 Postgres 中:

            @Id
            @Column(name="ctid")
            String id;
            

            在甲骨文中:

            @Id
            @Column(name="ROWID")
            String rowid;
            

            【讨论】:

              猜你喜欢
              • 2017-04-13
              • 1970-01-01
              • 2021-10-06
              • 1970-01-01
              • 2014-02-19
              • 2012-08-16
              • 1970-01-01
              • 2016-08-05
              相关资源
              最近更新 更多