Monday, 20 August 2012

JPA Primary Keys, Composite and Unique

This post illustrates JPA entity key, be them unique or composite. The code examples are available from Github in the JPA directory.

Unique Key

An entity can used a simple key made of a unique field. The only requirement is to annotate this field with @Key. The set of allowed types for unique keys is:

  boolean Boolean
  byte Byte
  char Character
  int Integer
  long Long
  short Short

  String
  BigInteger
  BigDecimal

  @Temporal(TemporalType.DATE)
  java.util.Date
  java.sql.Date
  java.math.BigDecimal
  java.math.BigInteger

  // Don't - Not recommended
  double Double
  float Float

Generated Value Strategy

The @GeneratedValue annotation can be used to specify an id generation strategy via a GenerationType. A sequence name can be specified using the proper annotation property.

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private long id; 

Composite Key

Here is an example of a composite key:
/**
 * Composite key must implement Serializable
 * and must be public.
 */
@AutoProperty
public class CompositeKey implements Serializable {

    // Must be public or protected
    public String s;
    public long l;

    // Default public parameter-less
    // constructor is required
    public CompositeKey() { }

    // equals() must be implemented
    @Override
    public boolean equals(Object o) {
        return Pojomatic.equals(this, o);
    }

    // hashCode() must be implemented
    @Override
    public int hashCode() {
        return Pojomatic.hashCode(this);
    }

    @Override
    public String toString() {
        return Pojomatic.toString(this);
    }

}
Using @EmbeddedId:
@Entity
public class WithEmbeddedId {

    @EmbeddedId
    private CompositeKey id;

    private String data;

    // Setter & Getter

}
The entity needs to declare the composite key with @EmbeddedId.

Using @IdClass:
@Entity
@IdClass(CompositeKey.class)
public class WithIdClass {

    @Id
    String s;

    @Id
    long l;

    private String someData;

    public WithIdClass() { }

    // Setter & Getter

}
With @IdClass, the class must declare the @Id fields matching the composite key fields.