jRelationalFramework

getting started

copyright © 2000 is.com

 
     
Here are the basic steps for using this framework:
  1. Make your persistent object subclass PersistentObject.  It should have getters and setters for all persistent (database) attributes.  The setters should call this.markModifiedPersistentObject() so the database will know the object can be updated.
  2. Create a subclass of AbstractDomain or AbstractStaticDomain using the naming convention: tablename + "Domain.java".
  3. Implement the protected setup() method.  Optionally, set the DatabasePolicy, the JDBCHelper pool name, and the table name. Make sure the JDBCHelper pool gets initialized before it is used.
  4. Add Column Specs in the setup() method.
  5. If joining columns from other tables, add Join Table definitions.
  6. Override the newPersistentObject() method that returns a new instance of your PersistentObject subclass.
  7. Try out your new classes with a simple example.
top
 

Example subclass of PersistentObject:

Notice how the persistent attribute setters call  this.markModifiedPersistentState().  If this is not done, the framework will not save the object because the state will stay current.  Setters for joined fields should not call this.markModifiedPersistentState() since those fields cannot be updated with the same AbstractDomain subclass.

Note that we use only primitive object wrappers for field getters and setters. The main page explains this in the section called "Behaviors Not Supported".

import com.is.jrf.PersistentObject;

public class Part
    extends PersistentObject
  {
  private Integer i_partID = null;
  private String  i_name = null;

  public Integer getPartID()
    {
    return i_partID;
    }
  public void setPartID(Integer v)
    {
    i_partID = v;
    this.markModifiedPersistentState();
    }

  public String getName()
    {
    return i_name;
    }
  public void setName(String v)
    {
    i_name = v;
    this.markModifiedPersistentState();
    }

  } // Part

top
 

Example Subclass of AbstractDomain.java

Here is an example of an AbstractDomain subclass.  Notice the custom SQL method named findNameStartingWith().

import com.is.jrf.AbstractDomain;
import com.is.jrf.ColumnSpec;
import com.is.jrf.DatabasePolicy;
import com.is.jrf.DomainException;
import com.is.jrf.IntegerColumnSpec;
import com.is.jrf.IntegerJoinColumn;
import com.is.jrf.JoinTable;
import com.is.jrf.PersistentObject;
import com.is.jrf.StringColumnSpec;
import com.is.jrf.StringJoinColumn;

import com.is.util.sql.JDBCHelper;

import java.util.List;

public class PartDomain
    extends AbstractDomain
  {

  public void setup()
    {
    this.setDatabasePolicy(new OracleDatabasePolicy());
    this.setJDBCHelperPoolName("ManufacturingDB");

    this.setTableName("Part");
    this.addColumnSpec(
        new IntegerColumnSpec(
            "PartID",
            "getPartID",
            "setPartID",
            DEFAULT_TO_NULL,
            SEQUENCED_PRIMARY_KEY));
    this.addColumnSpec(
        new StringColumnSpec(
            "Name",
            "getName",
            "setName",
            DEFAULT_TO_NULL,
            REQUIRED,
            UNIQUE));
    } // setup()

  public PersistentObject newPersistentObject()
    {
    return new Part();
    }

  /**
   * Custom SQL for doing a specialized search.
   *
   * @param s a value of type 'String'
   * @return a value of type 'List'
   */
  public List findNameStartingWith(String s)
          throws DomainException
    {
    String name = JDBCHelper.delimitSingleQuote(s);
    return this.findWhere(this.getTableAlias() + ".Name LIKE '" + name + "%'");
    }

  } // PartDomain

top
 
 

Simple Usage Example:

Here is a very simple example of a main method that uses the framework. For more useful examples check out the tutorial.

public static void main(String[] args)
  {
  PartDomain pdom = new PartDomain();
  List list = pdom.findAll();

  Iterator it = list.iterator();
  while (it.hasNext())
    {
    Part part = (Part)it.next();
    System.out.print("part ID: " + part.getPartID());
    System.out.println(" name: " + part.getName());
    }
  }

top
 
 

Column Specifications:

The abstract class  ColumnSpec is already subclassed for different java data types.  The subclasses you will most likely use are:

Other types of column specs that have been submitted by users are:


