Introduction
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.
The EJB 3 specifi cation recognizes that many applications have the above
persistence needs without requiring the services (security, transactions) of an
application server EJB container. Consequently the persistence aspects of EJB 3
have been packaged as a separate specifi cation—the Java Persistence API (JPA).
JPA does not assume we have a container and can even be used in a Java SE
(Standard Edition) application.
Successful standalone object-relational mapping products such as open source
Hibernate and proprietary Oracle Toplink have implemented these persistence
technologies for a number of years. Creators of Oracle Toplink and Hibernate
have been infl uential in the development of the JPA specifi cation. So,
readers who are familiar with either Hibernate or Toplink will recognize
similarities between the JPA and those products. Furthermore, under the covers,
the GlassFish application server implements the JPA using Toplink and the JBoss
application server uses Hibernate. These are pluggable defaults however, so it
is possible to implement the JPA in GlassFish using Hibernate for example.
The JPA can be regarded as a higher level of abstraction sitting on top of JDBC.
Under the covers the persistence engine converts JPA statements into lower
level JDBC statements.
EJB 3 Entities
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 defi nition 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 fi eld-based annotations. We
show an example of these later in this chapter. Note that all annotations
within an entity, other than class level annotations, must be all
property-based or all fi eld-based.
The fi nal 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 defi nitions. The home or local interface contains
defi nitions for the create() and findByPrimaryKey() methods and optionally
other fi nder method defi nitions. 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 defi ned 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.
|