Using Java Data Objects

Using Java Data Objects

Step Two: Persist Three "People" to the Database

Here we have some real meat. The persistPeople() method creates three people, using the constructor that we saw in the Person.java file. Then we see JDO at work. The first thing we do is get a persistence manager via getPersistenceManager(). Then we create a transaction where we will do our work (and we commit that work after we do it). To persist this object graph we simply call the makePersistentAll( Object[] ) method. The for() loop at the bottom of the code gets the unique ID for the persistent objects, and saves them away for later use.



public void persistPeople() {

  // create an array of Person's

  people = new Person[SIZE];



  // create three people

  people[0] = new Person("Gary Segal", "123 Foobar Lane", 

              "123-123-1234", "gary@segal.com", 

              "(608) 294-0192", "(608) 029-4059");

  people[1] = new Person("Michael Owen", 

              "222 Bazza Lane, Liverpool, MN", 

              "111-222-3333", "michael@owen.com", 

              "(720) 111-2222", "(303) 222-3333");

  people[2] = new Person("Roy Keane", 

              "222 Trafford Ave, Manchester, MN", 

              "234-235-3830", "roy@keane.com", 

              "(720) 940-9049", "(303) 309-7599)");



  // persist the array of people

  pm = pmf.getPersistenceManager();

  transaction = pm.currentTransaction();

  pm.makePersistentAll(people);

  transaction.commit();



  // retrieve the object ids for the persisted objects

  for(int i = 0; i < people.length; i++) {

    id.add(pm.getObjectId(people[i]));

  }



  // close current persistence manager to ensure that 

  // objects are read from the db not the persistence 

  // manager's memory cache.

  pm.close();

}

Here are some of the other methods that you can call on the persistence manager. The three categories are:

  • Make instances persistent. Take a transient object and persist it.
  • Delete persistent instances. Delete the information from the datastore.
  • Make instances transient. Disassociate the instances from the persistence manager. The datastore doesn't have its information deleted.
Make instances persistent Delete persistent instances Make instances transient
makePersistent(Object o) deletePersistent(Object o) makeTransient(Object o)
makePersistentAll(Object[] os) deletePersistentAll(Object[] os) makeTransientAll(Object[] os)
makePersistentAll(Collection os) deletePersistentAll(Collection os) makeTransientAll(Collection os)

Step Three: Display the "People" From the Database

Our display code starts by getting the persistence manager (as all the code will do). We use the object IDs that we saved in the persistPeople() method above to give us our object back. Once we have our object, we can call the methods that the object implements -- in this case gets to give us our data back. At this point you are probably seeing there isn't a lot of code needed to persist your objects.

public void display(int end) {

  Person person;

  int max = end <= SIZE ? end : SIZE;



  // get a new persistence manager

  pm = pmf.getPersistenceManager();

  // retrieve objects from datastore and display

  for(int i = 0; i < max; i++) {

	 person = (Person) pm.getObjectById(id.elementAt(i), 

                                       false);

	 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());

  }

  pm.close();

}

Step Four: Change the Name of One of the People

The code to change a Person that exists in the datastore is simple, too. It should look very similar to the code to display the "people." Here we are creating a transaction (since we are modifying the row), changing the name using the setName() method that we defined, and finally, committing the transaction to save the changes back. The only real difference between this operation and working with transient objects is that we are thinking about transactions.

public void change() {

  Person person;



  // retrieve objects from datastore

  pm = pmf.getPersistenceManager();

  transaction = pm.currentTransaction();

  // change DataString field of the second persisted object

  person = (Person) pm.getObjectById(id.elementAt(1), 

                                     false);

  person.setName("Steve Gerrard");

  // commit the change and close the persistence manager

  transaction.commit();

  pm.close();

}

Step Five: Delete a Person

Could you have guessed the code needed to delete the second person from the datastore? You know all of the information. Looking at the code below you will see that we are using the deletePersistent() method mentioned in the persistence manager methods in Step Two.

