Site Map Contact Login
W3apps
Company Products Support Services Careers
 
Buy Download

Table of Contents


Introduction

    JeevanTM is a single user Object Oriented Database for JavaTM platform.  Its simple yet powerful API allows you to:
     
    • Create an object database to store Java objects.
    • Directly map the application classes to database schema.
    • Directly communicate with the database without any middle layer driver (such as JDBC driver)
    • Index the database on primitive object attributes, such as int, long, short, String, etc.
    • Index the database on primitive attributes of referenced objects.
    • Dynamically relate any two objects in the database
    • Retrieve Java objects using simple but powerful queries.
    • Update the retrieved object by calling its methods and store it back in the database.

    •  
    The main design goals of Jeevan were:
     
    • Provide simple and intuitive Application Programming Interface (API).
    • Create a pure Java database so future JDK APIs can be easily supported.
    • Allow application development using industry standard tools such as  Visual Cafe, Visual J++ or any other development package.
    • Enable user to develop applications using only the Java Development Kit. No special pre compilers or third party class libraries should be required to build Jeevan applications.
    • Allow JDK classes that implement serializable interface to be stored in the database. No modification should be required to make JDK classes persistent. For example, user should be able to declare variables of type java.util.Hashtable or java.util.Vector in their classes and Jeevan should store the  user objects.

    •  
    This User Guide  presents features of Jeevan by building a small database application. In the process, you will learn  Jeevan architecture and the classes that provide  the Jeevan API.

Jeevan Architecture

    This section describes classes in Jeevan and gives a brief description of  the functions they provide.  The methods supported by each class and their brief description is also given.
    The Jeevan database consists of a Database engine,  four classes and two interfaces.

    The classes are: JeevanServer and OQLQuery
    The Interfaces are: Database and ObjectSet

    The classes and interfaces define the Jeevan API. The relationship between these objects and user application is shown below.
     

       

User Application

    User application is a collection of user defined classes that provide the application functionality.

    To use the database, user application first creates an instance of JeevanServer  and requests it to either create a new database or open an existing database. Based on the message,  JeevanServer  either create a new database or opens the existing database and returns a reference to the Database interface. The Client then uses  methods defined in the Database interface to manipulate the database.

Jeevan Server Class

    JeevanServer is used to create a new database or open the existing database and return the Database reference to a user application. Constructor of JeevanServer requires jeevan.properties file as an input parameter which defines two properties: a license file and a temp directory. A sample property file  entries are shown below:
     
        licenseFile=c:\\JeevanV3\\license.bin
        tempDir=c:\\JeevanV3\\temp


    The licenseFile property defines the location of license.bin file. The tempDir defines location of a temporary directory that is used as a work space to store temporary files.

    JeevanServer has the following methods:

       
      createDatabase Creates a new database.
      openDatabase Opens an existing database.

Database Interface

    The Database interface defines methods to maintain the database. These methods fall into three categories: a) Data definition methods,  b) Data Manipulation methods and c) Utility methods.
       
    Data definition methods are used to define the database schema and manage indexes. These methods are listed below. Methods marked with * are new to version 3.0:
       
      defineClass Defines use class in the database and creates database schema for the class.
      deleteClass Deletes class definition from the database and associated database schema.
      createIndex Creates new index.
      deleteIndex Deletes index. 
      getClassNames Returns a vector containing list of classes defined in the database.
      getIndexNames Returns vector containing names of indexes.
      getClassName  * Returns a class name given an object identifier
      getIndexFields Returns vector containing names of indexed fields for a specified index.
      addCounter  * Adds a new counter with specified initial value
      deleteCounter  * Deletes specified counter
    Data manipulation methods  manipulate objects in the database. The methods are as follows:
       
      selectObjects Selects objects from the database.
      selectObjectsOfType Selects objects using class hierarchy.
      insert Inserts object in the database.
      selectFields Selects fields given the selection criteria
      update Updates object in the database.
      delete Deletes object from the database.
      deleteObjectsOfType Deletes objects using class hierarchy.
      assignObjectId Assigns object identifier to a new object.
      relate Relates any two objects in the database.
      getImage Retrieves image from the database. 
      unrelate Removes relationship between two objects
      getObject Retrieves object from the database given its object identifier
      getObjectId * Get object identifier for a given object
      getRelatedClassNames * Get names of classes whose objects are related to a given object
      getRelatedObjectId * Get objectIds of related objects
    Utility methods are database compression, recovery  and helper methods. Utility methods currently supported are:
       
      compress compresses the database
      getObjectCount Returns the number of objects of a given class in the database.
      getUtilization Returns a number indicating fragmentation of disk space. 
      close Closes the database
      isDatabaseOpen Returns true if database is open
      getClassName Returns a name of a class that the object belongs to given the object identifier
      getNextCounterValue* Get next sequential integer from the counter
      isDatabaseOpen * Returns true if database is open

