【问题标题】:JPA entity has no primary key?JPA实体没有主键?
【发布时间】:2014-02-19 06:25:12
【问题描述】:

我有一个实体类:

@Entity
@Table(name="CMC_MAP_SERVER_INFO")
@NamedQuery(name="CmcMapServerInfo.getMapServer", query="SELECT c FROM CmcMapServerInfo c")
public class CmcMapServerInfo implements Serializable {
    private static final long serialVersionUID = 1L;

    @Column(name="APPLICATION_NAME")
    private String applicationName;

    private String remarks;

    @Column(name="SERVER_IP")
    private String serverIp;

    @Column(name="SERVER_NAME")
    private String serverName;

    @Column(name="SERVER_PORT")
    private short serverPort;

    public CmcMapServerInfo() {
    }

我收到以下错误:

Entity class [class cdot.oss.cmsat.conf.ejb.entity.CmcMapServerInfo] has no primary key specified.

我在网上阅读并发现实体必须定义一个主键。 但我这里的表只是一个单行表。它只是用来保存系统配置的。

所以我想做的唯一查询是检查该行是否存在,然后获取该行并更新它。

我的列是serverIp、端口、服务器名称

我应该如何继续消除这个错误?

【问题讨论】:

  • 我的回答被接受了吗?

标签: java database jpa entity ejb-3.0


【解决方案1】:

我也遇到了这个问题,没有 PK 的消息。

在 Oracle 中,您可以使用对任何表始终存在的 ROWID 列。

像这样:

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

希望对你有帮助...

【讨论】:

  • 非常感谢您的回答。它拯救了我的一天
  • 你是如何填充它的?
  • @Steve ROWID 是 Oracle 自动生成的内部密钥。
  • 如果我们从视图中选择,则不适用。请建议我们如何使用视图
  • 在这种情况下,您需要首先在视图选择中包含其中一个表的 rowid,前提是对于该记录,rowid 在视图结果中仍然是唯一的。
【解决方案2】:

JPA 2.0 Specification

  • 实体类必须使用Entity注解进行注解。
  • 实体类必须有一个无参数构造函数。
  • 实体类不能是最终的
  • 实体类必须实现Serializable 接口。
  • 实体类必须有一个唯一的、不可变的ID

否则,你不能。

【讨论】:

    【解决方案3】:

    数据库中的每个实体对象都是唯一标识的。 表示没有主键的表的另一种方法是使用复合主键,使用它的所有列,或者其中一些列表示候选键:

    @Entity
    public class TableWithoutId {
        @EmbeddedId EmbeddableTableWithoutId id;
    
        /* Getters an Setters... */
    
        //Here you can implement @Transient delegates to the Getters an Setters of "id".
    }
    
    @Embeddable
    Class EmbeddableTableWithoutId {
        int columnA;
        long columnB;
        /* Getters an Setters... */
    }
    

    也许你会遇到 [Select By Id] 的问题:

    entityManager.find(TableWithoutId.class, id);//it can throws NonUniqueResultException or anything like that...
    

    保重,快乐!!!

    【讨论】:

    • 必须这样做,但在我的情况下,我映射到一个数据库视图,甚至没有组合 PK 或 UK...
    【解决方案4】:

    您可以将 applicationName 或 ip 地址标记为主键(虽然不是自动生成的)。即使这些列都没有声明为数据库中的主键也没关系。

    【讨论】:

    • 您的意思是在我的 Entity.java 中我在列上方写了“@Id”并且不更改我的数据库配置? IP地址不断变化,所以不能保持不变
    • 是的,你可以把它放在 applicationName 上
    • 它不起作用。如果您将有相同字段值的记录标记为 id,则您的结果集可能包含两次相同的记录。
    【解决方案5】:

    另一种方法是指定类本身可以用作@IdClass 的唯一标识符。所以在这种情况下,只需使用 @IdClass(CmcMapServerInfo.class) 注释类,它应该独立于底层数据库。

    【讨论】:

      【解决方案6】:

      在 postgres 中只需添加假 id 字段

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-13
        • 2021-10-06
        • 1970-01-01
        • 2023-02-09
        • 1970-01-01
        • 2013-12-10
        • 2018-12-27
        • 1970-01-01
        相关资源
        最近更新 更多