Programming Tutorials

EJB 3 Entities

By: Michael Sikora, PACKT publishing in EJB Tutorials on 2008-11-26  

This is an extract from the book, EJB 3 Developer Guide from the 3rd Chapter on Entities published by PACKT publishing. Entities are classes that need to be persisted; their state is stored outside the application, typically in a relational database. Unlike session beans, entities do not have business logic other than validation. As well as storing such entities, we want to query, update, and delete them.

In JPA, any class or POJO (Plain Old Java Object) can be converted to an entity with very few modifi cations. The following listing shows an entity Customer.java with attributes id, which is unique for a Customer instance, and firstName and lastName.

package ejb30.entity;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Customer implements java.io.Serializable {
  private int id;
  private String firstName;
  private String lastName;
  public Customer() {}
  @Id
  public int getId() { return id; }
  public void setId(int id) { this.id = id; }
  public String getFirstname() { return firstName; }
  public void setFirstname(String firstName) {
  this.firstName = firstName;
  }

  public String getLastname() { return lastName;
  }

  public void setLastname(String lastName) {
	this.lastName = lastName;
  }
  
  public String toString() {
	  return "[Customer Id =" + id + ",first name=" +
	  firstName + ",last name=" + lastName + "]";
  }

}

The class follows the usual JavaBean rules. The instance variables are non-public and are accessed by clients through appropriately named getter and setter accessor methods. Only a couple of annotations have been added to distinguish this entity from a POJO. Annotations specify entity metadata. They are not an intrinsic part of an entity but describe how an entity is persisted or, as we shall see in Chapter 4, how an entity is related to other entities. The @Entity annotation indicates to the persistence engine that the annotated class, in this case Customer, is an entity. The annotation is placed immediately before the class definition and is an example of a class level annotation. We can also have property-based and fi eld-based annotations, as we shall see.

The @Id annotation specifi es the primary key of the entity. The id attribute is a primary key candidate. Note that we have placed the annotation immediately before the corresponding getter method, getId(). This is an example of a property-based annotation. A property-based annotation must be placed immediately before the corresponding getter method, and not the setter method. Where property-based annotations are used, the persistence engine uses the getter and setter methods to access and set the entity state.

An alternative to property-based annotations are field-based annotations. Note that all annotations within an entity, other than class level annotations, must be all property-based or all fi eld-based. The final requirement for an entity is the presence of a no-arg constructor.

Our Customer entity also implements the java.io.Serializable interface. This is not essential, but good practice because the Customer entity has the potential of becoming a detached entity. Detached entities must implement the Serializable interface.

At this point we remind the reader that, as throughout EJB 3, XML deployment descriptors are an alternative to entity metadata annotations.

Comparison with EJB 2.x Entity Beans

An EJB 3 entity is a POJO and not a component, so it is referred to as an entity and not an entity bean. In EJB 2.x the corresponding construct is an entity bean component with the same artifacts as session beans, namely an XML deployment descriptor fi le, a remote or local interface, a home or localhome interface, and the bean class itself. The remote or local interface contains getter and setter method definitions. The home or local interface contains definitions for the create() and findByPrimaryKey() methods and optionally other finder method definitions.

As with session beans, the entity bean class contains callback methods such as ejbCreate(), ejbLoad(), ejbStore(), ejbRemove(), ejbActivate(), ejbPassivate(), and setEntityContext().

The EJB 3 entity, being a POJO, can run outside a container. Its clients are always local to the JVM. The EJB 2.x entity bean is a distributed object that needs a container to run, but can have clients from outside its JVM. Consequently EJB 3 entities are more reusable and easier to test than EJB 2.x entity beans.

In EJB 2.x we need to decide whether the persistence aspects of an entity bean are handled by the container (Container Managed Persistence or CMP) or by the application (Bean Managed Persistence or BMP). In the case of CMP, the entity bean is defi ned as an abstract class with abstract getter and setter method defi nitions. At deployment the container creates a concrete implementation of this abstract entity bean class.

In the case of BMP, the entity bean is defined as a class. The getter and setter methods need to be coded. In addition the ejbCreate(), ejbLoad(), ejbStore(), ejbFindByPrimaryKey(), and any other fi nder methods need to be coded using JDBC.

Mapping an Entity to a Database Table

We can map entities onto just about any relational database. GlassFish includes an embedded Derby relational database. If we want GlassFish to access another relational database, Oracle say, then we need to use the GlassFish admin console to set up an Oracle data source. We also need to refer to this Oracle data source in the persistence.xml file. We will describe the persistence.xml fi le later in this chapter. These steps are not required if we use the GlassFish default Derby data source.

EJB 3 makes heavy use of defaulting for describing entity metadata. In this section we describe a few of these defaults. First, by default, the persistence engine maps the entity name to a relational table name. So in our example the table name is CUSTOMER. If we want to map the Customer entity to another table we will need to use the @Table annotation.

By default, property or fi elds names are mapped to a column name. So ID, FIRSTNAME, and LASTNAME are the column names corresponding to the id, firstname, and lastname entity attributes. If we want to change this default behavior we will need to use the @Column annotation as we shall see later in this chapter.

JDBC rules are used for mapping Java primitives to relational datatypes. So a String will be mapped to VARCHAR for a Derby database and VARCHAR2 for an Oracle database. An int will be mapped to INTEGER for a Derby database and NUMBER for an Oracle database.

The size of a column mapped from a String defaults to 255, for example VARCHAR(255) for Derby or VARCHAR2(255) for Oracle. If we want to change this column size then we need to use the length element of the @Column annotation.

To summarize, if we are using the GlassFish container with the embedded Derby database, the Customer entity will map onto the following table:

CUSTOMER ID INTEGER PRIMARY KEY FIRSTNAME VARCHAR(255) LASTNAME VARCHAR(255)

Most persistence engines, including the GlassFish default persistence engine, Toplink, have a schema generation option, although this is not required by the JPA specifi cation. In the case of GlassFish, if a flag is set when the application is deployed to the container, then the container will create the mapped table in the database. Otherwise the table is assumed to exist in the database.






Add Comment

* Required information
1000

Comments

No comments yet. Be the first!

Most Viewed Articles (in EJB )

Latest Articles (in EJB)