JavaEJBAdvanced Container-Managed Persistence

Advanced Container-Managed Persistence


This material is from the book JBuilder Developer’s Guide , written by Saleem Siddiqui, Michael Landy, and Jeff Swisher, published by Sams Publishing.

© Copyright Sams Publishing. All rights reserved.


Using the EJB 1.1 specifications, container managed persistence beans were
not very powerful. In most cases, bean developers went quickly beyond the
capabilities of CMP and had to convert to use bean managed persistence.
Many developers shied away from using entity beans altogether. The EJB 2.0
quickly addressed many of these issues. This now allows the bean developer
to implement most persistence requirements using container managed persistence.
The four features that facilitate this are the following:

  • EJB query language

  • Finder methods

  • Relationship mapping of multiple entity beans

  • Business methods implemented within the home interface

The Enterprise JavaBeans Query Language

The Enterprise JavaBeans Query Language (EJB QL) specification defines
a query language to be used within finder methods of an entity bean with
container managed persistence. Rather than develop a completely new query
language, the specification is based on a subset of SQL92. The EJB QL gives
you the features to allow navigation over the relationships defined in an
entity bean's abstract schema.

Your EJB QL queries will be contained within your deployment descriptor
of the entity bean. The container will then translate these queries into
the target language of the underlying data store. For example, EJB QL will
be translated to true SQL for JDatastore. Using this translation
allows entity beans using container managed persistence to be portable.
In other words, the code is not tied to a specific type of data store or
application server vendor.

EJB Query Restrictions

EJB QL has a few restrictions:

  • Commenting is not supported within EJB QL.

  • Date and time values are always represented in milliseconds and contained
    within a Java long.

  • Container managed persistence does not support inheritance. In other
    words, you cannot compare two entity beans of different types with each
    other.

Query Syntax

An EJB QL query has three components associated with it: SELECT,
FROM, and WHERE. The SELECT and FROM
clauses are the only required portions of EJB QL; the WHERE clause
is optional. For example, SELECT OBJECT(e) FROM Employee e selects
all the instances contained within the Employee entity.

The SELECT component defines the values or objects that will be
returned by the created query. The return values can either be a local interface
or a remote interface contained within an entity. The FROM component
defines the scope of the query. It may declare one or more entities. Finally,
the WHERE component contains a conditional expression that restricts
the values retrieved by the query. As mentioned earlier, this portion of
the query is optional; it is normally required to meet most entity finder
requirements.

Examples Described

SELECT OBJECT(e) FROM Employee e

This method returns all the instances of employee contained within the
entity. In this case, we refer to the Employee entity with an alias
e to make the definition of the query shorter.

SELECT DISTINCT OBJECT(e) FROM Employee e WHERE e.empNo = ?1

The query returns an employee instance specified by an empNo.
This query is typically used to find an instance by either a primary key
or alternate key. The DISTINCT keyword can be used to remove duplicates
from the query but this should not happen if you are using a primary key.

SELECT DISTINCT OBJECT(e) FROM Employee e, IN (e.salaryHistory)
as s WHERE s.Country
= ?1

This query navigates to related beans using the defined relationship. The
e variable relates to the Employee entity bean, and the
s variable represents the related bean instances SalaryHistory.
The IN keyword specifies that SalaryHistory is a collection
of beans related to the Employee entity. The query then navigates
the relationship to identify all the salary histories within a specific
country.

SELECT DISTINCT OBJECT(e) FROM Employee e WHERE e.salary BETWEEN ?1
AND ?2

The employees whose salaries fall within a given range are returned. The
BETWEEN keyword returns all salaries within the given range. This
expression is useful when using range finder methods.

Expressions and Functions

Just like SQL92 specifications of which EJB QL specifications is a subset,
EJB QL describes the functionality of the expressions and functions. The
specification does not include a full list of functions like that of SQL92
but simply a subset that should fit most requirements (see Table 1).

Table 1 Expressions and Functions Contained Within EJB QL

Type

Description

Standard comparisons

Just like SQL, you have the operations =, >, >=, <, <=,
and <>.

Arithmetic

+, -, *, /

Logical

NOT, AND, OR

Between

The BETWEEN expression determines whether a value falls
within a range.

In

The IN expression determines whether a value is contained
within a given set.

Like

The LIKE expression evaluates whether a string matches a
pattern. For a single character wildcard, use _. To use a wildcard
that represents zero or more characters, use %.

Null

The NULL comparison expression evaluates whether an attribute
or set is null. This is not used to evaluate a null collection; we
use the EMPTY expression to evaluate collections.

EJB QL also includes several functions, both arithmetic and string, listed
in Table 2. Most EJB vendors, including Borland's Application Server,
allow you to define and implement your own custom functions.

Table 2 Functional Expressions

Function Syntax

Description

CONCAT(String, String)

Concatenate two strings together and return into a third.

SUBSTRING(String, start, length)

Return a substring based on the start and length passed in.