public void delete() {

  // retrieve objects from datastore

  pm = pmf.getPersistenceManager();

  transaction = pm.currentTransaction();

  // delete the 2nd persisted object from the datastore and

  // its id from Vector id.

  pm.deletePersistent(pm.getObjectById(id.remove(1), 

                      false));

  // commit the change and close the persistence manager

  transaction.commit();

  pm.close();

}

Step Five: Run Through These Things in the main() method

Finally, this program has a main() to run through, persist the people, change one, and then delete it. If you run this, you will see the address book displayed at each point.

public static void main(String[] args) {

  System.out.println("Create PersonPersist");

  PersonPersist personPersist = new PersonPersist();



  System.out.println("Setup and persist a group of people");

  personPersist.persistPeople();



  System.out.println("Display the persisted people");

  personPersist.display(SIZE);



  System.out.println("Change a name ");

  personPersist.change();

  personPersist.display(SIZE);



  System.out.println("Delete a person ");

  personPersist.delete();

  personPersist.display(SIZE - 1);

}

JDOEnhancer: Create a JDO Descriptor for the JDOEnhancer

We now have all the code for our application. The next step that we need is to create a JDO descriptor that the JDOEnhancer will use. "What is the JDOEnhancer?", I hear you scream. The JDO architecture is built with the idea that a JDO implementation can take the bytecode for your classes and manipulate them to add needed functionality. For example, the JDOEnhancer will make the class implement the PersistanceCapable interface (so you don't have to), and may implement some of the methods in that interface. So we will see that after we compile our code, we will have to run the JDOEnhancer to do the bytecode manipulation (this is something that Thought Inc. doesn't like about JDO). We need to create a descriptor file that gives information about the classes that we wish to persist. The file looks like this:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE jdo SYSTEM 

"file:/D:/Apps/OpenFusionJDO/xml/schema/jdo.dtd">

<jdo>

   <package name="addressbook">

      <class name="Person" identity-type="datastore">

      </class>

   </package> 

</jdo>

This is a basic file, but works for our needs. There is more complicated mapping available, and you can check the spec at Section 18: XML Metadata. Here is a slightly more complex mapping from the OpenFusion examples:

<class name="Department" identity-type="datastore">

<field name="name"/>

<field name="employees">

<collection element-

type="com.prismt.j2ee.jdo.examples.appKeyDepartment.Employee">

</collection>

</field>

<field name="manager"/>

</class>

</package>

</jdo>

Now that we have the code and the JDO descriptor, let's put it all together and see how to build the system.

Build: Go Through the Steps to Build and Run the System

There are only a couple of steps to build the system that we have created:

  1. Compile the code.
  2. Run the JDOEnhancer.
  3. Set up the database (using output from the JDOEnhancer).
  4. Run the application.

Step One: Compile the Code

We all know how to run javac right? We just have to make sure that we set up the CLASSPATH correctly before we run it. Here is an example running Windows:

% set OPENFUSION_DIR=D:\Apps\OpenFusionJDO

% set 

CLASSPATH=%OPENFUSION_DIR%\lib\connector.jar;%OPENFUSION_DIR%\

lib\jndi.jar;%OPENFUSION_DIR%\lib\log4j.jar;%OPENFUSION_DIR%\l

ib\xerces.jar;%OPENFUSION_DIR%\lib\classes12.zip;%OPENFUSION_D

IR%\lib\jdo.jar;%OPENFUSION_DIR%\lib\jta-

spec1_0_1.jar;%OPENFUSION_DIR%\lib\ofjdo.jar;.



% javac d . Person*.java

Step Two: Run the JDOEnhancer

The JDOEnhancer takes the compiled code that we just created and the JDO descriptor file that we built previously. Here is the full syntax of the OpenFusion JDOEnhancer:

java com.prismt.j2ee.jdo.enhancer.JDOEnhancer



Mandatory Options:

-cp	base directory to begin searching for classes to be 

         enhanced. This is not the CLASSPATH, just where our 

         compiled persistent classes are