OjectSet Interface

    When Jeevan executes a query, it creates an ObjectSet  that contains  objects that satisfy selection criteria. The ObjectSet interface contains methods to get  objects from the set. Methods supported by ObjectSet are given below.
       
      close Close the objectSet
      getCount Returns the number of objects in the objectSet. 
      getObject Retrieves an object at the cursor position and moves cursor to the next object. 
      moveFirst Moves cursor to the first object in the ObjectSet. 

OQLQuery Class

    QOLQuery represents a dynamic query. In dynamic query, the variables are represented by place holder strings such as "$1", "$2" and so on. The variables are  assigned a value at run time. For example, to select computers with price less than certain value, the selection criteria is defined as "price < $1".  Value to $1 is assigned at  run time using the bind method.
       
      bind Associates value to a dynamic variable.
      getClassName Returns a className associated with this OQLQuery object. 
      assignObjectId Assigns object identifier to an object

Changes from Jeevan 2.0 to Jeevan 3.0

  1. All user classes must implement java.io.Serializable interface. The Storable class does not exist any more.  In earlier version, user classes extended Storable class. With removal of Storable class, you need not have source for your classes. Any third party class that implements Serializable imterface can now be stored in Jeevan.
  2. Object identifier is an Integer object. In earier version, it was of type long.
  3. Method getRelatedObjectId replaces the method getRelatedObjects in earlier version.
  4. RecordSet class is not implemented in version 3.0 as ObjectSet provides similar functionality.

Application Example

    The best way to explain concepts of Jeevan  is by building a small database application.

    We will build a database for a computer manufacturing company. The company buys  motherboards and power supplies  and assembles them into a fully functional desktop and laptop computer systems.

    We want  to store information about a computer, a motherboard which contains  CPU and video chips and a power supply.   We also need to maintain information about  customers and a link between the customers and the computer(s) they purchased.

    Specific information we would like to maintain for each component is as follows:
     

    1. For each desktop computer, we need to maintain its serial number, model number, price, repair history and a flag that indicates if the computer is repaired or not.
    2. For each laptop, we need to store its  weight in addition to all the information for desktop.
    3. When a computer is sold, we need to maintain a link to the customer who purchased the computer.
    4. For a motherboard, we need to maintain its serial number, model and information on two main chips on the board.
    5. For each chip, we need to store the type of chip (such as CPU or VGA) and its price.
    6. For a power supply, we need to maintain its model number and output capacity.
    7. For each customer, we need to maintain the name of the customer , address, and a link to  the computers purchased by the customer.

    8.  
    The figure below shows the application objects .
model.gif (5329 bytes)

Application Classes

