ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Object-Relational Mapping with Apache Jakarta OJB

by Charles Chan
01/08/2003

As enterprise applications become more complex, it becomes more challenging to map their object models to relational database tables. In typical J2EE applications, developers use EJB entity beans as the abstraction for the underlying object store. Unfortunately, entity beans, as of EJB 2.0, have limited mapping capabilities. For example, custom data conversions (such as from Currency objects to Strings) and component inheritance (Manager is an Employee) are not directly supported. When the object models require these features, developers have to write and maintain extra code. Even so, the results are often not satisfactory.

Fortunately, there are alternatives. These persistence frameworks allow developers to map normal Java objects to relational tables with minimal effort. The Java standard for such a framework is called JDO (Java Data Objects), and it is maturing. Unfortunately, there is no complete, free implementation of JDO today. This makes evaluating this emerging technology more difficult. However, with some planning and the use of best practices, it is not difficult to develop your application prototype with a non-standard persistence framework, later switching to an industrial-strength JDO implementation if it suits your business.

Three of the most popular persistence frameworks in the open source community are Hibernate, Castor, and OJB. In this article, we will focus on OJB. OJB integrates smoothly into J2EE containers with full support of JTA and JCA, and is a viable alternative to EJB entity beans. Since OJB does not modify your source code or byte code in any way, you can make an object persistent even without access to the original source code. This article introduces OJB and focuses on its component-inheritance capabilities. The Appendix presents some best practices to show you how to decouple your application from the specifics of a persistence layer.

Related Reading

Java Enterprise Best Practices
By The O'Reilly Java Authors

1. Obtaining OJB

OJB can be downloaded from the Apache Jakarta Project home page. We will use version 0.9.7, the latest as of this writing, throughout this article. As a member of the Jakarta family, OJB makes extensive use of the Jakarta Commons Library. This is good news to everyone who is already familiar with the Commons library through other Jakarta projects like Struts.

Installation is a snap. You only need to unzip the downloaded file into any directory and you are ready to go.

2. Component Inheritance

Component inheritance represents an "IS-A" relationship between two objects in the object store. EJB entity beans do not directly support component inheritance. You can mimic the relationship in entity beans by creating a one-to-one relationship, delegating all base class getters and setters to the base class entity bean. Unfortunately, this is only a halfway solution, because EJB finders cannot return the proper object type.

To showcase the component inheritance feature of OJB, we will use an example throughout this section. We will walk you through the entire process of creating and running this example to help you understand the steps involved. The example attempts to persist two objects: Manager and Employee. They are related by a "IS-A" relationship. See Figure 1 below.

Employee and Manager classes

Figure 1: The Employee and Manager classes

2.1 Interfaces

Example 1: Component Inheritance Example Interfaces

public interface Employee
{
    public String getName();
    public void setName(String name);
}

public interface Manager extends Employee
{
    public Integer getProjectNumber();
    public void setProjectNumber(Integer projectNumber);
}

The first step in our example is to create interfaces for our object model. It is always a good idea to have interfaces for your object model because interfaces allow your implementations to evolve without causing breakage in other areas of your system. This is especially true for objects in the persistence layer. For example, a version timestamp is used to support object versioning in the persistence layer. It is important in the persistence layer, but not so in the business layer. Using interfaces allow you to change the object versioning scheme without breaking the business layer.

Using interfaces also allows you to switch the underlying persistence framework with mininal effort.

2.2 Base Class Implementation

After the interfaces are done, we are ready for the implementation. Since different mapping techniques require slightly different implementations (see next page), a base class implementation will be helpful to house the common functionalities.

Example 2: Base Class Implementation

public class BasePersistenceObjectImpl
{
    private Integer id;

    public BasePersistenceObjectImpl()
    {
        super();
    }

    public Integer getId()
    {
        return id;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    public boolean equals(Object o)
    {
        if (o == this)
        {
            return true;
        }
        else if (o != null && o instanceof BasePersistenceObjectImpl)
        {
            return ((BasePersistenceObjectImpl) o).id.equals(this.id);
        }
        else
        {
            return false;
        }
    }
}

Pages: 1, 2, 3

Next Pagearrow