Entity Beans

Entity Beans have been given a complete overhaul in EJB 3.0. Entity beans are plain Java objects that can be allocated with new and attached/detached/reattached to persistence storage. Entity beans are not remotable and must be access through the new javax.persistence.EntityManager service. JBoss's EJB 3.0 implementation is built on top of Hibernate.

O/R Mapping

First let's look at the example implementation of two related Entity beans. Order and LineItem. These two beans form a one to many relationship and automatic table generation is used to generate the database tables.

The EJB container determines the persistent properties by looking for all getter/setter method pairs. By default, all getter/setter methods will be treated as persistence properties.

Defining an Entity is easy. First, tag the class as an @Entity. In the minimum, you must at least define a primary key field using the @Id annotation.

   @Id @GeneratedValue
   public int getId()
   {
      return id;
   }

Annotations must be defined on the getter method. The above @Id annotation tells the container that id is the primary key property. The @GeneratedValue: that it should be automatically generated by the container.

Also, the create table name is specified using the @Table annotation

@Table(name = "PURCHASE_ORDER")

If the table name isn't specified it defaults to the bean name of the class. For instance, the LineItem EJB would be mapped to the LINEITEM table.

One to Many Relationship

The Order bean also defines a one to many relationship.

   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="order")
   public Collection<LineItem> getLineItems()
   {
      return lineItems;
   }

Generics must be used so that the container can determine the bean order is related to.

CascadeType.ALL specifies that when an Order is created, any LineItems held in the lineItems collection will be created as well (CascadeType.PERSIST). If the Order is delete from persistence storage, all related LineItems will be deleted (CascadeType.REMOVE). If an Order instance is reattached to persistence storage, any changes to the LineItems collection will be merged with persistence storage (CascadeType.MERGE).

FetchType.EAGER specifies that when the Order is loaded whether or not to prefetch the relationship as well. If you want the LineItems to be loaded on demand, then specify FetchType.LAZY.

The mappedBy attribute specifies that this is a bi-directional relationship that is managed by the order property on the LineItem entity bean.

Many to One Relationship

LineItem completes the bi-directional between Order and LineItem.

   @ManyToOne
   @JoinColumn(name = "order_id")
   public Order getOrder()
   {
      return order;
   }

The @JoinColumn specifies the foreign key column within the LineItem table.

EntityManager

The ShoppingCartBean allocates and stores all instances of Orders and LineItems. If you look at the example you can see that ShoppingCart interacts with Order as a plain Java object. It allocates it with new. It can pass the Order back to the client. The checkout() method actually stores it with persistence storage by using the required EntityManager service.

The EntityManager service is injected using field injection and the @PersistenceContext annotation.

   @PersistenceContext
   private EntityManager manager;

The EntityManager is central to EJB 3.0 as there are no homes. The EntityManager is used to do querying, creating, find by primary key, and removal of entity beans.

Building and Running

To build and run the example, make sure you have ejb3.deployer installed in JBoss 4.0.x and have JBoss running. See the reference manual on how to install EJB 3.0.
Unix:    $ export JBOSS_HOME=<where your jboss 4.0 distribution is>
Windows: $ set JBOSS_HOME=<where your jboss 4.0 distribution is>
$ ant
$ ant run

run:
     [java] Buying 2 memory sticks
     [java] 2004-10-06 22:12:44,131 INFO org.jboss.remoting.InvokerRegistry[main] - Failed to load soap remoting transpo
rt: org/apache/axis/AxisFault
     [java] Buying a laptop
     [java] Print cart:
     [java] Total: $3000.0
     [java] 2     Memory stick     1000.0
     [java] 1     Laptop     2000.0
     [java] Checkout

The INFO message you can ignore. It will be fixed in later releases of JBoss 4.0.

View the tables and rows

You can view the tables created by JBoss by going to the Hypersonic SQL service, scrolling down to the startDatabaseManager button and clicking it. A Hypersonic SQL window will be minimized, but you can open it up to look at the tables and do queries.

Jar structure

Persistence archives must have a META-INF/persistence.xml file. They can be packaged along with EJB-JARs or by themselves in an EAR. They can also be packaged in a WAR as well, but JBoss doesn't support his yet. See the packaging tutorial for more detail. Running the ant script above creates a JAR file within the deploy/ directory of JBoss. All that needs to be in that jar is your server-side class files and additionally, you will probably need to define a hibernate.properties file in the META-INF directory of the JAR. hibernate.properties is needed if you need to hook in a datasource other than JBoss's DefaultDS, or change the caching of Hibernate. See the EJB 3.0 reference manual and Hibernate reference manual for more details.f