Adding another subclass for another data type (like DateColumnSpec) is as simple as subclassing AbstractColumnSpec and implementing the appropriate methods (The constructors would also have to be reimplemented since Java doesn't allow them to be inherited).

ColumnSpec constructor arguments:

  1. column name
  2. getter method name
  3. setter method name
  4. default value (This can be any object of the respective attribute type)
  5. zero or more options
    Predefined default values: (Default values can be any object)  These are defined in the JRFConstants interface.


    ColumnSpec options:  These too are defined in the JRFConstants interface.

A few ColumnSpec option rules:
top
 

Adding ColumnSpecs in the setup() method:

Below is an example of a setup method for a table with a sequenced primary key and a timestamp used as an optimistic lock.  See OracleDatabasePolicy and SQLServerSybaseDatabasePolicy for examples of the SQL used to retrieve the next available key value.

  public void setup()
    {
    this.setDatabasePolicy(new OracleDatabasePolicy());
    this.setJDBCHelperPoolName("ManufacturingDB");
    this.setTableName("Part");
    this.addColumnSpec(
      new IntegerColumnSpec(
            "PartID",
            "getPartID",
            "setPartID",
            DEFAULT_TO_NULL,
            SEQUENCED_PRIMARY_KEY));
    this.addColumnSpec(
        new StringColumnSpec(
            "Name",
            "getName",
            "setName",
            DEFAULT_TO_NULL,
            REQUIRED,
            UNIQUE));
    this.addColumnSpec(
        new IntegerColumnSpec(
            "Age",
            "getAge",
            "setAge",
            DEFAULT_TO_NULL,
            REQUIRED));
    this.addColumnSpec(
        new BooleanColumnSpec(
            "Wealthy",
            "isWealthy",
            "setWealthy",
            DEFAULT_TO_FALSE));
    this.addColumnSpec(
        new TimestampColumnSpec(
            "LastUpdated",
            "getLastUpdated",
            "setLastUpdated",
            DEFAULT_TO_NOW,
            OPTIMISTIC_LOCK));
    } // setup()
 

Here is an example of a natural primary key.
       new StringColumnSpec(
            "PartCode",
            "getPartCode",
            "setPartCode",
            DEFAULT_TO_NULL,
            NATURAL_PRIMARY_KEY));
 

Here is an example of a compound primary key.  ColumnSpecs in a compound primary key do not need any options specified.

    this.addColumnSpec(
        new CompoundPrimaryKeyColumnSpec(
            new IntegerColumnSpec(
                "Id",
                "getId",
                "setId",
                DEFAULT_TO_NULL),
            new StringColumnSpec(
                "Code",
                "getCode",
                "setCode",
                DEFAULT_TO_NULL)));
top
 

Adding JoinTables in the setup() method:

JoinTable instances are needed when you want to include columns from other tables in your PersistentObject subclass.  Joining with multiple tables is supported, just add more than one JoinTable object to the domain object.  JoinTable objects can also be added to other JoinTable objects to create deep joins (see RentalDomain#setup() in the examples directory for an example of a deep join).

Let's say the main (Part) table has these columns:
   Part.PartID
   Part.Name
   Part.ManufacturerId
   Part.ManufacturerCode

and the Manufacturer has these columns:
   Manufacturer.Id
   Manufacturer.Code
   Manufacturer.Name
   Manufacturer.City

public void setup()
    {

    // ... other stuff here (see above)

    JoinTable joinTable =
            new OuterJoinTable(
                "Manufacturer",      // join table name
                "ManufacturerId,ManufacturerCode", // main table (Part) join columns
                "Id,Code");          // join table (Manufacturer) join columns
    joinTable.addJoinColumn(
        new StringJoinColumn(
            "Name",                  // Column Name
            "ManufacturerName",      // Alias in case of column name conflict
            "setManufacturerName")); // Setter method name
    joinTable.addJoinColumn(
        new StringJoinColumn(
            "City",                  // Column Name
            "ManufacturerCity",      // Alias in case of column name conflict
            "setManufacturerCity")); // Setter method name
    this.addJoinTable(joinTable);
    }

The main table columns and the join table columns are used to make the join between the two tables.  Assuming the generated join for the example would like like this: "WHERE Part.ManufacturerId = Manufacturer.Id AND Part.ManufacturerCode = Manufacturer.Code".   The join columns are those columns you want included into your PersistentObject subclass.
 

top
main page
noticed a document error?
copyright © 2000 is.com