9.12.6 Specifying the primary key in the entities
With an entity, make sure that you specify the primary key in the class hierarchy. When you specify the primary key, follow the below rules:
-
For a simple (not complex type) primary key, specify @Id in the persistence field or persistence property or specify the key in the O/R mapping file. Accordingly, associate the primary key with the entity fields.
-
For a complex type primary key, specify the primary key class in a single field as @EmbeddedId or specify the complex primary key as a field set using @IdClass and @Id.
-
For a complex type primary key, create a class that contains the primary key, called the primary key class.
If these conditions are not satisfied, an exception occurs when you start the application.
Also, do not change the primary key value of the entity in the application. If the primary key value is changed in the application, an exception occurs during execution.
- Organization of this subsection
(1) Primary key type
Set one of the following types for the simple or complex type primary keys:
-
Java primitive type
-
Type that wraps primitive
-
java.lang.String
-
java.util.Date
-
java.sql.Date
Note that if the approximation type (for example, floating-point number type) is specified as the primary key, rounding off errors and problems such as lack of reliability in the results of the equals method occur in Cosminexus JPA Provider. Therefore, the operations when the approximation type is used in the primary key might not function properly with Cosminexus JPA Provider. If java.util.Date is used in a field/ property as the primary key, the temporal type attribute must be specified as the DATE type.
(2) Complex type primary key
The complex type primary key can be handled with an entity. The methods of specifying a complex type primary key in the entity include the method of using the embedded class and the method of using @IdClass. The following points describe each method:
(a) Method of using the embedded class
To use an embedded class, create a class that assigns @Embeddable and define the complex type primary key as a field in that class. With the entity class, define the type field of the class that assigns @Embeddable and annotate @EmbeddedId. The examples of entity class and embedded class are as follows:
-
Example of an entity class
@Entity public class Employee { private EmployeePK employeePK; public Employee(){ } @EmbeddedId public EmployeePK getEmployeePK(){ retrun this.employeePK; } public void setEmployeePK(EmployeePK employeePK){ this.employeePK = employeePK; } ... } -
Example of an embedded class
@Embeddable public class EmployeePK { private String name; private int employeeId; public EmployeePK(){ } public boolean equals(Object obj){ ... } public int hashCode(){ ... } ... }
For details on the embedded class, see (3) Embedded class. Note that you can also use the O/R mapping file instead of the annotation.
(b) Method of using @IdClass
To use @IdClass, define multiple instance variables corresponding to the primary key in the entity class and assign @Id. Also, use @IdClass to specify the primary key class. With the primary key class, define a field or property with the same name and type as the primary key defined in the entity. The examples of entity class and primary key class are as follows:
-
Example of an entity class
@Entity @IdClass(EmployeePK.class) public class Employee { private String name; private int employeeId; public Employee(){ } @Id public String getName(){ retrun this.name; } public void setName(String name){ this.name = name; } @Id public int getEmployeeId(){ retrun this.employeeId; } public void setName(int employeeId){ this.employeeId = employeeId; } ... } -
Example of a primary key class
public class EmployeePK implements Serializable { private String name; private int employeeId; public EmployeePK(){ } public boolean equals(Object obj){ ... } public int hashCode(){ ... } ... }
As in the case of the embedded class, you can use the O/R mapping file instead of the annotation. Note that the access type of the primary key class is determined by the access type of the entity class corresponding to the primary key.
To handle a complex type primary key, use either an embedded class or @IdClass. However, follow the below rules:
-
The primary key class must be public and must have a constructor without argument.
-
When you use a persistence property, set the property of the primary key class to public or protected.
-
The primary key class must be serializable.
-
Define the equals and hashCode method with the primary key class. When the primary keys on the mapped database are equal, true must be returned for equals and the hashCode value must be equal.
-
The complex primary key must be mapped as an embedded class or must map multiple fields/properties of the entity class.
-
When a primary key class is mapped to the complex fields/properties of the entity class, match the field/property name of the primary key of the primary key class with the name of the entity class. Also, unify the types.
With Cosminexus JPA Provider, the operations might not function properly if these conditions are not satisfied. If the conditions are not satisfied, an exception might also occur when you start the application.
(3) Embedded class
If you prepare a class that brings together some fields for persistence, you can store the fields as entity fields. Such a class is called an embedded class.
The embedded class is embedded in an entity and is mapped to the same database table as the entity. Therefore, unlike the entity, the embedded class does not have a primary key.
When using the embedded class, the user specifies @Embeddable in the embedded class. Also, specify @Embedded in the embedding destination field or property in the entity class that is embedded. Note that you can also define the embedded class similarly in the O/R mapping file instead of the annotation.
You can also use the embedded class for defining the complex type primary key. In this case, specify @EmbeddedId instead of @Embedded in the embedded entity class.
Make sure that you conform to the following creation requirements for the embedded class:
-
Make sure that the embedded class is defined in @Embeddable or in the <embeddable> tag of the O/R mapping file.
-
Do not set enum and the interfaces as an embedded class.
-
When the entity class containing the embedded class is passed by value as a detached object, implement the Serializable interface.
-
Do not set the embedded class, the persistence instance variables of the embedded class, and all the methods to final.
-
The embedded class must have a constructor without an argument.
-
Declare the constructor without an argument as public or protected.
-
The instance variable of the embedded class must be referable from private, protected, or package.
-
Specify settings so that the persistence instance variable of the embedded class is not accessed directly from the client. Do not access the persistence instance variable of the embedded class with the accessor method (getter/ setter method) of the entity and the other business methods.
With Cosminexus JPA Provider, if the conditions 1 and 2 are not satisfied, an exception occurs and the application fails to start. Also, in the case of conditions 3 to 8, an exception might occur, but even if an exception does not occur, the operations might not function properly.
You determine the access type of the embedded class using the access type of the entity class on the embedded side.
When using the embedded class, set one embedded hierarchy. Also, the embedded class object cannot be shared by multiple entities. If these conditions are not satisfied, the operations might not function properly with Cosminexus JPA Provider.