Defining keys

Frequently we need more than just a primary key. Starting from hibintro.v4.User we may want to add a property uidNumber adding a common requirement: On UNIX type operation systems each user does have both a unique login name (like goik) and a unique numerical value (like 123). We choose our primary key to be numeric ❷and the login name to become a second candidate key ❶:

package hibintro.v5;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
@Table(uniqueConstraints={@UniqueConstraint(columnNames={"uid"})}) ❶
public class User {

  int uidNumber;
  @Id ❷
  public int getUidNumber() { return uidNumber; }
  public void setUidNumber(int uidNumber) { this.uidNumber = uidNumber; }

  String uid;

  /**
   * @return The user's unique login name e.g. "goik"
   */
  @Column(nullable=false)
  public String getUid() { return uid; }

  /**
   * @param uid, See {@link #getUid()}.
   */
  public void setUid(String uid) { this.uid = uid; }

  ...
}

Notice the slight difference: The property uid may need a @javax.persistence.Column(nullable=false) annotation to become a candidate key. This is not automatically inferred by the javax.persistence.UniqueConstraint definition ❶. In contrast the property uidNumber is not being referenced by the preceding javax.persistence.Table annotation but annotated by javax.persistence.Id. Hence a nullable=false is not needed.

This is in accordance with DDL: Attributes composing a primary key must not allow NULL values but attributes only appearing in UNIQUE declarations may become NULL.

The resulting DDL reads:

CREATE TABLE User (
  uidNumber INT NOT NULL PRIMARY KEY,
  cname VARCHAR(255) NOT NULL,
  uid VARCHAR(255) NOT NULL UNIQUE
)