Establishing a Database Connection
In Bales' program, the constructor registered a driver and established a connection with the database. I have provided similar code, except with JDO it is necessary to construct instances of
Transaction for interacting with the database.
PersistenceManager is created and configured with a
PersistenceManagerFactory. One can place the properties needed to initialize the
PersistenceManager in a property file, which I have called
jdo.properties. The following lines can be placed in this property file:
javax.jdo.PersistenceManagerFactoryClass=vendors_pmf_class_name javax.jdo.option.ConnectionURL=jdbc:oracle:thin:@DAVESLAPTOP:1521:dave javax.jdo.option.ConnectionDriverName=oracle.jdbc.driver.OracleDriver javax.jdo.option.ConnectionUserName=scott javax.jdo.option.ConnectionPassword=tiger
The first property identifies a vendor-specific name of a
PersistenceManagerFactory class. Only this one property value must be changed to switch from one vendor implementation to another. The other properties are virtually identical to the values needed in Bales' program to initialize his JDBC driver and connection.
In the main method of Bales' program, he starts by updating the connection's type map, associating the Java class with its corresponding SQL user-defined type. This is not necessary with JDO. This registration code is automatically added to the
Person class by the enhancer and is executed when the class is first loaded into the JVM.
Making an Instance Persistent
The next step in the application is to create an instance of
Person. The code to initialize the
Person instance with data is identical in the two programs. To persist the
Person instance in the JDO application only requires a single line of code:
In Bales' program, it is necessary to reference the underlying table in the relational database. The developer is forced to deal with both the Java data model and the relational data model. There is an opportunity for trouble here if the wrong table is used. With JDO this is not necessary; the developer only needs to use the Java data model. This also makes the JDO application more portable, as it can work across many different database architectures.
Updating an Instance
The next step is to update the
Person instance. In JDO, if we have a reference to the
Person instance after committing a transaction, the identity of the referenced instance is maintained. If the reference is used in a new transaction, the identity is used to access the instance in the database. My code demonstrates this capability. To update the email address, we simply invoke the
When the transaction commits, any updates to objects get automatically propagated to the database without any coding by the developer necessary. Once again, the JDO code to perform the operation is a single line of code. Can it get any simpler than that? This one line of JDO code corresponds to 25 lines in Bales' program. Half of Bales' code here deals with committing the update to the database. The other half deals with issuing a query to access the instance. I could have performed a query in JDO; I demonstrate this later when we delete the instance. Many lines of code are necessary in Bales' program to set up SQL statements to be processed. None of these lines of code need to be written in a JDO application program. The same functionality is provided by the underlying JDO implementation if it is providing access to an SQL database. But by using the JDO API there is less work necessary for the application and no dependencies on the specific underlying database being used.
Printing Information About All Instances
The next step performed in the two applications is the printing of information about all of the
Person instances in the database. The two programs are fairly similar with this step. In JDO, you access an
Extent, which provides access to all of the instances of a class. You then use a standard
java.util.Iterator to iterate through each of the instances. With JDBC, you create a statement to perform a select on a table and you execute the query. It returns a
ResultSet, which has its own built-in methods to iterate through each instance.
Perhaps now would be a good time to raise a question concerning Bales' proposed solution. In JDO, within the context of a transaction, the
PersistenceManager guarantees that each unique instance in the database is represented just once in the application's memory. If the application performed several different queries or navigated from several different places in the data model and referenced the same instance in the database, the application would always get a reference to a single instance in memory.
It is extremely important for the application to have only a single copy of each instance from the database in a transaction. Otherwise, if distinct updates were made to the different copies of the same persistent instance, there is an issue of migrating these updates to the database. If each separate instance is written to the database, the same object in the database would get updated multiple times, and the last update made would have its values reflected in the database. Maintaining a single copy of each instance is a very valuable service provided by JDO's cache management architecture. It is not clear whether this is supported in the software being described by Bales.
Deleting the Instance
The final step in each program is the deletion of the
Person instance. My JDO application no longer has a reference to the specific
Person instance, so I have perform a query to access the instance. Once I have a reference to the
Person instance, again, only a single line is necessary to delete the instance.
When examining the two programs that delete the instance, another point of differentiation emerges. In Bales' program, it is not necessary to instantiate an instance of
Person in the application; a SQL delete operation performs the necessary action. In my JDO application, it appears that I first need to query the database and read a
Person instance into my application.
The underlying JDO implementation, however, may only need to instantiate the
Person instance and initialize the identity of the instance. Unless the application explicitly accesses a field of the instance, the implementation does not need to read the object's state from the database into the instance in memory.
Assessment of Alternative APIs
Bales claims in his conclusion that using JDBC with an object-relational technology is far simpler than using JDO. I am sorry, I just don't see it. With his JDBC program, the application must deal with two distinct data models: the Java object model and the relational data model. There is a lot of statement setup code in the JDBC application program that is not necessary in the JDO program. I do not see how the JDBC application is simpler. Nor do I understand his claims that JDO is "flawed" and a "workaround."
Bales boasts about Oracle's implementation of OR technology, claiming you can "have your cake and eat it, too" by being able to use either a relational or object view of the information. I can use a JDO implementation with Oracle8i or Oracle9i and get JDO's object view of the database, and I can also use Oracle's underlying SQL facilities to access the same data. My JDO software is portable across all object and relational databases. But my direct use of Oracle-specific features will only work with Oracle. Multiple vendors provide support for JDO on Oracle8i.
There is one final, major point I would like to make. This example of persisting a
Person object that has just six
String fields is taken directly from the article written by Dion Almaer. This was done to show a very simple use of JDO. But this is an extremely simple and trivial example; it does not demonstrate the powerful capabilities provided by JDO. Most object models have many inter-relationships among classes, represented by references and collections that model one-to-one, one-to-many, and many-to-many relationships. JDO directly supports such object model relationships.
JDO also supports inheritance relationships among classes. This includes references (or collections of references) where the referred instances may be of various different subclasses of a common base class. This use of polymorphic references is very common in object models and provides the extensibility mechanism employed in many object-oriented programs. JDO supports such polymorphic references in the database, and also supports references to interfaces. The use of these features with JDO is no more complex than the use of the simple
Strings found in this
I would like to see an example application that has the necessary JDBC code to support all of these modeling constructs. This will clearly demonstrate that JDO is simpler than JDBC for more realistic object models. Members of the JDO community have wanted someone to produce an article with such an example for quite some time to illustrate the differences between JDBC and JDO in supporting these more advanced modeling constructs. But so far, no one has been willing to produce it. Why? Because it would be a huge amount of work to get all of the cache management and object modeling capabilities (collections, inheritance, polymorphic references) implemented in JDBC. I assert that when you have such more realistic examples of Java object models, the JDO application will be substantially smaller and simpler than the corresponding JDBC.
To conclude, I would like to state that SQL is not bad; it does provide powerful relational capabilities that you will not find in the JDO API. It allows you to dynamically associate data via join operations and it supports projections, group-by operations, and many other capabilities useful in data analysis. But if you have Java object models or relationships among your classes, or if you use inheritance and other features supported by Java, JDO provides a very simple API to persist those object models in a wide variety of databases. I can run my JDO applications on top of a multi-user Oracle 8i or Oracle 9i database, taking advantage of its multi-user access capabilities. I can have my Java-centric view of the information with JDO. I can also go underneath the JDO API and directly use JDBC and SQL. In closing, Bales' JDO FUD is a dud.
- "Flawed JDO Points the Way to the Objectbase," by Don Bales, April 24, 2002.
- "Using Java Data Objects," by Dion Almaer, Feb. 6, 2002.
- "The Debate Over Java Data Objects," by Dion Almaer, Jan. 23, 2002.
Return to ONJava.com.