Skip to content

Entity IDs

@Id

One of the main requirements of relational databases is having unique identifiers. In order to declare a column. that represents the primary key, you have to use @Id annotation. The primary key in Java must be a primitive type, or a wrapper type, e.g. Integer,Long, String,Date, BigInteger orBigDecimal.

@Entity
@Table(name = "movies")
public class Movie {
   @Id 
   private Long id;

   private String name;

   @Column(name = "movie_title")
   private String title;
}

NOTE: In practice, @Id very often appears above a Long, UUID, or String field.

@GeneratedValue

Primary keys in the database can be natural or automatically generated when saving the row to the database. In order to mark the column representing the identifier so that it is generated automatically, we must additionally use an annotation @GeneratedValue.

The annotation can choose the method of generating such an identifier. These methods are represented by the GenerationType enum values:

  • TABLE
  • SEQUENCE
  • IDENTITY

The description and details of the individual generation methods are beyond the scope of the training. When using @GeneratedValue, use the GenerationType.AUTO strategy so that the generation method is automatically adjusted to the capabilities of the database type used, e.g .:

import javax.persistence.*;

@Entity
@Table(name = "movies")
public class Movie {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  private String name;

  @Column(name = "movie_title")
  private String title;
}

@EmbeddedId

Tables can also have keys that consist of multiple columns. In order to define such a key, we must follow these steps:

  • define a class that represents a composite key. This class must implement the Serializable interface.
  • mark the class representing the composite key with the annotation @ Embeddable
  • on the entity on which we want to use such a key, define the key field and place the annotation @EmbeddedId above it.

NOTE: We can embed a class that represents multiple columns in an entity and that is not an entity key in a similar way to a composite key. In this case, instead of the @EmbeddedId annotation, we use the @Embedded annotation.

The next example shows how to use a composite key in an entity, and also shows how to embed a class representing two columns in the entity:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Embeddable;

@Embeddable
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
  private String firstName;
  private String lastName;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Embeddable;
import java.io.Serializable;

@Embeddable
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TeacherId implements Serializable { // interfejs Serializable jest wymagany
  private int documentId;
  private String license;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Embedded;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {

  @EmbeddedId // klucz złożony
  private TeacherId teacherId;

  @Embedded // osadzenie kolumn firstName i lastName w encji za pomocą pola klasy Person
  private Person person;
}

@IdClass

Another way to define multi-column keys is with the annotation @IdClass, however it is a bit less intuitive than using@EmbeddedId.

The class representing the key looks exactly the same as using @EmbeddedId.

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Embeddable;
import java.io.Serializable;

@Embeddable
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TeacherId implements Serializable {
  private int documentId;
  private String license;
}

The difference appears in the entity in which we define the composite key. The @IdClass annotation must be above the class definition and must point to an object that stores information about the columns that make up the primary key. These columns must be additionally declared at the level of the database entity along with marking them as @Id. This solution can work when one of the columns is a relation, e.g.

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@IdClass(TeacherId.class)
public class Teacher {

  @Id
  private int documentId;

  @Id
  private String license;

  @Embedded
  private Person person;
}