JOB (Java Object Base) is an object to relational mapping tool that works in conjunction with any EJB application server that can support stateless session beans. Here is a list of some of the key features of JOB:
- Deployable in any J2EE compliant application server. The J2EE server provides the transactional integrity, JDBC connection pool, and distributed computing support. All JOB does is map Java API calls to the database while your J2EE server of choice does the "heavy lifting" on the server side.
- Generates both a database definition (the CREATE TABLE/ALTER TABLE scripts) and Java source code from a single, very simple metadata specification. Foreign key constraints are added, but additional constraints can be added later by the developer.
- Supports multiple input formats. Currently supported formats are a "proprietary" XML-based JOB format and Rational Rose 2000 .mdl files. XMI is a likely supported input format in the future.
- Simple Java based API to the resulting data model is generated allowing the application developer to focus on the application and not on the database.
- Simple Tcl based API is generated. This interface is usable in both Jacl (the Java based Tcl interpreter) as well as the native version of Tcl. This allows you to very quickly write simple GUI based access to a database as well as opening up the database to all of the many extensions that Tcl supports.
- Can be used with any database that supports transactions and foreign keys through easy to write Database Adaptors (DBAs). Currently supported databases: PostreSQL and Oracle.
- Supports "disconnected" operation. That is, an application can interact with JOB for periods of time while not being connected to the database.
- Metadata is stored in the database and is accessible via the JOB Persistent Manager (PM) interface.
- Persistent objects are cached in the persistent manager to reduce database access. Supports a highly configurable means of invalidating the cache contents.
I wanted a simple-to-use O/R system that worked inside of a J2EE based application server. Container Managed Persistence (CMP), which is part of the EJB 1.1 specification, was not at all adequate. I found the version 2.0 of the specification, while a significant improvement over the 1.1 version, unnecessarily complicated to use. Furthermore, all versions of the CMP spec used entity beans as the underlying data access layer. Being that my experience was not good with entity beans (bad performance, proprietary features to get good performance, and just generally strange semantics of the spec, etc.) served to reduce my confidence in CMP as a viable O/R mapping system.
Other O/R mapping tools were made in the days before the J2EE specification had been realized, and as a result, often contain much code to do the heavy, server-side, lifting. While some of them have been retrofitted to work in the EJB world, there was still too much baggage in many of the other systems. And, oh, let's not forget that the commercial varieties of O/R mapping systems are very expensive (the ones I am aware of anyway).
Much of my work over the past several years has involved designing and implemementing application servers, O/R mapping systems, and code generators. I decided to take that background and write JOB.
J2EE based application servers were chosen for the server side support necessary for JOB's interaction with the database because they represent a standard way to write and deploy server side components. I find this to be a tremendous advantage over home grown, proprietary application servers. I also like having the ability to choose from a large number of application servers for the server side support. Combining the application server flexibility, with JOB's support for multiple databases, provides a very flexible solution for both development and deployment. For example, I have successfully used JOB in a PostgreSQL/Orion Server development environment while deploying the same application to an Oracle/Weblogic environment.
How to Use It
JOB provides a simple to learn metadata model, that can be easily represented using a variety of formats and a variety of tools. From the resulting data models, JOB generates both a DDL and a Java API. 80-90% of your interaction with the database can be done through that API without writing a single database query, thus greatly easing the development effort. For the remaining 10-20% JOB supports simple (and not so simple) query capabilities. Furthermore, for the situations where peformance is critical (large batch type jobs, reporting, etc.) you can access the database in anyway your particular database supports (it is afterall, just a database).
We will get into the details in a bit, but, for now, just think of the following steps:
That is the development cycle in a nutshell. Let's look at each of these steps in more detail...
- Draw a pretty picture (using a UML modelling tool). Or, if you don't have a UML modelling tool you will need to create an XML document describing your metadata.
- Generate the database and Java code (JOB comes with an Ant task that performs the generation step).
- Compile the resulting Java class files.
- Run the database scripts to create the database.
- Start writing the application.
1 - Design the Metadata Model
First of all, what is meta data? The textbook definition is "data about the data." For our purposes, a metadata model is basically just a set of entities (in a UML class diagram entities are usually called "classes"), attributes for each of those entities, and relationships between those entities.
The model (if you have trouble viewing the model with the applets, you can just view the diagram) that we will use for this example is a movie database. This is a fairly realistic model, one that I hope can support an interesting and nontrivial online movie database (and no I don't plan on competing with the Internet Movie Database). JOB takes that diagram and generates a database and a Java API. The only classes that you need to worry about are those that match the entity name exactly. In other words the Tcl and DataShell classes you can ignore.
Let's start with entities. I like the term entity because it is abstract. Other terms that can be used to describe the same thing (which we will use from time to time when the context is appropriate) are class and table. The term class is normally associated with UML class diagrams, whereas table is normally associated with a database. Because JOB really bridges both of these worlds the use of entity seems most appropriate.
Entities are simply made up of a name. The JOB naming convention for entities (and most other names) is that same as that for Java class names. That is, start the entity name with a capital letter, and if it is a multiword name, start each new word with a capital letter. Entities typically have singular names. I mention this because those of you coming from the database world are likely used to using plural names. The standard in JOB, however, is the opposite. So, for instance the entity names in our movie database are things like Movie, Person, and Award (as opposed to Movies, People, and Awards). When we get to associations we will see where and when the plural name comes into play.
Java Mapping for Entities
JOB entities get mapped to Java classes that extend the Persist class. The class name has the same name as the entity.
Database Mapping for Entities
JOB entities get mapped to database tables. The table name has the same name as the entity but with underbars between words. So, for example OneTwoThree in the Rose model becomes One_Two_Three in the database. As we'll see when it comes to generation, you can also specify a prefix that gets prepended to all table names so that naming conflicts can be avoided.
Attributes are the traits that we associate with each entity. Each attribute has a name and a data type associated with it. The attribute name follows the same convention as the entity name. That is, it should start with a capital letter and each new word should start with a capital letter.
The following types are allowed:
||Java String class
||Medium size VARCHAR
||Java String class
||Large size VARCHAR
||Java Date class
||A date type capable of storing time information
||Java primitive int type
||Some sort of number type
||Java primitive long type
||Some sort of number type
||Java primitive float type
||Some sort of number type
||Java primitive double type
||Some sort of number type
||Java primitive boolean type
||A single character that is either 'T' for
true or 'F' for
Entities can have any number of attributes. Each attribute name must be unique. Currently, you must also avoid the following names as attributes:
- <Entity Name>Id. This is because JOB creates an implicit database column for the primary key that follows the same naming convention.
- <Role Name>Fkid. JOB creates an implicit database column for the each foreign key implied by the relationships (see below for the discussion on relationships).
- ObjectVersionNum. JOB creates a column called ObjectVersionNum to ensure data integrity.
- LastModifiedTime. JOB creates a column called LastModifiedTime to give a timestamp the last time the row/object was updated.
Java Mapping for Attributes
JOB attributes get mapped to Java class fields. Each field has the same name as the JOB attribute and the type as specified in the above table.
Each attribute also gets a pair of accessor methods: one for read access to the attribute and other for write access. The reason you should start your attribute names with a capital letter is becaues JOB simply tacks on a "get" or "set" to the beginning of the attribute name to derive the Java accessor method name.
Database Mapping for Attributes
Attributes in the JOB metamodel get converted to database table columns. The names follow those for entities/tables, but in the case of attributes/columns the optional prefix is not added.
The database column types get mapped as outlined in the above table.
JOB does not directly support many-to-many relationships. But you can do what you would likely do in the database world: create an intersection table. That is, you put another table between
Appendix A -- JavaDoc API
For futher reference the JavaDoc is available.