Defining the Primary Key Class

   

An entity object must have an associated primary key object. This isn't surprising given that an entity bean instance typically corresponds to a row in a relational database table. Even if you're using an entity bean to represent some other type of data, you still have to associate a primary key with each unique element of that data so the container can keep track of everything. Part of your job as a bean provider is to identify the primary key class for an entity bean within its deployment descriptor. This is true no matter which persistence management approach you choose.

Note

This section isn't intended to imply that all the data associated with an entity bean comes from a single table in a database. More often, an entity bean provides a coarse-grained representation of data from multiple associated tables. However, it's usually the case that a single table is central to the entity so that the association of a primary key is straightforward.


Just like the database tables to which they map, entity beans need to support primary keys that are defined either by a single field or by a combination of multiple fields. The difference isn't significant, but when you need to use a multiple-field key, you must do a little more work. The rest of this section looks at both approaches.

Using a Single-Field Key

It's common for a table's primary key to be a single field. Usually this field holds an integer value or a string that uniquely defines each row. When this is the case, defining the primary key for a corresponding entity bean is simple. You simply need to define the class that is used to store the primary key as part of the bean's deployment descriptor. You'll see more details about deployment descriptors in Chapter 6 and Chapter 7, but for now, here's how an integer primary key would be identified:

 <?xml version="1.0"?>  <!DOCTYPE ejb-jar PUBLIC    '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN'    'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>  <ejb-jar>    <enterprise-beans>      ...      <entity>        <ejb-name>EnglishAuction</ejb-name>        <local-home>com.que.ejb20.auction.model.EnglishAuctionHome</local-home>        <local>com.que.ejb20.auction.model.EnglishAuction</local>        <ejb-class>com.que.ejb20.auction.model.EnglishAuctionBean</ejb-class>        <persistence-type>Bean</persistence-type>        <prim-key-class>java.lang.Integer</prim-key-class>        <reentrant>False</reentrant>        ...      </entity>      ...    </enterprise-beans>    ...  </ejb-jar> 

As you can see, the prim-key-class element is used to identify an entity bean's primary key class by specifying its fully qualified name. The primary key class can be any legal RMI-IIOP value type, which mostly means that it must implement Serializable and it must not implement java.rmi.Remote . For example, you can use standard Java types, such as String , Integer , and Long , as a primary key.

If you're using container-managed persistence (CMP) with a single-field key, you also must identify the entity bean field that maps to the primary key using the primkey-field element:

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

The field you identify with primkey-field must be a container-managed field and it must be of the type specified by prim-key-class . Don't include primkey-field in your deployment descriptor if you're using bean-managed persistence (BMP) or you're using CMP with a multiple-field key.

Using a Multiple-Field Key

If you map an entity bean to a table whose primary key is composed or more than one field, you must declare a primary key class to represent the key in the entity bean. The class must follow the rules for RMI-IIOP value types, so you must declare it to implement Serializable and it can't implement java.rmi.Remote . The class must also provide appropriate implementations of the hashCode and equals methods . There are a few other rules to adhere to if you're using CMP (you should follow the first three for BMP as well):

  • A primary key class must be declared public .

  • A primary key class must declare a public , no-argument constructor.

  • All fields that make up the key in a primary key class must be declared public .

  • Each field name in a primary key class must exactly match one of the container-managed field names .

When you create a primary key class, you'll often be doing it to support a specific entity bean. You're also allowed to use the same primary key class for multiple beans if you want ” this is no different than using String or Integer for multiple classes.

Listing 5.9 shows an example of a primary key class that defines a two-field key. CarModelPK represents a key that could be used to uniquely identify a car model by its make and model.

Listing 5.9 CarModelPK.java “An Example of a Primary Key Class
 public final class CarModelPK implements java.io.Serializable {   public String make;    public String model;    private Integer myHashCode;    public CarModelPK() {   }    public CarModelPK(String make, String model) {     this.make = make;      this.model = model;    }    public String toString() {     return make + " " + model;    }    public int hashCode() {     if (myHashCode == null) {       // the components of a primary key are immutable        // so this only needs to be computed once        myHashCode = new Integer(make.hashCode() ^ model.hashCode());      }      return myHashCode.intValue();    }    public boolean equals(Object other) {     // always check for the same object in an equals method      if (this == other) return true;      // declaring the class as final makes this a fast comparison      if (!(other instanceof CarModelPK)) return false;      CarModelPK otherPK = (CarModelPK)other;      if (!make.equals(otherPK.make)) return false;      if (!model.equals(otherPK.model)) return false;      return true;    }  } 

Specifying the Primary Key at Deployment

Sometimes an entity bean has a natural primary key, but not always. For example, identifying a car by its make and model is intuitive, and so is identifying an employee by an employee number assigned by an HR department. However, many times a primary key is nothing but a unique number or string. Even though it's consistent with common practices, there's nothing natural about assigning an integer value to be the primary key for an auction. It gives you a unique way to identify an auction, but there's no real-world business meaning to it. When this is the case, it's possible to defer the choice of a primary key class to the deployer if you're using CMP.

Even if you assign a somewhat arbitrary primary key class to an entity bean, you should go ahead and specify it in the deployment descriptor if you know the type of key that will be stored in the database. That is, if you're using a sequence number as a primary key, you should go ahead and specify that the primary key class is Integer (or whatever integer type you decide on). The only time you might want to defer this choice is if you're not sure how the key will ultimately be implemented in the database or if you have to support multiple database types that use different keys. For example, if you have to support native sequencing with one database but unique strings with another, you can't specify a single key class that works in both situations. The solution here is to define the prim-key-class as Object and defer the final choice until deployment.

This approach is not without its drawbacks. When you defer the choice of your primary key class, you can't write code in your beans that depend on any specific primary key class behavior. This is also true for the clients that access your bean because the primary key exposed to them will be declared as Object as well. The actual subclass type isn't known until deployment, so no code can assume a particular choice.



Special Edition Using Enterprise JavaBeans 2.0
Special Edition Using Enterprise JavaBeans 2.0
ISBN: 0789725673
EAN: 2147483647
Year: 2000
Pages: 223

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net