How does the Container handle entity bean fields that are references to other entity beans?

In RDBMSs, associations take the form of foreign keys. It is possible for any of your CMP fields to correspond to a foreign key field in the corresponding table. At the EJB code level, these foreign key CMP fields can be surfaced as object references.

As an example, let's say you have an address table and it has a reference to the country table:

create table address (
    addr_id             number(10),
    addr_street1        varchar2(40),
    addr_street2        varchar(40),
    addr_city           varchar(30),
    addr_state          varchar(20),
    addr_zip            varchar(10),
    addr_co_id          number(4)       * foreign key *
);

create table country (
    co_id               number(4),
    co_name             varchar2(50),
    co_exchange         number(8, 2),
    co_currency         varchar2(10)
);

You map them to entities in this way:

public class Address extends EntityBean {
  public int id;
  public String street1;
  public String street1;
  public String city;
  public String state;
  public String zip;
  public Country country; // this is a direct pointer to the Country
  // etc.
}

public class Country extends EntityBean {
  public int id;
  public String name;
  public int exchange;
  public String currency;
  // etc.
}

The reference is an EJBObject reference not a direct Java reference to the implementation Bean.

Then, using the deployment descriptor, you can hook up the reference Address.country to the JNDI name of CountryHome. A further explanation of this is provided in the pigs example.

The container optimizes this cross-entity reference to be pretty much as fast as just storing the value of the foreign key. Two important differences are:

  • You don't have to call CountryHome.findByPrimaryKey(addresss.country) to get the Country object corresponding to the country id.
  • The state of the Country entity bean is only loaded when you actually use it. For example, loading in an Address object does not actually load in a Country object. Think of the Country field in Address as a "lazy" reference, which only loads in its corresponding state when the object is used. (This "lazy" behavior actually comes free of charge via the EJB model.) The life-cycle of Address.country is decoupled from the life-cycle of the Address bean instance itself simply by virtue of the EJB model. Address.country is a normal entity bean EJBObject reference and thus the state of Address.country is only loaded when (and if) it is used. Likewise, the state of AddressBean.country is controlled as any other EJBObject is.

Also, note that we changed the CMP field names to be more Java-friendly (for example, the SQL column "address.addr_city" maps to the Java field "Accress.city"). This too is achieved via the deployment descriptor. For example:

            <env-entry>
                <env-entry-name>ejb.cmp.jdbc.column:city</env-entry-name>
                <env-entry-type>String</env-entry-type>
                <env-entry-value>addr_city</env-entry-value>
            </env-entry>

Java programmers certainly prefer "normal" field names.