-oc	directory to place the enhanced classes

-pd	JDO descriptor file(s)



Optional:

-db	specific target database [oracle, sybase, etc]	

-od	directory to generate SQL scripts to

Here is an example of running the JDOEnhancer for our application:

% java com.prismt.j2ee.jdo.enhancer.JDOEnhancer -oc . -pd 

person.jdo -db oracle -od db -cp .

Step Three: Set Up the Database (Using Output From the JDOEnhancer)

The JDOEnhancer can create database scripts to set up the database for us, as long as we give it the db and od switches. It will create lots of separate scripts, but one will be called load_all.sql. Open that file and load it into your favorite SQL prompt (e.g., sqlplus for Oracle).

Take a peek at the Oracle version that is created for our application:

CREATE SEQUENCE instid_seq INCREMENT BY 1

;



CREATE TABLE JDO_addressbook_Person_SCO

(

    inst_id INTEGER NOT NULL,

    class INTEGER NOT NULL,

    JDO_address VARCHAR2(255),

    JDO_email VARCHAR2(255),

    JDO_homePhone VARCHAR2(255),

    JDO_name VARCHAR2(255),

    JDO_ssn VARCHAR2(255),

    JDO_workPhone VARCHAR2(255)

)

;

CREATE TABLE JDO_addressbook_Person

(

    inst_id INTEGER NOT NULL,

    class INTEGER NOT NULL,

    JDO_address VARCHAR2(255),

    JDO_email VARCHAR2(255),

    JDO_homePhone VARCHAR2(255),

    JDO_name VARCHAR2(255),

    JDO_ssn VARCHAR2(255),

    JDO_workPhone VARCHAR2(255)

)

;

CREATE  TABLE prismjdoProp

(

    name VARCHAR2(255) PRIMARY KEY,

    value VARCHAR2(255)

)

;

CREATE TABLE prismjdoExtents

(

    class_id NUMBER(38,0) PRIMARY KEY,

    class_name VARCHAR2(255) UNIQUE,

    app_key VARCHAR2(255)

)

;

ALTER TABLE JDO_addressbook_Person_SCO ADD PRIMARY KEY 

(inst_id, class)

;

ALTER TABLE JDO_addressbook_Person ADD PRIMARY KEY (inst_id, 

class)

;



INSERT INTO prismjdoExtents VALUES(0, 'addressbook.Person', 

'com.prismt.j2ee.jdo.spi.DBKey')

;

COMMIT WORK

;



INSERT INTO prismjdoProp VALUES('USE.RDBMS.TRIGGERS', 'true')

;

COMMIT WORK

;

Step Four: Run the Application

Now the database is set up; we can run the application and see it roll!

% java addressbook.PersonPersist

Grab the code and try it out!

Conclusion

We have shown how to work with the new JDO standard, using the OpenFusion JDO implementation. This is a new world, where developers can focus on their business needs and work with objects without having to be SQL gurus. I hope JDO takes off, even though some people in the industry think that the spec isn't quite there yet.

Dion Almaer is a Principal Technologist for The Middleware Company, and Chief Architect of TheServerSide.Com J2EE Community.


Return to ONJava.com.

Prev  [1] [2] 

Close    To Top
  • Prev Article-Java:
  • Next Article-Java:
  • Now: Tutorial for Web and Software Design > Java > JDOnJDBCnSQLJ > Java Content
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Geek Tutorial
     

    Blogging Tutorial

      RSS Tutorial
      Podcasting Tutorial
    Graphic Design Tutorial
      Coreldraw Tutorial
      Illustrator Tutorial
      3D Tutorials
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial/ Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial/ Articles
     

    XML Style

      AJAX Tutorial
      XML Mobile
    Flash Tutorial/ Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial/ Articles
      Linux Tutorial
      Symbian Tutorial
      MacOS Tutorial
    Personal Tech
      Hardware Tutorial
      Software Tutorial
      Online Auction