LOCATE(String, String [, start])

Locate a string within another and return its location.

LENGTH(String)

Return the length of a string.

ABS(number)

Return the absolute version of the number.

SQRT(double)

Return the square root of a number.

Finder Methods

The ability to find an entity is a key requirement of all entity beans.
The implementation of finder methods, within EJB specification 1.1, required
us to quickly move to bean managed persistence rather than use the simpler
container managed persistence beans. Using EJB QL in conjunction with finder
methods within a container managed persistent bean, you can meet most requirements
for finding an individual or collection of entities.

We'll continue to look at our Employee entity and add a more
complex finder other than findByPrimaryKey(). The requirement we
need to implement is the capability to find employees based on a salary
range. The following steps are required to build this finder method implementation:

  1. Right-click on the Employee entity and choose Add, Finder.
    The results of which display the finder editor.

  2. Add the finder properties required to accomplish the given task.

  3. Set the following properties (see Figure
    1):


  4. Figure 1
    Finder editor within the EJB Designer.

    • Method name: findBySalaryRange

    • Return type: java.util.Collection

    • Input parameters: int low, int high

    • Home interface: local home

    • Query: SELECT OBJECT(e) FROM Employee e WHERE e.Salary BETWEEN
      ?1 AND ?2

  5. Save and compile your project.

The deployment descriptor now contains the information for this finder
method (see Listing 1). When the bean is deployed to the container,
it translates the information contained within the deployment descriptor
EJB QL to standard SQL for JDatastore.

Listing 1 Portion of the Deployment Descriptor for Defining a Finder
Method with EJB QL

<query>
 <query-method>
  <method-name>findBySalaryRange</method-name>
  <method-params>
    <method-param>int</method-param>
    <method-param>int</method-param>
   </method-params>
 </query-method>
 <ejb-ql>SELECT OBJECT(e) FROM Employee e WHERE e.Salary 
BETWEEN ?1 AND ?2</ejb-ql>
</query>

Relationship Mapping

As stated earlier the introduction of relationships in EJB 2.0 specifications
makes a huge difference. These relationship mappings allow for not only
providing the mechanics for managing relationships, but also the capability
to model and implement complex business relationships with unidirectional
and bidirectional traversal.

Each entity bean typically is not isolated in itself; it relates to other
entities within our system. For example, the Employee entity we
have been working with relates to many other entities within our system
such as the salary history. To demonstrate relationships, we will start
with one-to-many and move to more complex relationships, such as many-to-many.

One-to-Many Relationships

We can use a simple example for a one-to-many relationship. Using the sample
database provided with JBuilder, each employee has a lengthy salary history
that we want to make available through the instance (see Figure
2).


Figure 2
Model of employee to salary history.

The process for creating this one-to-many relationship within JBuilder
is accomplished by using the EJB Designer. The relationship ultimately
is exposed via a local interface defined on the Employee entity
bean. Ultimately, you would access this local interface by way of a session
façade bean, but to make the example simple, we will use the remote
interface with a test client.

  1. Expand the EmployeeData source and verify that the SALARY_HISTORY
    table is contained within the source's definition.

  2. Right-click on the SALARY_HISTORY table and select Create
    Entity Bean. The bean then appears in the EJB Designer. Make sure
    that the version property is set to EJB 2.0 compliant.

  3. Creating an EJB relationship is accomplished by right-clicking on
    the parent entity. In this class, right-click on our Employee
    entity and select Add, Relationship. An arrow used to graphically
    represent our relationship appears within the EJB Designer.

  4. Drag the end of the relationship arrow onto the SalaryHistory
    entity.

  5. Select the newly created method that contains the relationship. The
    name assigned by JBuilder's EJB Designer is salaryHistory.

  6. The Relationship Property editor appears to allow you to change the
    behavior of the relationship (see Figure
    3).


  7. Figure 3
    Relationship Property editor for the Employee to SalaryHistory
    relationship.

  8. For the relationship properties, Multiplicity should be set to one-to-many,
    and Navigability should be set to unidirectional. The Navigability
    is set to unidirectional because it does not make sense to access
    Employee entity information through the SalaryHistory
    entity.

  9. Click on the Edit Table Reference button to open the Table Reference
    editor (see Figure 4). We will
    use this editor to provide the link/keys between the two entities.


  10. Figure 4
    Table Reference editor for the Employee to SalaryHistory
    relationship.

  11. Adding a relationship is important because it indicates all the important
    keys that define the relationship between parent and child entities.
    Double-click on the empNo in the Employee entity
    and drag it onto the empNo of the SalaryHistory
    entity. Click OK.

  12. You should have a new attribute that contains the relationship between
    the Employee and the employee's salary history. Using
    the property editor, shown in Figure
    3, make sure that the return type of the salaryHistory
    method within the Employee entity is java.util.Collection.

Many-to-Many Relationships

