JPA entity has no primary key?
Asked Answered
W

6

20

I have an Entity class:

@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() {
    }

I get the following error:

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

I read online and found out that entities must have a primary key defined. But my table here is a ONE row table only. It just used to save system configuration.

So only queries I will like to do will be to check if the row exists then get that row and update it.

My columns are serverIp, port, name of the server.

How should I proceed to remove this error?

Why answered 28/1, 2014 at 5:15 Comment(1)
is my answer accepted?Troupe
H
26

JPA 2.0 Specification

  • Entity class must be annotated with the Entity annotation.
  • Entity class must have a no-arg constructor.
  • Entity class must not be final
  • Entity class must implement the Serializable interfaces.
  • Entity class must have a unique, immutable ID

Otherwise, you cannot.

Hug answered 28/1, 2014 at 6:59 Comment(0)
T
38

I had this problem as well with a message without PK.

In Oracle, you can use the ROWID column which is always there for any table.

Like this:

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

Hope it helps...

Troupe answered 25/8, 2016 at 12:29 Comment(8)
Thank you very much for this answer. it saved my dayMisalliance
How are you populating it?Tidewaiter
@Tidewaiter the ROWID is an internal key generated automatically by Oracle.Troupe
same is not applicable if we are selecting from view.Please suggest how can we do with viewLiliuokalani
In that case you need to first include the rowid of one of the tables in the view select, provided that, for that record, the rowid is still unique in the view results.Troupe
In this way JPA fails validation, because it says that there's not a column named ROWID. I'm using an Oracle DBChiffchaff
@ChristianVincenzoTraina what versions are you using of JPA/Oracle driver? what solution did you apply?Troupe
@JoseManuelGomezAlvarez I'll tell you the exact driver versions when I access my work machine Monday. By the way, I solved it by creating an @EmbeddedId with a couple of columns that made the row unique (there was a unique index), and even if it wasn't a compound key the driver didn't complain. Tendentially you can create an EmbeddedId with all the columns, and leave the @Entity emptyChiffchaff
H
26

JPA 2.0 Specification

  • Entity class must be annotated with the Entity annotation.
  • Entity class must have a no-arg constructor.
  • Entity class must not be final
  • Entity class must implement the Serializable interfaces.
  • Entity class must have a unique, immutable ID

Otherwise, you cannot.

Hug answered 28/1, 2014 at 6:59 Comment(0)
C
6

Every entity object in the database is uniquely identified. An alternate way to represent a table without a primary key is to use a composite primary key using all its columns, or some of them representing a candidate key:

@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... */
}

Maybe you will have problems with [Select By Id]:

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

Take care and be happy!!!

Claustral answered 29/1, 2015 at 23:56 Comment(1)
Had to do the same, but in my case I was mapping to a db view, without even a combined PK or UK...Arrestment
B
3

In postgres just add fake id field

@Id
@Column(name="ctid")
String id;
Bitterweed answered 18/10, 2021 at 12:34 Comment(1)
While it is definitely helpful in this specific case, I'd like to point out that the ctid should not be used as a replacement for a primary key. Citing postgresql.org/docs/current/…: ctid: The physical location of the row version within its table. Note that although the ctid can be used to locate the row version very quickly, a row's ctid will change if it is updated or moved by VACUUM FULL. Therefore ctid is useless as a long-term row identifier. A primary key should be used to identify logical rows.Decadence
A
0

Another way would be specify that the class itself can be used as unique identifier with @IdClass. So in this case just annotate the class with @IdClass(CmcMapServerInfo.class) and it should be independent of underlying database.

Antitank answered 17/10, 2019 at 18:0 Comment(0)
R
-1

You can mark the applicationName or the ip address as the primary key (though not auto generated). It's ok even if neither of these columns are declared as primary keys in the database.

Rudolphrudwik answered 28/1, 2014 at 5:19 Comment(3)
You mean in my Entity.java I write '@Id' above the column and don't change my database configuration ? Ip address keeps changing, so can't keep thatWhy
Yes, you can put that on the applicationNameRudolphrudwik
it would not work. if you'll have records with same value of field marked as id, your result set might contain the same record twice.Circumcision

© 2022 - 2024 — McMap. All rights reserved.