JPA实体没有主键?

20

我有一个实体类:

@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.

我在网上读到实体必须有一个主键定义的规定。但是我的表格只有一行,仅用于保存系统配置。

所以我只需要查询是否存在该行,然后获取该行并更新它。

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

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


1
我的答案被接受了吗? - Jose Manuel Gomez Alvarez
6个回答

37

我之前也遇到过一条没有主键的消息问题。

在Oracle中,您可以使用ROWID列,这对于任何表格都是存在的。

就像这样:

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

希望能对您有所帮助...


1
非常感谢您的回答。它救了我的一天。 - sher17
你是如何填充它的? - Steve
@Steve,ROWID 是由 Oracle 自动生成的内部键。 - Jose Manuel Gomez Alvarez
如果我们从视图中进行选择,则“same”不适用。请建议如何处理视图。 - Priyanshu Singh
@JoseManuelGomezAlvarez,星期一我访问我的工作机器时会告诉你确切的驱动程序版本。顺便说一句,我通过创建一个带有几个列的@EmbeddedId来解决了这个问题,使行唯一(有一个唯一索引),即使它不是复合键,驱动程序也不会抱怨。通常情况下,您可以创建一个包含所有列的EmbeddedId,并将@Entity留空。 - Christian Vincenzo Traina
显示剩余3条评论

26

JPA 2.0规范

  • 实体类必须带有@Entity注解。
  • 实体类必须拥有无参构造函数。
  • 实体类不能是final类型。
  • 实体类必须实现Serializable接口。
  • 实体类必须拥有独一无二且不可修改的ID

否则将无法进行操作。


6

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

@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...

请注意并保持愉快!!!

(这段话不涉及IT技术)

我也需要做类似的事情,不过在我的情况下,我要将其映射到数据库视图,甚至没有组合主键或唯一键... - Nicolas Mariano Obregon

3

在Postgres中只需要添加一个虚拟ID字段。

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

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

-1

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


你的意思是在我的Entity.java文件中,在列名上方写上'@Id',而不更改数据库配置吗?IP地址会不断变化,因此无法固定。 - Siddharth Trikha
是的,你可以将它放在 applicationName 上。 - 6ton
1
如果您的记录中有标记为ID的字段具有相同的值,则它将无法正常工作。这可能会导致您的结果集包含重复的记录。 - magulla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接