46

I'm working with a table in a database and that table don't have a primary key or a proper column whith a unique value who can act as a primary key, I don't have permissions to alter that table.

What should I do? I tried putting a @id annotation in a random column and it worked, but I don't know if this is going to bring any trouble later on. what can I do?

My class

@Entity
@Table(name="my_table")
public class TheTable {
@Column (name="name", nullable=false)
    private String name;

    @Id <--- I just put this id in this random column but this column should not be a id column
    @Column (name="anyfield", nullable=false)
    private String anyfield;
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
stackUser2000
  • 1,615
  • 11
  • 32
  • 55

11 Answers11

184

I had this problem and was using the wrong import for @id:

Make sure it's:

import javax.persistence.Id;

and not:

import org.springframework.data.annotation.Id;
Cory Roy
  • 5,379
  • 2
  • 28
  • 47
  • @Id needs to be an integer though, or convertible to an Integer, or am I mistaken? – sMaN Apr 12 '16 at 05:47
  • I am mistaken, my issue was elsewhere. I've managed to use an @Enumerated(EnumType.STRING) column as the id. I'm returning a single row of a single column, so this enum is unique by default. – sMaN Apr 12 '16 at 22:37
  • OP was specifically asking what to do when table has no primary key column to mark with `@Id`. – Klesun Jun 12 '21 at 16:53
11

Hibernate is an intermediate to adress SQL databases, and since each row in a sql database should have a unique identifier, hibernate forces you to define one.

Here is an example of a generated primary key, which will be added automatically (do not forget the getter and setter)

@Id 
@GeneratedValue
@Column(name = "id")
private int id;

Since duplicates are not allowed, choosing an arbitrary column is not the way to go.

ThMBc
  • 794
  • 13
  • 18
  • would this require an actual column called 'id'? – shanehoban Feb 03 '16 at 13:37
  • 1
    This solution requires it, but if you have a column in which you only have unique values, that could be the @Id column as well. If you decide to auto-generate one, you also need that column in your database. – ThMBc Feb 03 '16 at 14:13
  • OK, what about where no unique value columns are being returned from a stored procedure? Could you perhaps try the following: `@Id \n @GeneratedValue \n private int id;` – shanehoban Feb 03 '16 at 15:13
  • 1
    If you want to use hibernate and thus SQL you need to define a unique value column. The code provided automatically creates this column and fills it up. there are alternative storage systems where no primary keys are required but that is not in the scope of this question or answer. If you do not supply the @Column annotation it will create it for you. – ThMBc Feb 03 '16 at 15:30
  • "each row in a sql database should have a unique identifier" - this is not true. – Mike Argyriou May 28 '17 at 20:29
4

Also had same issue. The problem was wrong import of @Id annotation. So please make sure that you not only annotate the id but also that you do it with javax.persistence.Id.

3

JPA (not Hibernate as such) requires all entities to be uniquely identified. Sadly it doesn't allow for what you want.

JDO, on the other hand, does allow a persistable class to map to a table without PK and would handle what you need.

3
You can solve this using embedded id 

ex:

@Entity
@Table(name = "my_table")
public class MyTable implements Serializable {

    private static final long serialVersionUID = 1L;

    // @Id
    @Column(name = "id", insertable = false, updatable = false)
    private String id;

    @EmbeddedId
    MYtablePK pk;

    public MYtablePK getPk() {
        return pk;
    }

    public void setPk(MYtablePK pk) {
        this.pk = pk;
    }

    @Column(name = "my_table_FirstName", insertable = false, updatable = false)
    private String name;

    @Transient
    public String getName() {
        return pk.getName();
    }

    public void setName(String mrn) {
        pk.setName(name);
    }
    @Transient
        public String getSeverity() {
        return pk.getSeverity();
    }
    public void setSeverity(String severity) {
        pk.setName(name);
    }

    public String getId() {
        return pk.getId();
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return pk.getName();
    }
    public void setName(String name) {
        tpk.setName(name);
    }
}

@Embeddable
public class MyTablePK implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = -1257821517891392898L;
    @Column(name = "id")
    private String id;
    @Column(name = "name")
    private String name;
    @Column(name = "dob")
    private Date dob;
    public Date getdob() {
        return dob;
    }
    public void setdob(Date dob) {
        this.pk.setdob(dob);
    }
    @Column(name = "severity")
    private String severity;
    public String getSeverity() {
        return severity;
    }
    public void setSeverity(String severity) {
        this.severity = severity;
    }

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name
1

Its not juts Hibernate - a relational datamodel require primary keys. So what you've got is a broken data model because without a primary key it can't be relational, and this is why its difficult to use with an ORM.

for more info, here

Ankur Singhal
  • 26,012
  • 16
  • 82
  • 116
0

Make sure there is p.k constraint defined for each Entity and check the import statement for Id Annotation. Check Import statement:

import javax.persistence.Id;
@Id
@Column(name="id")
@GeneratedValue 
private int id;
0

Specify a field annotated with @Id. Every @Entity requires an @Id (This is the primary key in the table). The solution for you is to use @Embeddable instead of @Entity, then you wont need to annotate any column with @Id. Change the import statement from javax.persistence.Entity; to javax.persistence.Embeddable;

user7420004
  • 61
  • 1
  • 5
0

Use @Embeddable annotation instead of @Entity if your class mapping is used as readOnly mapping and does not have PK or @EmbeddedKey

//@Entity
@Embeddable
@Table(name = "my_table")
public class MyTable implements Serializable {

}
JeremyW
  • 5,157
  • 6
  • 29
  • 30
0

Basically make sure your Column annotated fields match the database table in question

0

requirement: table don't have a primary key or a proper column whith a unique value solution: just add a dummy column for your id, and ignore it for the rest of your select statements. imagine such a column is not there for all your requirements that doesnt need a primary key. setup some auto increment mechanism or something based on sequence, for this column. you need: permission to alter table, though, as needed.

Jose
  • 1
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 15 '22 at 12:43