Table of Contents

Preface
Installation
Example
Step 1: Create database
Step 2: Business Model
Step 3: File descriptor
Identities
Step 4: Compile and enhance
Step 5: Create database schema
Step 6: The DAO class
Step 7: Execute the application
References

Preface

Java Data Objects (or JDO in short) is a new specification that handles Java objects' storage to any DBMS transparently to the application and the developer. It is the new standard way to interact with any kind of database (RDBMS, ORDBMS, OODBMS, filesystem) without thinking of the specifics of each database. The developer only designs their business model, and it is JDO's task to map it to the database of choice.This standard allows Java developers to use their object model as a data model, too. There is no need to spend time going between the "data" side and the "object" side.

Various products -- including CocoBaseCastor JDO, iBatis and Hibernate -- try to do this for you. However, now thaat there is a standard way to do this, we get the benefit of  having to learn only one way to do it. This is just like when JDBC came along and allowed us to work with any database that provided a driver. JDO seems to be the next step to JDBC and eventually developers will use JDO in place of JDBC to access databases.

JDO is now in version 2.0 (JSR 243) with many new additions and enhancements. Advantages:

In the following, we describe the creation of a simple Java application that uses JDO to store persistent objects to a RDBMS. You can download the source code from here.Check the available JDO implementations, commercial and non-commercial, too.

Installation

We shall need the following tools:

You will need the following jars:

Create the following folder structure:

jdo example directory structure
Figure 1. Tutorials' folders

Copy the above libraries to lib folder. We 'll create the rest of configuration files shown in the figure later. You may also download the full source code from here.

Example

We will create a small application of an electronic bookstore in order to demonstrate JDO in action. MySQL will be the datastore. I will not go in details on how to you use MySQL or how you
create databases in general, but only what is required for our example case study. 

A client user should be to search from a list of books or CDs, search book items using keywords, order books etc. The tradesman should be able to store new book arrivals, modify or erase books etc. In order to make the example more interesting and investigate more of the possibilities of JDO, we will use classes that are related with various relations (e.g. inheritance).

The steps to develop using JDO are the following:

  1. Create the database: this is the only step not handled by JDO;
  2. Business model: Create the classes that we wish to persist in the database;
  3. File descriptor: Write file descriptor that describes how the class attributes are stored in fields of tables of the database;
  4. Compile and enhanceCompile and enhance business model objects, by using JDO Enhancer;
  5. Database schema: Create the database schema (there is no standard way among implementations regarding this step);
  6. DAO: Create of a Data Access Object (DAO) class to manage persistent objects;
  7. Build: Go through the steps to build and run the program.

Step 1: Create the database

Create a new database. (You can do that either from command line or by using one of the GUI interfaces to MySQL that exist, like Mascon from Scibit, or MyCC from MySQL, or MySQL Navigator. Otherwise, open a DOS (in Windows) or Command (in Linux) prompt and start mysql by issuing the command mysql (or mysql -u user); note that mysql must be in your path to be able to execute this command; if it is not, then go inside [MySQL installation]\ bin and run the command mysql). Up to MySQL version 4, you can create a database without issuing a username or password if you prefix the database name with the word 'test' (this has changed from version 4.1 and on however). Go on and create the database test_bookstore_db.

 mysql> create database test_bookstore_db

That's all you need to do if you are using JDO. JDO deals with the rest of the details! Isn't this awsome?

Step 2: Business model 

First, we need to create our domain model. This is described in the following UML class diagram and is derived from JPOX's basic tutorial:

jdo model
Figure 2. UML class diagram of our business model

