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

advertisement

AddThis Social Bookmark Button

Flawed Understanding of JDO Leads to FUD
Pages: 1, 2, 3

Example Application

I will now discuss my experiences of reviewing Bales' program and my development of an equivalent program with JDO. Bales' first step is to create a user-defined type (UDT) using a SQL CREATE TYPE command and then create an associated object table. It is not necessary to provide these underlying datastore data definitions using most JDO implementations. Many of the JDO implementations automatically generate these data definitions for the Java application. If there is an existing set of tables, implementations provide a means to define the mapping between your Java object model and the underlying database.



Next Bales introduces a Person class. It is necessary for his class to import other classes from java.io and java.sql. His class needs to implement the SQLData interface, using SQLInput and SQLOutput streams. In JDO, it is not necessary to import such types or implement the methods that marshal and demarshal the object. I used his program as the starting point for my implementation of the program in JDO. The definition of his data members included the following:

private String = name;
private String = address;
private String = ssn;
// etc.

Another problem I discovered was the following method definition:

public void setEmail(String Email) {
  this.email = email;
}

I discovered this when my email address seemed to always be set to null. The reason for this is that the name of the parameter (Email) is not being assigned to the field itself. These two pieces of code prevent his program from being compiled and tested successfully. The equivalent JDO application that I provide here has been compiled and tested.

The Persistent Class Person

The following class, Person, is the class to be stored in the database. This is the same class defined in Bales' article, with the above corrections made and also removing code not necessary when using JDO.

package onjava;
public class Person {
  private String name;
  private String address;
  private String ssn;
  private String email;
  private String home_phone;
  private String work_phone;
 
  public Person() {
  }
  // Accessors
  public String getName() {
    return name;
  }
  public String getAddress() {
    return address;
  }
  public String getSsn() {
    return ssn;
  }
  public String getEmail() {
    return email;
  }
  public String getHomePhone() {
    return home_phone;
  }
  public String getWorkPhone() {
    return work_phone;
  }
  // Mutators
  public void setName(String name) {
    this.name  = name;
  }
  public void setAddress(String address) {
    this.address  = address;
  }
  public void setSsn(String ssn) {
    this.ssn  = ssn;
  }
  public void setEmail(String email) {
    this.email  = email;
  }
  public void setHomePhone(String homePhone) {
    home_phone  = homePhone;
  }
  public void setWorkPhone(String workPhone) {
    work_phone  = workPhone;
  }
}

Bales' Person class was 78 lines long. The class defined above has the same functionality in only 50 lines. The savings comes from the fact that with JDO I do not need to provide the methods readSQL, writeSQL, and getSQLTypeName. As Bales notes himself, this code is tedious. It could also be error-prone. With a JDO implementation, this same functionality is automatically generated for my class. So the same functionality is necessary, but with JDO this code is generated for the application, reduces the developer's workload, and avoids error-prone code.

The Enhancer and Metadata

Specifically, the code is added by an enhancer directly to my .class file. The enhancer is given the file Person.class and a JDO metadata file that lists the persistent classes and any other persistence-related information not expressible in Java. For this very simple schema, the metadata is trivial:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE jdo SYSTEM "jdo.dtd">
<jdo>
  <package name="onjava" >
    <class name="Person" />
  </package>
</jdo>

The enhancer adds the code necessary to provide transparent persistence of the class, including methods needed to migrate data between the object and the database. The JDO enhancement contract for performing this is designed in such a manner that the code placed in my class is portable and will work with any JDO implementation. The resulting .class file is vendor-neutral.

The Application

Below I provide the application program that performs the same operations as provided in the DemonstrateOR program written by Bales.

package onjava;
import javax.jdo.*;
import java.util.*;
import java.io.*;
/**
A program to demonstrate JDO
*/
public class DemonstrateJDO {
    PersistenceManager pm;
    Transaction tx;
 
public DemonstrateJDO() {
    PersistenceManagerFactory pmf = null;
    try {
        InputStream propStream =
                      new FileInputStream("jdo.properties");
        Properties props = new Properties();
        props.load(propStream);
        pmf = JDOHelper.getPersistenceManagerFactory(props);
    } catch(Exception ex){
        System.out.print("Error creating PMF");
        System.out.println(ex);
        System.exit(1);
    }
    pm = pmf.getPersistenceManager();
    tx = pm.currentTransaction();
}
 
public static void main(String[] args)
               throws Exception {
    new DemonstrateJDO().process();
}
 
public void process(){
    Person person = null;
    // Insert a person object
    try {
      // create a new instance
        person  = new Person();
        person.setName("Bales, Donald J.");
        person.setAddress("Downers Grove, IL 60516");
        person.setSsn("999-99-9999");
        person.setEmail("balesd@compuserve.com");
        person.setHomePhone("(999) 999-9999");
        person.setWorkPhone("(999) 999-9999");
        tx.begin();
        pm.makePersistent(person);
        tx.commit();
    }
    catch (JDOException e) {
      System.err.println("JDO Error: "+e.getMessage());
      System.exit(1);
    }
 
    // Update the object using standard JDO
    try {
        // Let's change my email address
        tx.begin();
        person.setEmail("don@donaldbales.com");
        tx.commit();
    }
    catch (JDOException e) {
        System.err.println("JDO Error: "+e.getMessage());
        System.exit(1);
    }
 
    try {
        // Print the Persons in the database
        tx.begin();
        Extent persons = pm.getExtent(Person.class,true);
        Iterator personIter = persons.iterator();
        while( personIter.hasNext() ){
            person = (Person) personIter.next();
            System.out.println("name:       " +
                    person.getName());
            System.out.println("address:    " +
                    person.getAddress());
            System.out.println("ssn:        " +
                    person.getSsn());
            System.out.println("email:      " +
                    person.getEmail());
            System.out.println("home phone: " +
                    person.getHomePhone());
            System.out.println("work_phone: " +
                    person.getWorkPhone());
        }
        persons.close(personIter);
        tx.commit();
    }
    catch (JDOException e) {
      System.err.println("JDO Error: "+e.getMessage());
      System.exit(1);
    }
 
    // Delete the person
    try {
        tx.begin();
        Extent persons = pm.getExtent(Person.class,true);
        Query query = pm.newQuery(persons,
                               "ssn == \"999-99-9999\"");
        Collection rslt = (Collection) query.execute();
        Iterator iter = rslt.iterator();
        person = (Person) iter.next();
        query.close(rslt);
        pm.deletePersistent(person);
        tx.commit();
    }
    catch (JDOException e) {
      System.err.println("JDO Error: "+e.getMessage());
      System.exit(1);
    }
  }
 
  protected void finalize()
   throws Throwable {
    if (pm != null)
      try { pm.close(); }catch (JDOException ignore){ }
    super.finalize();
  }
}

Once again, the JDO program is smaller. DemonstrateOR is 197 lines of code, my DemonstrateJDO program is 119 lines. Not only is the JDO program smaller, it also seems simpler to me. But deciding which program is simpler is likely a subjective opinion. You can decide for yourself which program is easier to understand.

Pages: 1, 2, 3

Next Pagearrow