8.4. The Primary Key Class

The Primary Key class is necessary for entity beans only. It encapsulates the fields representing the primary key of an Entity Bean in a single object. If the primary key in the database table is composed of a single column with a basic data type, the simplest way to define the primary key in the bean is to use a standard Java class (for example, java.lang.Integer or java.lang.String). This must have the same type as a field in the bean class. It is not possible to define it as a primitive field (for example, int, float or boolean). Then, it is only necessary to specify the type of the primary key in the deployment descriptor:

<prim-key-class>java.lang.Integer</prim-key-class>

And, for container-managed persistence, the field which represents the primary key:

<primkey-field>accno</primkey-field>

The alternative way is to define its own Primary Key class, described as follows:

The class must be serializable and must provide suitable implementation of the hashcode() and equals(Object) methods.

For container-managed persistence, the following rules apply:

8.4.1. Primary Key Class Example

public class AccountBeanPK implements java.io.Serializable {
    public int accno;
    public AccountBeanPK(int accno) { this.accno = accno; }
    public AccountBeanPK() { }
    
    public int hashcode() { return accno; }
    public boolean equals(Object other) {
	...
    }
}

8.4.1.1. Special Case: Automatic Generation of Primary Keys Field

There are two ways to manage automatic primary keys with JOnAS. The first method is closer to the EJB specification (that is, an automatic PK is a hidden field, the type of which is not even known by the application). In the second method, the idea is to declare a typical PK CMP field of the type java.lang.Integer as automatic. These two cases are described below.

8.4.1.1.1. Method 1: Standard Automatic Primary Keys (from JOnAS 4.0.0)

In this case, an automatic PK is a hidden field, the type of which is not known by the application. All that is necessary is to stipulate in the standard deployment descriptor that this EJB has an automatic PK; you do this by specifying java.lang.Object as primkey-class. The primary key will be completely hidden from the application (no CMP field, no getter/setter method). This is valid for both CMP 2.x and CMP1 entity beans. The container will create an internal CMP field and generate its value when the Entity Bean is created.

8.4.1.1.1.1. Method 1 Example:

Standard deployment descriptor:

<entity>
  ...
  <ejb-name>AddressEJB</ejb-name>
  <local-home>com.titan.address.AddressHomeLocal</local-home>
  <local>com.titan.address.AddressLocal</local>
  <ejb-class>com.titan.address.AddressBean</ejb-class>
  <persistence-type>Container</persistence-type>
  <prim-key-class>java.lang.Object</prim-key-class>
  <reentrant>False</reentrant>
  <cmp-version>2.x</cmp-version>
  <abstract-schema-name>Cmp2_Address</abstract-schema-name>
  <cmp-field><field-name>street</field-name></cmp-field>
  <cmp-field><field-name>city</field-name></cmp-field>
  <cmp-field><field-name>state</field-name></cmp-field>
  <cmp-field><field-name>zip</field-name></cmp-field>

Address Bean Class extract:

// Primary key is not explicitly initialized during ejbCreate method
// No cmp field corresponds to the primary key
public Integer ejbCreateAddress(String street, String city,
     String state, String zip ) throws javax.ejb.CreateException {
  setStreet(street);
  setCity(city);
  setState(state);
  setZip(zip);
  return null;
}

If nothing else is specified and the JOnAS default CMP 2 database mapping is used, the JOnAS container generates a database column with the name JPK_ to handle this PK. However, it is possible to specify in the JOnAS-specific Deployment Descriptor the name of the column that will be used to store the PK value in the table. You can do this as follows using the specific <automatic-pk-field-name> element (this technique is necessary for CMP2 legacy and for CMP1):

JOnAS-specific deployment descriptor:

<jonas-ejb-jar xmlns="http://www.objectweb.org/jonas/ns" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.objectweb.org/jonas/ns 
  http://www.objectweb.org/jonas/ns/jonas-ejb-jar_4_0.xsd" >
<jonas-entity>
   <ejb-name>AddressEJB</ejb-name>
   <jdbc-mapping>
      <jndi-name>jdbc_1</jndi-name>
      <automatic-pk-field-name>FieldPkAuto</automatic-pk-field-name>
   </jdbc-mapping>
</jonas-entity>

8.4.1.1.2. Method 2: CMP Field as Automatic Primary Key (from JOnAS 3.3.x)

The idea here is to declare a typical PK CMP field of type java.lang.Integer as automatic. By doing this, the field will no longer appear in create methods and its value will be automatically generated by the container at the EJB instance-creation time. However, it is still a cmp field, with getter/setter methods, and is accessible from the application.

8.4.1.1.2.1. Method 2 Example:

In the standard deployment descriptor, there is a typical primary key definition:

<entity>
   ...
   <prim-key-class>java.lang.Integer</prim-key-class>
   <cmp-field><field-name>id</field-name></cmp-field>
   <primkey-field>id</primkey-field>

In the JOnAS-specific deployment descriptor, specify that this PK is automatic:

<jonas-entity>
   ...
   <jdbc-mapping>
   <automatic-pk>true</automatic-pk>