Skip to content
thesarfo

Concept

Persistence: Primary Keys

Writing a custom IdentifierGenerator, and defining composite primary keys with @IdClass or an @Embeddable id.

views 0

You can generate your own primary keys with Hibernate by implementing the IdentifierGenerator interface — the most important method to override is generate().

public class UUIDGenerator implements IdentifierGenerator {
@Override
public Object generate(SharedSessionContractImplementor sharedSessionContractImplementor, Object o) {
return UUID.randomUUID().toString(); // this is just a basic implementation
}
}

There are other methods you can implement based on your use case — for instance, a sign() method if you want to sign your primary key with a cryptographic algorithm.

On the id field:

@Id
@GenericGenerator(name = "UUIDGenerator", type = UUIDGenerator.class) // type is the class we created above; name can be anything
@GeneratedValue(generator = "UUIDGenerator")
private String id;

Composite primary key

Sometimes no single field is unique enough to identify an entity — you combine two or more fields into a composite primary key. There are two ways to define one: with an @IdClass, or with an @Embeddable id.

1. Option with @IdClass

Assuming we have a Product entity:

@Entity
public class Product {
private String code;
private long number;
private String color;
// getters and setters
}

To generate a composite primary key, create a ProductKey class containing the fields that make up the key.

Note: with composite primary keys, equals and hashCode are mandatory, to define the uniqueness of the fields.

public class ProductKey implements Serializable {
private String code;
private long number;
// getters and setters
// equals and hashcode
}

Then tell JPA where the primary key is:

@Entity
@IdClass(ProductKey.class) // telling jpa where our id class is
public class Product {
@Id
private String code;
@Id
private long number;
private String color;
// getters and setters
}

Creating a Product now derives its primary key from both code and number:

try {
em.getTransaction().begin();
Product p1 = new Product();
p1.setCode("ABC");
p1.setNumber(10);
p1.setColor("Red");
em.persist(p1);
em.getTransaction().commit();
} finally {
em.close();
}

2. Embeddable id

Create the key the same way:

@Embeddable // this means we can plug our class into our entity
public class StudentKey implements Serializable {
private long number;
private String code;
// getters and setters
// equals and hashcode
}

Then specify it as the primary key on the Student entity:

@Entity
public class Student {
@EmbeddedId // insert our id from the embedded class
private StudentKey id;
private String name;
// getters and setters
}

Creating a Student instance:

try {
em.getTransaction().begin();
// we create our key first
StudentKey id = new StudentKey();
id.setCode("ABC");
id.setNumber(10);
Student s = new Student();
s.setId(id); // set our instance's id to the key
s.setName("Ernest");
em.persist(s);
em.getTransaction().commit();
} finally {
em.close();
}