These should follow JavaBeans' rules, i.e. there should be a default constructor (this is required by any PersistenceCapable class, and the class will fail the enhancing step if this is not present)  and have getXXX() and/or setXXX() methods for the properties of the class.
List 1. Product.java
/**********************************************************************
Copyright (c) 01-Nov-2003 Andy Jefferson and others. All rights reserved.
This program and the accompanying materials are made available under the
terms of the JPOX License v1.0 which accompanies this distribution.
Contributors:  
John N. Kostaras (20-Oct-2005)
**********************************************************************/
package org.jpox.tutorial.model;
/**
 * Definition of a Product
 * Represents a product, and contains the key aspects of the item.
*

 
* @version $Revision: 1.2 $ 
 
**/
public class Product {
   /**
   
* Product id. Primary key
    **/
   
protected long id;
    /**
    
* Name of the Product.
    
**/
   
protected String name=null;
    /**
    
* Description of the Product.
     **/
   
protected String description=null;
    /**
    
* Value of the Product.
    
**/
   
protected double price=0.0;
   
/**
    
* Default constructor.
    
**/
   
protected Product()
{
   
}
    /**
* Constructor.
     * @param name name of product
     * @param description description of product
     * @param price Price
     **/
    public Product(String name, String description, double price) {
        this.name           = name;
        this.description    = description;
        this.price          = price;
    } 
    // -------------------------Accessors --------------------
    /**
     * Accessor for the name of the product.
     * @return  Name of the product.
     **/
    public String getName() {
        return name;
    }
    /**
* Accessor for the description of the product.
     * @return  Description of the product.
     **/
    public String getDescription() {
        return description;
    }
    /**
     * Accessor for the price of the product.
     * @return  Price of the product.
     **/
    public double getPrice() {
        return price;
    } 
    // ---------------------------Mutators ---------------------
    /**
     * Mutator for the name of the product.
     * @param   name   Name of the product.
     **/
    public void setName(String name) {
        this.name = name;
    }
    /**
     * Mutator for the description of the product.
     * @param description Description of the product.
     **/
    public void setDescription(String description) {
        this.description = description;
    }
    /**
     * Mutator for the price of the product.
     * @param price price of the product.
     **/
    public void setPrice(double price) {
        this.price = price;
    }
}
List 2. Book.java
/**********************************************************************
Copyright (c) 01-Nov-2003 Andy Jefferson and others.All rights reserved.
This program and the accompanying materials are made available under the
terms of the JPOX License v1.0 which accompanies this distribution.
Contributors:
    ...
**********************************************************************/
package org.jpox.tutorial.model;
/**
 * Definition of a Book. Extends basic Product class.
 *
 * @version $Revision: 1.2 $
 **/
public class Book extends Product {
    /**
     * Author of the Book.
     **/
    protected String  author=null;
    /**
     * ISBN number of the book.
     **/
    protected String  isbn=null;
    /**
     * Publisher of the Book.
     **/
    protected String  publisher=null;
    /**
     * Default Constructor.
     **/
    protected Book() {
        super();
    }
    /**
     * Constructor.
     * @param name name of product
     * @param description description of product
     * @param price Price
     * @param author Author of the book
     * @param isbn ISBN number of the book
     * @param publisher Name of publisher of the book
     **/
    public Book(String name,
                String description,
                double price,
                String author,
                String isbn,
                String publisher) {
        super(name,description,price);
        this.author     = author;
        this.isbn       = isbn;
        this.publisher  = publisher;
    }
    // ------------------------------- Accessors --------------------
...

    // ------------------------------- Mutators ---------------------
       ...
}

Save the two files inside src/org/jpox/tutorial/model, as declared in the package line of the classes.

Note that there is an inheritance association between the two classes; some objects are of class Product and others of class Book. This allows us to extend our store in the future to sell e.g. DVDs.

Step 3: File descriptor 

Next, we need to define which of the classes attributes will be persisted. We do this by defining an XML metadata file, which is called file descriptor. This file describes the attributes that are to be persisted to the datastore. In other words, the file descriptor maps the class attributes to database fields.

The file descriptor is an .xml file that ends with .jdo. It complies with jdo_2_0.dtd. We can either create a single .jdo file for each class to be persisted or a package.jdo file which describes all persistent classes. We prefer the second solution.

List 3. package.jdo
<?xml version="1.0"?>
    <!DOCTYPE jdo PUBLIC "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"     "http://java.sun.com/dtd/jdo_2_0.dtd">