A many-to-many relationship appears frequently in relationship database
designs. It is usually implemented through the use of a resolution table
because most relational database servers do not support this many-to-many
relationship directly, although object modeling supports this relationship
well. Although we can create this same resolution entity within our container,
why not implement a many-to-many relationship that more accurately represents
our actual instances?

For example, our employee system contains a many-to-many relationship
implemented through a resolution table (see Figure
5).


Figure 5
Employee relational data model.

Let's now create a many-to-many relationship using the existing
employeeData source. The relationship will be exposed via local
interfaces of the Employee and Project entity beans.
To access these interfaces, we will use the local interfaces of the
beans created. The following tasks help us create the required relationships
and deployment descriptor for these entity beans:

  1. Right-click on the PROJECT table within the defined data
    module within the EJB Designer and select Create CMP 2.0 Entity
    Bean.

  2. Create the many-to-many relationship between the Employee
    and Project entity beans using the EJB Designer. This is
    accomplished by right-clicking on the Employee bean and
    selecting Add, Relationship; then drop the other end of the relationship
    on the Project entity.

  3. Select the newly created relationship entity called Project,
    and the relationship editor is created (see Figure
    6):


  4. Figure 6
    Relationship editor for a many-to-many relationship.

    • Relationship name: employee-project

    • Multiplicity: many to many

    • Navigability: bidirectional

    • Field name: project

    • Return type: java.util.Collection

    • Getters/setters: local

  5. Click on Edit Table Reference; this launches the Table Reference
    editor.

  6. Click on Add Cross Table (see Figure
    7). After you make the appropriate selections, the Add Cross
    Table button becomes available.


  7. Figure 7
    Table Reference editor to establish a many-to-many relationship.

  8. Select the EMPLOYEE_PROJECT table as the cross table (see
    Figure 8).


  9. Figure 8
    Table Reference editor to establish a many-to-many relationship using
    a cross table.

  10. Drag EMPLOYEE EMP_NO to the EMPLOYEE_PROJECT EMP_NO
    and drag EMPLOYEE_PROJECT PROJ_ID to PROJECT PROJ_ID
    (see Figure 9).

  11. Click OK and compile and save your project.


  12. Figure 9
    Build the relationship between the resolution table and the Employee
    and Project tables with the connected keys.

Home Business Methods

One of the new changes for the specification is the addition and support
for collection methods and business methods contained within the home
interface. For example, we might want to calculate the total current
salary of all employees. The process for building this is simple:

  1. Add a new method to the Employee entity bean calling it
    calculateTotalSalary.

  2. Enter the return type to be a java.math.BigDecimal
    and the target interface should be local home.

  3. Create another finder method with the following parameters:

    • Finder name: findAll

    • Return type: java.util.Collection

    • Parameter: leave empty

    • Method interface: local home

    • Query: SELECT OBJECT(e) FROM Employee AS e

  4. Create a select method with the following properties:

    • Select name: selectAll

    • Return type: java.util.Collection

    • Parameter: leave empty

    • Result type mapping: local

    • Query: SELECT OBJECT(e) FROM Employee AS e

  5. Most of the code for the Employee entity has been generated
    by the EJB Wizard. The piece we need to add is the implementation
    of CalculateTotalSalary.

  6. Locate the EmployeeBean class and double-click to view
    the source.

  7. Locate the ejbHomeCalculateTotalSalary() method in the
    class.

  8. Implement the method as follows:

  9.  public java.math.BigDecimal  ejbHomeCalculateTotalSalary() {
      float res = 0;
    
      try {
       java.util.Iterator iter = ejbSelectAll().iterator();
       while(iter.hasNext()){
        Employee emp = (Employee)iter.next();
        res = res + emp.getSalary().floatValue();
       }
      }
      catch (FinderException ex) {
       throw new javax.ejb.EJBException(ex);
      }
    
      return new java.math.BigDecimal(new Float(res).toString());
     }

About the Authors

Saleem Siddiqui is a technical architect and trainer with Dunn Solutions Group. He is also a Sun Certified Developer and a Borland Certified JBuilder Instructor. At Dunn, he provides consulting services and business application development.

Michael Landy is Director of Business Applications for Dunn Solutions Group directing the strategic solutions for clients.

Jeff Swisher is a technical manager for the Dunn Solutions Group business applications. He works as a programmer, trainer, architect, and instructional designer. He is a Sun Certified Java Developer and a Borland Certified Instructor in JBuilder.

Source of this material

This material is from Chapter 23: Developing Entity Beans from the book JBuilder Developer’s Guide (ISBN: 0-672-32427-X) written by Saleem Siddiqui, Michael Landy, and Jeff Swisher, published by Sams Publishing.

To access the full Table of Contents for the book.


Other Chapters from Sams Publishing:

Web Services and Flows (WSFL)

Overview of JXTA

Introduction to EJBs

Processing Speech with Java

The Java Database Control in BEA Weblogic

Databases and Tomcat

Working with JAX-RPC

Understanding Servlets


Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories