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 aLong
,UUID
, orString
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;
}