<jdo>
    <package name="org.jpox.tutorial.model">       
       <class name="Product" identity-type="
application">
         <inheritance strategy="new-table"/>
         <field name="id" primary-key=”true” value-strategy="autoassign"/>
         <field name="name" persistence-modifier="persistent">
             <column length="100" jdbc-type="VARCHAR"/>
         </field>
         <field name="description" persistence-modifier="persistent">
              <column length="255" jdbc-type="VARCHAR"/>
         </field>
         <field name="price" persistence-modifier="persistent"/>
       </class>
       <class name="Book" identity-type="application"
         persistence-capable-superclass= "org.jpox.tutorial.Product">
          <inheritance strategy="new-table"/>
          <field name="author" persistence-modifier="persistent">
              <column length="40" jdbc-type="VARCHAR"/>
          </field>
          <field name="isbn" persistence-modifier="persistent">
              <column length="20" jdbc-type="CHAR"/>
         
</field>

          <field name="publisher" persistence-modifier="persistent">
                <column length="40" jdbc-type="VARCHAR"/>
            </field>
        </class>
    </package>
 </jdo>

Save the above file as package.jdo inside src/org/jpox/tutorial/model

<jdo> tag defines this file as a JDO descriptor. <package> tag defines the package name inside which the persistent classes reside (it's good practice to put all persistent classes inside the same package). <class> tags define the persistent classes. Under this tag we define the attributes that are to be stored to the database.Not all attributes of a class need to be mapped to database fields. For each attribute, we define its datatype when it is not obvious how to map to a database type. E.g. attribute "name" is defined to be of type "VARCHAR" and length = "100"; however we don't need to define this explicitly for attribute "price" which is of type int and JDO maps it by default to an Integer field. 

Inheritance is declared in the line:

<class name="Book" identity-type="application"
         persistence-capable-superclass="org.jpox.tutorial.Product">

persistence-capable-superclass declares that class Book inherits from class Product.

Identities

Another thing we must make clear is identity-type. There are two basic identity types: application identity and datastore identity.  With datastore identity you are leaving the assignment of id's to JDO. Your class will not have a field for this identity - it will be added to the datastore representation by JPOX. A new column will be added to the respective table in the datastore that will serve the purpose of a surrogate key.

<class name="MyClass" identity-type="datastore">
</class>

This is the default value of identity-type hence it may be missing.

With application identity your application is taking control of the specification of id's. Application identity requires a primary key class, and each persistent capable class may define a different class for its primary key, and different persistent capable classes can use the same primary key class, as appropriate. If your primary key consists of one attribute only, JDO 2 provides an easier solution: just define this attribute to be primary-key=”true”:

<class name="MyClass" identity-type="application" objectid-class="MyIdClass">
<field name="myPrimaryKeyField" primary-key="true"/>
...
</class>

In list 3, we have declared attribute id of class Product to be a primary key and the database to autoassign key values to it, e.g. by declaring it's type as autonumber.

<field name="id" primary-key=”true” value-strategy="autoassign"/>

We could declare isbn to be the primary key, but what if a book's ISBN is not available?

But when and why do we declare identity-type= “application and whendatastore? If we wish to have full control about Book objects, e.g. if we wish to fetch a book given it's id (or primary key), then we should use application identity because this is the only way to associate an id to a specific book. With datastore identity, control of identities is on the datastore side and we cannot always associate a specific book with it's id; in that case we need to know other criteria that uniquely identify it (e.g. ISBN).

Step 4: Compile and enhance

It's time to compile and enhance our classes. JDO requires that your classes implement PersistenceCapable interface. You could write the methods required in order for your classes to become  PersistenceCapable. Alternatively, you may use a JDO enhancer which enhances your compiled classes by adding the necessary methods for them to become PersistenceCapable.

JPOX provides a bytecode JDO enhancer to enhance your classes in order to be able to be used by any JDO implementation. Use jpox-enhancer.jar located inside lib folder. Figure 1 should now contain:

src/java/org/jpox/tutorial/model/package.jdo
src/java/org/jpox/tutorial/model/Book.java
src/java/org/jpox/tutorial/model/Product.java
lib/jdo.jar 
lib/jpox.jar
lib/jpox-enhancer.jar
lib/log4j.jar
lib/bcel.jar

 Create the following properties file (list 4) and save it in the location shown in Figure 1:

List 4. jpox.properties

javax.jdo.PersistenceManagerFactoryClass=org.jpox.PersistenceManagerFactoryImpl
javax.jdo.option.ConnectionDriverName=com.mysql.jdbc.Driver
javax.jdo.option.ConnectionURL=jdbc:mysql://localhost:3306/test_bookstore_db
javax.jdo.option.ConnectionUserName=root
javax.jdo.option.ConnectionPassword=
 
org.jpox.autoCreateSchema=true
org.jpox.validateTables=false
org.jpox.validateConstraints=false

JDO uses this file to connect to MySQL database. The source code contains log4j.properties used by log4j and build.xml used by ant.

Open a command line window, navigate to the project's home directory, (build.xml should be there) and type the command ant. If everything went smoothly, the following class files should have been created. If the "other scenario" took place, check jpox-enhancer.log.

build/org/jpox/tutorial//model/package.jdo
build/org/jpox/tutorial/model/Book.class
build/org/jpox/tutorial/model/Product.class

build.xml has been configured in order to compile and then enhance the classes so that JPOX can work with them.

<project name="tutorial" default="enhance" basedir=".">

Step 5: Create database schema

If there are no errors, then type the command ant createschema for JPOX to create your database schema! Open test_bookstore_db in MySQL to view the tables that JPOX has created.

database schema

Figure 3 Database test_bookstore_db schema

Step 6: The DAO class

The last step is to create the class that handles the persistent objects. We call this class DAO (Data Access Object) according to [5], but you may call it any name you want.

Classes DAO, PersistenceManagerHelper and Main are shown in lists 5-7. Save them under src/org/jpox/tutorial/ and compile them typing ant to a command prompt. To run the program, type  ant run.

List 5. DAO.java
package org.jpox.tutorial;
import javax.jdo.Extent;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
import java.util.Collection;
import java.util.Vector;
import org.jpox.tutorial.model.*;

/**
  * Data Access Object that handles all JDO transactions with the db storage.<br>
  *
  * @author John Kostaras
  * @version 1.0 $23/10/2005 @ 6:11:40 μμ$
  */
class DAO {
   DAO() {
   }

/**
  * Persist <code>Product</code>.
  *
  * @param product to save
  * @since JDO 1.0
  */
static void save(Product product) {
   PersistenceManager pm = PersistenceManagerHelper.getPersistenceManager();
   try {
      Transaction tx = pm.currentTransaction();
      tx.begin();
      pm.makePersistent(product);
      tx.commit();
   } catch (Exception ex) {
      System.err.println(ex);
   } finally {
      if (pm.currentTransaction().isActive()) {
         pm.currentTransaction().rollback();
      }
      pm.close();
   }
}

/**
  * Retrieve <code>Product</code> by <code>id</code>.
  *
  * @param id of product to retrieve
  * @return Product
  * @since JDO 2.0
  */
static Book load(long id) {
  PersistenceManager pm = PersistenceManagerHelper.getPersistenceManager();
  Book book = null;
  try {
     Transaction tx = pm.currentTransaction();
     tx.begin();
     book = (Book) pm.getObjectById(Book.class, new Long(id));
     tx.commit();
  } catch (Exception ex) {
     System.err.println(ex);
  } finally {
     if (pm.currentTransaction().isActive()) {
         pm.currentTransaction().rollback();
     }
     pm.close();
  }
  return book;
}

/**
  * Retrieve <code>Product</code>s by <code>filter</code>, i.e. products that satisfy the
  * conditon.

  *
  * @param filter condition to use, e.g. price < 50.00
  * @param order can be "ascending", "descending" or "no order"
  * @return Collection of <code>Product</code>s
  * @since JDO 1.0
  */
static Collection load(String filter, String order) {
  PersistenceManager pm = PersistenceManagerHelper.getPersistenceManager();
  Vector products = new Vector();
  try {
     Transaction tx = pm.currentTransaction();
     tx.begin();
     Extent extent = pm.getExtent(Product.class, true);
     Query q = pm.newQuery(extent, filter);
     q.setOrdering(order);
     Collection results = (Collection) q.execute();
     products.addAll(results);
     q.closeAll();
     tx.commit();
  } catch (Exception ex) {
     System.err.println(ex);
  } finally {
     if (pm.currentTransaction().isActive()) {
         pm.currentTransaction().rollback();
     }
     pm.close();
  }
  return products;
}

/**
  * Delete a <code>Product</code>.
  *
  * @since JDO 2.0
  */
static void delete(long id) {
  PersistenceManager pm = PersistenceManagerHelper.getPersistenceManager();
  try {
    Transaction tx = pm.currentTransaction();
    tx.begin();
    Book book = (Book) pm.getObjectById(Book.class, new Long(id));
    if (book != null)
       pm.deletePersistent(book);
       tx.commit();
    } catch (Exception ex) {
       System.err.println(ex);
    } finally {
       if (pm.currentTransaction().isActive()) {
           pm.currentTransaction().rollback();
       }
       pm.close();
    }
}

/**
  * Delete all <code>Product</code>s.
  *
  * @since JDO 2.0
  */
static void deleteAll() {
  PersistenceManager pm = PersistenceManagerHelper.getPersistenceManager();
  try {
    Transaction tx = pm.currentTransaction();
    tx.begin();
    Extent extent = pm.getExtent(Product.class, true);
    Query q = pm.newQuery(extent);
    long deletedCount = q.deletePersistentAll();
    System.out.println("Objects deleted: " + deletedCount);
    tx.commit();
  } catch (Exception ex) {
    System.err.println(ex);
  } finally {
     if (pm.currentTransaction().isActive()) {
         pm.currentTransaction().rollback();
     }
    pm.close();
  }
}

/**
  * Load all <code>Product</code>s.
  *
  * @return Collection of <code>Product</code> descriptions
  * @since JDO 2.0
  */
static Collection loadAll() {
  Vector names = new Vector();
  PersistenceManager pm = PersistenceManagerHelper.getPersistenceManager();
  try {
    Transaction tx = pm.currentTransaction();
    tx.begin();
    Query q = pm.newQuery(Product.class);
    q.setResult("name");
    Collection results = (Collection) q.execute();
    names.addAll(results);
    q.closeAll();
    tx.commit();
  } catch (Exception ex) {
    System.err.println(ex);
  } finally {
     if (pm.currentTransaction().isActive()) {
         pm.currentTransaction().rollback();
     }     
     pm.close();
  }
  return names;
}  
}
List 6. PersistentManagerHelper.java
package org.jpox.tutorial;
import java.io.InputStream;
import java.io.IOException;
import java.util.Properties;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.JDOHelper;

/**
  * Utility singleton class that returns a PersistenceManager.
  * @version 1.0 $12/8/2005$
  * @author John Kostaras
  */
public class PersistenceManagerHelper {
    private static PersistenceManagerFactory pmfSingleton = null;
  private PersistenceManagerHelper() { }
/**
  * Utility method to create a PersistenceManager
  * @return The PersistenceManager
  **/
  public static final PersistenceManager getPersistenceManager() {
    PersistenceManagerFactory pmf;
    if (pmfSingleton == null) {
       // Get an instance of the PersistenceManagerFactory via JDOHelper.
       pmf = JDOHelper.getPersistenceManagerFactory(getProperties());
       pmfSingleton = pmf;
    } else {
       pmf = pmfSingleton;
    }
    // Retrieve a PersistenceManager from the PersistenceManagerFactory.
    return pmf.getPersistenceManager();
  }

/**
  * Read <code>jpox.properties</code>.
  * @return Properties or null if properties file not found
  **/
  private static final Properties getProperties() {
    Properties props = new Properties();
    InputStream stream = PersistenceManagerHelper.class.getResourceAsStream("/jpox.properties");
    try {
      props.load(stream);
      return props;
    } catch (IOException e) {
      e.printStackTrace();
      return null;
    } finally {
      if (stream != null) {
      try {
        stream.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
 }
}

Step 7: Execute the application

List 7. Main.java
/**********************************************************************
Copyright (c) 23-Oct-2005 John Kostaras
**********************************************************************/
package org.jpox.tutorial;

import java.util.Collection;
import java.util.Iterator;

import org.jpox.tutorial.model.*;

/**
 * Main class for the JPOX Tutorial.<br>
 * Relies on the user defining a file jpox.properties to be in the CLASSPATH
 * and to include the JDO properties for the JPOX PersistenceManager.
 *
 * @version 1.0 $
 **/
public class Main {
    public static void main(String args[]) {        
    
    DAO.deleteAll();
       
        // Persist a Product and a Book.
        Product product = new Product("iPod","MP3 player and storage by Apple",249.00);
        Book book = new Book("Core J2EE Patterns: Best Practices and Design Strategies", "2nd Edition (2003)",49.99,"Alur D., Crupi J., Malks D. ", "12345678", "Prentice Hall PTR");        
    DAO.save(product);
    DAO.save(book);       

       // Basic Extent
    System.out.println("Products in bookstore");
    System.out.println("=====================");
    Collection products = DAO.loadAll();
        Iterator iter = products.iterator();        
        while (iter.hasNext()) {
            String productDescription = (String)iter.next();
            System.out.println("Product : " + productDescription);
        }
       
        // Perform some query operations
    products = DAO.load("price < 60.00", "price ascending");    
        iter=products.iterator();
        while (iter.hasNext()) {            
            product = (Product)iter.next();            
        System.out.println(">  " + product.getName());
    }
    }
}

The program's output must be similar to:

C:\jdo-tutorial> ant run
Buildfile: build.xml
run:
[java] javax.jdo.JDOUserException: Deletion by query is not yet supported f
or JDOQL queries.
[java] Products in bookstore
[java] =====================
[java] Product : iPod
[java] Product : Core J2EE Patterns: Best Practices and Design Strategies
[java] > Core J2EE Patterns: Best Practices and Design Strategies
BUILD SUCCESSFUL
Total time: 2 seconds

Let's begin from class Main. To store a persistent object to the datastore is obvious. In class Main we created two objects of type Product and Book and we saved them to the database by calling static method save() of DAO class.  All JDO interactions with the database requires an instance of PersistenceManager class. Hence, the first thing to do is to retrieve a PersistenceManager from a factory class. PersistenceManagerHelper.getPersistentManager() (list 6) returns a single PersistenceManager object for the whole application by applying the Singleton design pattern [6].  Method PersistenceManagerHelper.getProperties() loads the required jpox.properties property file.
Then, we need to get the current transaction from PersistentManager object. A transaction starts with a begin() and ends with a commit() or rollback().

Class DAO (list 5) provides static methods for storing, deleting and retrieving persistent objects. Saving a persistent object is simple:

Transaction tx = pm.currentTransaction();
tx.begin();
pm.makePersistent(product);
tx.commit();

Hence, the steps to use JDO are:

  1. retrieve a PersistenceManager from a PersistenceManagerFactory
  2. get the current transaction from PersistentManager object
  3. Issue a begin to start a transaction
  4. process the results
  5. Commit or rollback the transaction
To modify a persistent object's attribute and reflect this change to the database, simply do the following:

Transaction tx = pm.currentTransaction();
tx.begin();
book.setDescription("This book has been reduced in price!");
tx.commit();

We may simply retrieve a persistent object if we know its primary key (or id) by the following piece of code:


Transaction tx = pm.currentTransaction();

tx.begin();
Βook book = (Book) pm.getObjectById(Book.class, new Long(id)); //id=1
tx.commit();

To retrieve all products stored in the datastore, make use of an Extent:


Transaction tx = pm.currentTransaction();
tx.begin();
Extent extent=pm.getExtent(Product.class,true);
Query q=pm.newQuery(extent);
Collection results=(Collection)q.execute();
products.addAll(results);
q.closeAll();
tx.commit();

pm.getExtent(Product.class,true) first parameter returns all objects of Product.class while the second, if true retrieves all persistent objects from classes that inherit from Product, too (i.e. Book objects); if false, then only objects of class Product are retrieved.

We may also provide criteria to our queries, in order to filter the results, e.g. retrieve all books that cost less than 50€:


Transaction tx = pm.currentTransaction();
tx.begin();
Extent extend=pm.getExtent(Product.class,true);
Query q=pm.newQuery(extend, "price < 50.00");
q.setOrdering(price ascending);
Collection results=(Collection)q.execute();
products.addAll(results);
q.closeAll();
tx.commit();

If we are certain that only a single object can be the result of a query, (or none), then we can use q.setUnique(true):


Transaction tx = pm.currentTransaction();
tx.begin();
Query q = pm.newQuery(Book.class, "name == bookName");
q.declareParameters("String bookName");
q.setUnique(true);
Book book = (Book) q.execute(bookName); // π.χ. bookName = “iPod”
q.close(book);
tx.commit();

Class Extent returns a collection of Objects. There are cases, though, where we want to retrieve a specific database table field, or else, a single object attribute. JDO 2.0 allows us to define the attribute we wish to return using q.setResult():


Transaction tx = pm.currentTransaction();

tx.begin();
Query q = pm.newQuery (Product.class);
q.setResult("name");
Collection results = (Collection)q.execute();
names.addAll(results);
q.closeAll();
tx.commit();

To empty the database from all records (persistent objects) use:

Transaction tx = pm.currentTransaction();

tx.begin();
Extent extent = pm.getExtent(Product.class, true);
Query q = pm.newQuery (extent);
long deletedCount = q.deletePersistentAll();
System.out.println("Objects deleted: " + deletedCount);
tx.commit();

To delete a single persistent object pm.deletePersistent():


Transaction tx = pm.currentTransaction();
tx.begin();
Book book = (Book) pm.getObjectById(Book.class, new Long(id));
if (book != null)
pm.deletePersistent(book);
tx.commit();

In summary, JDO is a standard which will diminish your development time and will allow you to forget the burden of designing the database for your applications. JDO 2.0 is mature enough to be used in commercial applications.

If you found this rather long article useful and interesting, then you 'd better refer to the references to learn more about this new exciting technology.

References

  1. This article's source code.

  2. JDO Expert Corner, http://www.jdocentral.com.

  3. JPOX, http://www.jpox.org.

  4. Almaer Dion (2002), "Using Java Data Objects", http://www.onjava.com/pub/a/onjava/2002/02/06/jdo1.html.

  5. Alur D., Crupi J., Malks D. (2003), Core J2EE Patterns: Best Practices and Design Strategies, 2nd Edition, Prentice Hall PTR.

  6. Gamma, E., Helm R., Johnson R., and Vlissides J. (1995), Design Patterns Elements of Reusable Components, Addison-Wesley.

  7. Peterson R., Bhogal K. S. (2005), "An introduction to JDO 2.0 using JPOX and DB2 Universal Database", IBM Developer Works, 
    http://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0506bhogal/.

  8. Roos R. M. (2002), Java Data Objects, Addison-Wesley, http://www.ogilviepartners.com/JdoBook.html.

  9. Roos R. M. (2005), JDO 2 Queries, Part 1 & 2, http://www.theserverside.com/articles/article.tss?l=JDOQueryPart1

  10. Thomas Paul (2004), "Java Data Objects - An Introduction", http://www.javaranch.com/newsletter/200401/IntroToJDO.html

  11. Tilly J. and Burke E. (2002), Ant: The Definite Guide, O’ Reilly.

Creator: John N. Kostaras - email [email protected]
Last modification: 4 April 2006
URL: http://www.geocities.com/jnkjavaconnection/jdotut.html
URL: http://www.ergoway.gr/jkost/jnkjavaconnection/jdotut.html
Hosted by www.Geocities.ws

1