The classes required to create the application model are the following:
  • Computer
  • Motherboard
  • Power supply
  • Laptop
  • Chip
  • Customer
  • Based on the application requirements discussed earlier, the class definitions for the above classes are given below. We will use these class definitions  throughout the discussion in this document.

    Note the following points about the classes as defined below. We will discuss these points in detail later in the document.

    1. All classes implement java.io.Serializable interface
    2. Laptop extends Computer class
    3. Objects of Motherboard and Power supply classes are attributres of Computer class
    4. Objects of Chip class are attributes of Motherboard class.

    5.  
     public class Computer implements java.io.Serializable {
       Integer       customerOID;    // link to customer
       PowerSupply   ps;    // embedded power supply object
       Motherboard   mb;    // embedded mother board object
       public String serialNumber;
       public String model;
       public float  price;
       public String history;      // history of repairs
       public boolean repaired;

       // constructor
       public Computer (String sn, String m, float p) {
          this.serialNumber=sn;
          this.model=m;
          this.price=p;
          repaired = false;
       }

       public void addHistory(String h) {
                history = history + h;
        }
    }

    public class Customer extends Storable {
       public Vector vComputerOID;           // vector of links to computer
       public String name;
       public String address;

       // constructor
      public Customer (String n, String a) {
          this.name=n;
          this.address=a;
       }
    }

    public class Motherboard implements Serializable {
       public Chip[] chipArray;              // array of embedded chip objects

       // constructor
       public Motherboard (Chip[] chips) {
          this.chipArray=chips;
       }
    }

    public class Chip implements Serializable {
       public String type;
       public float  price;

       // constructor
       public Chip (String type, int price) {
          this.type=type;
          this.price=price;
       }
    }

    public class PowerSupply implements Serializable {
       public String model;
       public int output ;

       // constructor
       public PowerSupply (String model, int output) {
          this.model = model;
          this.output = output;
       }
    }
     

    Key Concepts

      This section describes  key concepts of Jeevan Database System. It is important that you read this section completely before building the application. The concepts described here are then used to build the example database application.

     Starting Jeevan Server

      The first thing the Client application does is to start JeevanServer. Creating a new instance of JeevanServer starts the server. The following statement starts  the Jeevan server.
       
        JeevanServer server = new JeevanServer("c:\\jeevanV3\\jeevan.properties");
      The parameter is jeevan.properties file which defines location of license file and temp directory.

      Only one JeevanServer object is required in the application. In the following discussion, we will assume that the application has started a JeevanServer and variable "server" is available for use.

         

      Temporary Files

      Jeevan database requires some storage space as a "scratch pad" during its operation.  The directory for the scratch pad is named "tempDir" and is normally created on the device where the database is created.

       For certain applications, temp directory cannot be located on the same device  that contains the database. CD-ROM based database application is one example.  Specify the location of temp directory in jeevan.properties file. The following line in jeevan.properties file specifies that temp directory be located in c:\scratchPad directory.
       

        tempDir="c:\\scratchPad"
        
        

      License File

      A license file is named license.bin. Place this file in any directory and specify its location as licenseFile property in jeevan.properties file. The line below specifies that license File is located in JeevanV3 directory on C: drive.
       
        licenseFile=c:\\JeevanV3\\license.bin

      Creating a New Database

      Use  createDatabase method of  JeevanServer to create a new database. The following code segment creates a new database called "ComputerDb" in the directory specified by dbPath on C: drive and returns a reference to  Database interface.
       
        Database database = server.createDatabase("c:\\dbPath\\ComputerDb");
      A new sub directory named "ComputerDb" is created under the directory specified by dbPath. Database files reside in this directory.

      All images used in the application must be stored in the image directory. The getImage method in the Database interface looks for the requested image in this directory.

         

      Opening an Existing Database

      Use the openDatabase method to open the existing database. The following statement requests the server to open a database called ComputerDb located under dbPath in a read-write mode. To open the database in read mode, specify the second parameter in openDatabase method as "r".
       
        Database database = server.openDatabase("c:\\dbPath\\ComputerDb", "rw");

    Object Identifier

      Jeevan assigns a unique object identifier to each object stored in the database. Object identifier is an Integer object. Once assigned, it is never used again or assigned to any other object.

      Object identifier is unique across the database. If you know the  object identifier, the class of the object can be obtained by using the getClassName method of the Database  interface.

      Object identifier is normally assigned to an object when  the object  is inserted in the database. However, there are situations when object identifier  is required prior to its insertion in the the database. One example of this situation is when two newly constructed objects are linked using their object identifiers before the objects are inserted in the database.  See relating objects using Object identifiers  below.  The Database interface provides assignObjectId method to assign object identifier to a new object.

      Object identifier of an object cannot be changed. However, database interface  provides a clearObjectId method  that can be used to clear the object identifier associated with the object.  The method is provided so that the existing object can be re-used. Rather than creating a new object, one can use clearObjectId method and use the existing object as if it were created new. Using this method will improve the system performance as there will be fewer objects needing  garbage collection.

         

    Embedded Objects

      Jeevan uses Object Serialization technology to store Java objects. When an object is serialized, the object attributes  which are references to other objects are also written to the same output stream as that of the object being serialized. Because the referenced objects are stored in the same output stream as the object they are referenced in, the referenced objects are called the embedded objects in Jeevan documentation.

      Consider the following definition of a Computer and Board class. The Computer class has an attribute board of type Board.

         
              class Computer implements Serializable {
                    String serialNumber;
                    Board board;            // reference to a board object
              }

              class Board implements Serializable{
                      String serialNumber;
                      String model;
              }

      Let us create a new computer object and insert it in the database:
       
              //construct a board first
              Board b = new board();
              b.serialNumber = "BSN1";
              b.model = "M300";

              //construct a computer with the board
              Computer c = new Computer();
              c.serialNumber = "SN1";
              c.board = b; // b is board object created earlier

              //Now insert computer in the database

              database.insert(c);
               

      When a Computer object is serialized for  storing  in the database, the board object is also serialized and embedded in the computer object and stored along with the computer object as illustrated below. The computer object is a container object and stores board object in it.

      The following figure illustrates the memory model of the object and its persistent model as it exists on the disk.


       

      Note that the board object is not assigned an object identifier. The board object cannot be retrieved independently from the database. When the Computer object is retrieved from the database, the board object is  retrieved along with it.

      Just remember that every time you reference an object A in another object B, the referenced object A is embedded when  object B is stored in the database.

      The class of an embedded object must implement Serializable interface.

         

    Defining Application Classes

      A user defined class whose objects are to be stored in the database must meet the following criteria:
       
      1. The class must be defined as public
      2. The object attributes that will be used in a query or used to create an index must be declared public.
      3. To make objects persistent, the class must  implement java.io.Serializable interface.
      4. The class must be defined in the Database using the defineClass method before any of its objects can be stored.

      5.  
      The first two requirements are necessary because Jeevan needs to access the class definitions and must have access to variables if the variables are used in creating indexes. These requirements will not be necessary in the future when  Java version 1.2 is released.
       
    • The third requirement is about making object persistent.
      1.  
      While designing application classes, you must be careful not to store an object in two places.

      Consider the following definition of Computer class and Board class. The Computer class has an embedded board object as an attribute.

         
            public class Computer extends Storable{
                  public String serialNumber;
                  public Board board;
            }

            public class Board implements Storable{
                    public String serialNumber;
                    public String model;
            }
             

      Now consider the following situation where application creates Computer and Board object separately and stores them in their respective storage:
         
            Computer c = new Computer();  //create new computer object
            Board b = new Board();        //create new board  object
            c.board = b;                 //assign board to computer
            database.insert(c);           //store computer
            database.insert(b);           //store board
      In the above scenario, the board object will have two copies, one in its own storage and one embedded in the computer object. This is not a desirable situation because there is a possibility of one board object getting  updated and leaving the second in its original state thus making the database inconsistent. This situation can be avoided as described below.
         
      If you must embed object in other object, do not store the embedded object in its own store. This will prevent a duplicate copy of the embedded object.
         
      The above code sample can be rewritten as follows, in this case it will not cause the database to be in inconsistent state. Note that board is not stored in its own store.
         
            Computer c = new Computer();  //create new computer object
            Board b = new Board();        //create new board object
            c.board = b;                  //assign board to computer
            database.insert(c);           //store computer

       Object Version Control

      As application classes evolve, new methods and attributes are added to the original class definition. At any time, classes and objects with different version can exist in the database.  It is important that application be able to read older versions of objects and also write the new versions to the database.

      Jeevan database exploits the version control mechanism provided by the object serialization mechanism of the Java language. To use the version control mechanism, follow the procedure below:
       

      1. For each original class, get the serial version UID for the class by using serialver program that comes with JDK.

      2. To get the serial version UID, run the serialver program with class name as parameter. The following commands issued in the console window in Widows enviroment generates a serial version UID for Computer class. It is assumed that the Computer.class file exists in c:\jeevan\lib directory.


                  cd c:\jeevan\lib
                  set classpath=.;c:\jeevan\lib
                  serialver Computer
       

        The  serialver program prints the following output:
        static final long serialVersionUID = 5699446985967904237L;
         
      1. Copy the serialVersionUID into your Java class definition file. The following code sample defines the Computer class that is ready for version  control.

      2.  
          class Computer extends Storable {
              static final long serialVersionUID = 5699446985967904237L;
              String serialNumber;
              ...
          }
       There are certain restrictions on the type of changes allowed for the version control mechanism to work. A detailed discussion on type of changes affecting serialization and what changes are considered incompatible, see http://java.sun.com:80/products/jdk/rmi/doc/serial-spec/version.doc.html#6519

    Database Schema

      In Jeevan, the application classes directly define the database schema. There is no need to learn a separate data definition language. The Database interface provides defineClass method to map a user class to database schema. The following statements define the database schema for Computer and Board class:
       
                database.defineClass("Computer");
            database.defineClass("Board");
      You have to make sure that the class files, Computer.class and Board.class are in CLASSPATH..

    Relating Objects Using Object Identifiers

      It was mentioned earlier that each object stored in the database is assigned a unique object identifier. The object identifiers are used to link two objects in the database.
       

      One Way Relation

      In our  example, when a customer buys a computer, we need to relate the customer object to a computer object. To make this relationship,  we define a field called customerOID of type Integer in the Computer class as shown below. This links the Customer object to the Computer object.
       
          public class Computer implements Serializable {
                String serialNumber;
             Integer customerOID; //link to customer
              ...
          }

          public class Customer implements Serializable {
              String name;
              ...
          }
           

      The application code sample below illustrates how to link the two objects. First a customer object is created and inserted in the database. The insert operation returns the object identifier assigned to the customer object which is  stored in custOid variable.

      Next a computer object is created and custOid is assigned to customerOid variable.
       

          Customer cust = new Customer();    //create new customer
          Integer custOid = database.insert(cust); //store customer and get its oid
          Computer computer = new Computer(); //create new computer object
          computer.customerOID = custOid; //relate computer to customer
          database.insert(computer); //store computer.

      Two Way Relation

      In the above example, we have created a one way link from the computer object to the customer object. To establish a reverse link from customer to computer, we need to define a variable in Customer class to hold object identifiers of computers that the customer purchased.  Since a customer can purchase more than one computer, we define an attribute vCustomerOid of type Vector to hold  object identifiers of computers.  The following class definitions create forward and reverse links between computer and customer objects.
       
            public class Computer implements Serializable {
                  String serialNumber;
               Integer customerOID; //link to customer
                ...
            }

            public class Customer implements Serializable {
                String name;
                    Vector vComputerOID;
                ...
            }
             

       Assigning Object Identifier

        As discussed earlier, object identifier is assigned to an object when the object is inserted in the database. For linking  new  computer and customer objects, we need object idenfiers of both the objects before the objects are actually inserted in the database. For  this situation, Database interface  provides assignObjectId method.

        Following example creates computer and customer objects, assigns them object identifiers and links these objects together creating a two way link between the objects.
         

          Computer computer = new Computer();
          Customer customer = new Customer();
          Integer computerOID = database.assignObjectId(computer);
          Integer customerOID = database.assignObjecdtId(customer);
          computer.customerOID = customerOID;             //link to customer
          customer.vComputerOID.addElement(computerOID);  //link to computer
          database.insert(computer);                      //store in database
          database.insert(customer);
        When an object with an object identifier already assigned is inserted in the database, the insert method  returns the same object identifier already assigned to the object.

    Dynamically Relating Objects

      The mechanism described above to relate two objects in the database require that the class definitions contain fields of type Integer or of type Vector to hold the object identifiers of related objects. There are situations where you do not want to modify the class definition or you do not have access to class definition but still want to relate two objects. Jeevan has the feature where any two objects in the database can be related without explicitly defining fields to hold  object identifiers.
         
      To relate any two objects, use the relate method of the Database interface.

      Consider the following class definitions:

         
          public class Computer implements Serializable {
                String serialNumber;
              ...
          }

          public class Customer implements Serializable {
              String name;
              ...
          }
           

      The application code sample below creates two computers and relates them to a customer.
         
          Computer computer1 = new Computer();   //create new computer
          computer1.serialNumber = "SN1";        //set computer1 properties
          database.insert(computer1);            //store computer1

          Computer computer2 = new Computer();   //create new computer
          computer2.serialNumber = "SN2";        //set computer2 properties
          database.insert(computer2);            //store computer2

          Customer customer = new Customer();    //create new customer
          customer.name="Electronica Inc."       //set customer properties
          database.insert(customer);             //store customer

          database.relate(customer, computer1 );  //relate customer and computer1 objects
          database.relate(customer, computer2 );  //relate customer and computer2 objects
           

      The relate method establishes a two way relationship. That is, the computers are related to customer and the customer is related to computers.
       

      Retrieving Related Objects

      To retrieve related objects, use the getRelatedObjectId method of Database interface.  The method requires the object and the class name of the related object as a parameter.

      The following statement gets a vector containing object identifiers of computers  related to a customer object customer1:
       

        Vector v  = database.getRelatedObjects(customer1, "Computer");
      Vector v contains object identifiers of computers related to customer1 object.

      The following statement gets a Vector containing object identifiers of customers  related to a computer1  object:
       

        Vector v  = database.getRelatedObjects(computer1, "Customer");
      Vector v contains object identifier of customer related to computer1.

    Using Images

      When a new database is created, Jeevan creates /images sub- directory under the main database directory to store the images.

      All Image files used in the application must be stored in  /images sub directory. To get an image from the database, use the getImage method of the Database interface.
       

    Storing Objects in the Database

      Objects are stored in the database using the insert method of the Database interface. When an object is inserted into the database, it is assigned a unique object identifier. Object identifiers are of type Integer. The following code fragment creates a new computer object with serialNumber of SN1000, model  P133, price of $2000 and stores it in the computer database.
        Computer computer = new Computer("SN1000", "P133", 1200);
        Integer objectId = database.insert(computer);
       The insert method returns the object identifier assigned to the object.
       

    Selecting Objects from the Database

      The Database interface provides three methods to retrieve objects from the database: getObject, selectObjects and selectObjectsOfType.
       

      Using getObject

      The getObject method retrieves one object with a given object identifier. If you know the object identifier of the object, you can retrieve the object using this method.

      For example, assume that you have already retrieved a computer object from the database and computer.customerOID field holds the object identifier of the customer who purchased this computer. The following statement will retrieve the customer object from the database:
       

        Customer customer = (Customer)database.getObject(computer.customerOID);
        Note that getObject returns the  Object type and you must cast the returned value to a desired class.

      Using selectObjects

      There are three selectObjects methods retrieve a set of objects (more than one object) from the database. The set of objects is represented by the ObjectSet object. The three selectObjects method are:
       
        ObjectSet selectObjects("ClassName")
        ObjectSet selectObjects("ClassName", criteria)
        ObjectSet selectObjects(oqlQuery)
        
        
      The first form selects all  objects for a given class.  For example, the following statement returns an ObjectSet containing all computer objects:
       
        ObjectSet oset = database.selectObjects("Computer");
      The second form selects objects of a given class that satisfy a given selection criteria. For example, the following statement returns an ObjectSet containing all computers whose price is less than 2000:
       
        ObjectSet oset = database.selectObjects("Computer", "price < 2000");
      The third form uses dynamic query. Dynamic query is described later in the document.

      Using selectObjectOfType

      The selectObjectsOfType method retrieves objects using the class hierarchy. For example, the class Laptop extends the  Computer class. Each laptop is therefore also a computer. If you want to select all computers in the database which will include the computers as well as laptops, use the selectObjectsOfType method. The following statement returns an objectSet containing all computers and laptops in the database:
       
        ObjectSet oset = database.selectObjectsOfType("Computer");
      The following statement returns an ObjectSet containing all computers and laptops whose price is less than 2000:
       
        ObjectSet oset = database.selectObjectsOfType("Computer", "price < 2000");

    Object Selection Criteria

      The object selection criteria consists of logical expressions connected with && or || symbols. The logical expression is specified as follows:
       
        object_attribute  logical_token  value
      Object attributes can be any on the following type:
       
      int, Integer double, Double
      long, Long short, Short
      float, Float boolean, Boolean
      String

      Logical tokens  supported are given in the table below.
       

      ==
      Equal to
      !=
      Not equal to
      <
      Less than
      <=
      Less than or equal to
      >
      Greater than
      >=
      Greater than or equal to
      IN or in
      in a list
      BETWEEN or between
      between two end points
      HAS or has
      field contains a string value. For String only.

      String values must be enclosed in single quote.

      The selectObjects statement and some examples of selection criretia are given below:

        ObjectSet oset = database.selectObjects("Computer", selectionCriteria );
      Following are some examples of selectionCriteria:
       
      • Select all computers whose prices are less than $2000:

      •  
          "price < 2000"
      • Selects all computers in the price range $1000 and $2000:
              "price between (1000, 2000)"
      • Selects all computers with serial numbers  SN100 and SN200:
          "serialNumber IN('SN100', 'SN200')"
      • Select all computers with model number M133 and price less than 2000
      •     "(price < 2000) && (model == 'M133')"
      • Select all computers that contain a word "relplaced" in its history field.
      •     "history has 'replaced'"
      • Select all computers that are repaired.

      •  
          "repaired == true"
        While using && or || operators, make sure that logical expressoins they connect are enclosed in paranthesis as in the above statement.

    Selecting Objects Using Properties of Embedded Objects

      One of the powerful features of Jeeven is that it allows you to select object by using the properties of embedded object in the selection criteria.

      For example, the Computer class defined earlier has two embedded objects, a PowerSupply and Motherboard. The Motherboard has two Chip objects embedded in the form of an array of chips (using the chipArray attribute). We can use the properties of these embedded objects to select a computer from the database.

      The following statement selects the computer that has a motherboard with serial number BSN2:

        ObjectSet oset=database.selectObjects("Computer", 
                                        "motherboard.serialNumber='BSN2'");
      As another example, the following statement selects all computers that have a P133 chip :
        ObjectSet oset=database.selectObjects("Computer", 
                                       "motherboard.chipArray.type='P133'");
      Note that object properties are specified in the familiar dot notation of "object.property".

    ObjectSet

      An ObjectSet represents a set of objects that satisfy a given selection criteria.

      The ObjectSet maintains an implicit cursor. After creation, the cursor points to a first object in the objectSet. The getObject method returns an object at the current cursor position and moves the cursor to  next object. Use  moveFirst method at any time to point the cursor to the first object. Close the ObjectSet using close method.

      The following code fragment selects all computers whose price is less than $2000 and lists their serial numbers.

        ObjectSet oset = database.selectObjects("Computer", "price < 2000");
        int count  = oset.getCount();  //get number of objects in the set
        for (int i=0; i<count; i++) {
            Computer computer = (Computer)oset.getObject();
            System.out.println(computer.price);
        }
        
        oset.close();
      Note that getObject returns a variable of type Object and you must cast the the returned value to a desired class.
        
        

     Dynamic Query

      The object selection criteria described in the previous section is static in nature.  It is static because the values of the variables are statically assigned. For example, to select all computers with price less than 2000, we construct a query criteria as "price < 2000".  Here the number 2000 is assigned at the compile time.

      There are situations where we want the query  criteria to be dynamic such as "price < x" and assign a value to x at run time.

      Jeevan provides OQLQuery class to build the dynamic selection criteria.

      To build a dynamic query, construct an object of OQLQuery  class. The constructor takes two parameters, the first is a name of a class and second is a query criteria. In the query criteria, the variables are represented as $1, $2 and so on..  In the following statements, $1 and $2 represent a dynamic variable for price and model.  If there are more variables, use $3, $4 and so on.
       

        OQLQuery oql = new OQLQuery("Computer", "price < $1" );
        OQLQuery oql = new OQLQuery("Computer", "price < $1 and model==$2" );
      Once the OQLQuery object is constructed, use the bind method to assign a value to a dynamic variable at any time. The bind method takes two parameters. The first parameter is a String  representing a dynamic variable such as $1 and second is an Object representing a value.

      In the following statements, a value of 2000 is assigned to $1 wchich is a dynamic varialble for price.

              Integer x = new Integer(2000);

        oql.bind("$1", x);
      To execute the query, use the selectObjects method of the Database interface and pass the OQLQuery object after all the dynamic variables are assigned values using the bind method. The following statement builds an ObjectSet containing objects specified by the query in oql object
       
        ObjectSet os = database.selectObjects(oql);
      To construct a dynamic query that has IN or BETWEEN clause as follows:

          OQLQuery oql = new OQLQuery("Computer", "price BETWEEN $1" );

      and bind $1 to a vector that contains the two price values. The first item in the vector represents the low value and second item represents the high value.

      The following code segment creates a vector containing two integers (1000 and 2000)  representing the price range and binds it to the dynamic query  as shown below.
       

           Vector vector = new Vector();
           vector.add(new Integer(1000));    //low value
           vector.add(new Integer(2000));    //high value
           oql.bind(vector);
      For IN clause, the vector holds more than two objects. The following code segment creates a dynamic query to select objects whose serial numbers are SN1, SN3 and SN5.
       
            OQLQuery oql = new OQLQuery("Computer", "serialNumber IN $1" );

           Vector vector = new Vector();

           vector.add(new String("SN1"));
           vector.add(new Integer("SN3));
           vector.add(new Integer("SN5));
           oql.bind(vector);

    Updating Objects

      To update an object, first retrieve it from the database and then modify it by directly changing its attributes or using its methods. Store the modified object by using the update method of the Database interface.

      The following code fragment selects a computer with serial number "SN1", adds a repair history, and stores the modified computer back into the database.

              ObjectSet os = database.selectObjects("Computer", "serialNumber == 'SN1'");
              Computer computer = (Computer)os.getObject(); //retrieves the first object in os
              computer.addHistory("Replaced a cpacitor");
              database.update(computer);
              os.close();
      The addHistory method adds a new history to the old history.

    Deleting Objects

      The delete method deletes an object from the database. Three signatures of delete are supported.
       
      • delete(object) deletes the given object.
      • delete(objectId) deletes the object with given object id.
      • delete("className", criteria) deletes objects that match the selection criteria.

      •  
      The following code fragment selects  computers that are repaired and deletes them from the database.

          database.deleteObjects("Computer", "repaired == true");
       

    Indexing The Database

      An index on a database is created using  createIndex method of  the Database interface. Index can be created on any field of primitive type such as int, long, float, double or String type.

      The following statement creates an index on the price field of a computer object.
       

        database.createIndex("Computer", "price");
      The first parameter specified the class and second parameter specified the index field.

      The index in Jeevan is inherited by children classes. For example, the Laptop class extends Computer class. If an index is created on a serialNumber field of Computer, the index is also created for Laptop class on the serialNumber field.
       

      Creating index on a field of embedded object

      Index can also be created on a field of an embedded object.

      The following statement creates an index on the model field of a power supply object embedded in the Computer.
       

        database.createIndex("Computer", "ps.model");
      The following statement creates an index on the type field of a Chip in the computer. Note that chipArray is defined as an array of type Chip in the  Motherboard class.
       
        database.createIndex("Computer", "motherboard.chipArray.type");
      Creating an index speeds the object retrieval process but also slows the update process as the  index need to be updated as well. Create index on fields which you will normally use in object selection criteria.

      The getIndexNames method of Database interface returns the index list.
       

      Deleting an Index

       AN index is deleted using the deleteIndex method of  Database interface. The following statements delete an  index on ps.model fields and a price field of a Computer class. ps is the embedded power supply object in the Computer class.
        database.createIndex("Computer", "price");
        database.createIndex("Computer", "ps.model");

    Creating a Query Class

      The Database interface provides getObject, selectObjects and selectFields methods with a selection criteria to retrieve objects from the database. If an application requires more complex queries than what these three methods provide, you can construct a class to implement the query logic using these methods.

      For example, let us say that we want to get the names of all the customers who have purchased computers that have P300 type chips. We build a CustomerByChip class to achieve the desired result.

        class CustomerByChip {
            String chipType;
            Database database;
        
            CustomerByChip(String chipType, Database database) {
                this.chipType = chipType;
                this.database = database;
            }
        
        
            Vector execute() {
                Vector vNames = new Vector();
                String criteria = "motherboard.chipArray.type= '" + chipType + "' ";
                RecordSet recordSet = 
                        database.selectFields("Computer", "customerOid", criteria);
                int customerCount = recordSet.getCount();
                for(int i=0; i<customerCount; i++) {
                    long oid = recordSet.get(i);
                   Customer customer = (Customer)database.getObject(oid);
                    vNames.addElement(customer.name);
                }
                return vNames;
            }
        }
      We can now use this class to list names of the customers who have purchased computers with P300 type chip as shown in the following program fragment:
        JeevanServer server = new JeevanServer(); //start server
        Database database = server.openDatabase("ComputerDb"); //open database
        CustomerByChip cbc = new CustomerByChip(database, "P300"); //create query class
        Vector vNames = cbc.execute();    //execute query
        
        //Now print the customer names
        for (Enumeration e = vNames.elements() ; e.hasMoreElements() ;) {
          System.out.println(e.nextElement());
        }

    Database Compression

      As objects are updated and deleted from the database, the storage becomes fragmented. The Database interface  provides  getUtilization method that returns the precent storage utilization for a given class. Use the compress method to recover the disk space.

      The following statement compresses storage area allocated for Computer class in the database:

        database.compress("Computer");

    Jeevan Application

        The source code of computer database application discussed in this document  is in the \jeevan\example directory.
       
     
    Home | Company | Products | Support | Services | Careers
    ©2007 W3apps Corporation. All rights reserved. Privacy Statement