|
|||||||||||||||||||
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Table of Contents
Introduction
Jeevan Architecture
The classes are: JeevanServer and OQLQuery
The classes and interfaces define the Jeevan API. The relationship between
these objects and user application is shown below.
![]() User Application
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
tempDir=c:\\JeevanV3\\temp
JeevanServer has the following methods:
Database Interface
OjectSet Interface
OQLQuery Class
Changes from Jeevan 2.0 to Jeevan 3.0
Application Example
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:
Application ClassesThe classes required to create the application model are the following: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. Key Concepts
Starting 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 FilesJeevan 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 FileA 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.
Creating a New DatabaseUse 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 DatabaseUse 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
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
Consider the following definition of a Computer and Board class. The Computer class has an attribute board of type Board.
String serialNumber; Board board; // reference to a board object } class Board implements Serializable{
Board b = new board(); b.serialNumber = "BSN1"; b.model = "M300"; //construct a computer with the board
//Now insert computer in the database database.insert(c);
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
Consider the following definition of Computer class and Board class. The Computer class has an embedded board object as an attribute.
public String serialNumber; public Board board; } public class Board implements Storable{
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
Board b = new Board(); //create new board object c.board = b; //assign board to computer database.insert(c); //store computer Object Version ControlAs 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:
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.
static final long serialVersionUID = 5699446985967904237L; String serialNumber; ... } Database Schema
database.defineClass("Board"); Relating Objects Using Object Identifiers
One Way RelationIn 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.
String serialNumber; Integer customerOID; //link to customer ... } public class Customer implements Serializable {
Next a computer object is created and custOid is assigned to
customerOid
variable.
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 RelationIn 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.
String serialNumber; Integer customerOID; //link to customer ... } public class Customer implements Serializable {
Assigning Object Identifier
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
Consider the following class definitions:
String serialNumber; ... } public class Customer implements Serializable {
computer1.serialNumber = "SN1"; //set computer1 properties database.insert(computer1); //store computer1 Computer computer2 = new Computer(); //create new computer
Customer customer = new Customer(); //create new
customer
database.relate(customer, computer1 ); //relate customer and
computer1 objects
Retrieving Related ObjectsTo 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:
The following statement gets a Vector containing object identifiers
of customers related to a computer1 object:
Using 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
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
Using getObjectThe 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 selectObjectsThere 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:
Using selectObjectOfTypeThe 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:
Object Selection Criteria
object_attribute logical_token valueObject attributes can be any on the following type:
Logical tokens supported are given in the table below.
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:
"price between (1000, 2000)"
"serialNumber IN('SN100', 'SN200')"
"(price < 2000) && (model == 'M133')" "history has 'replaced'"
Selecting Objects Using Properties of Embedded Objects
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
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
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 and model==$2" ); In the following statements, a value of 2000 is assigned to $1 wchich is a dynamic varialble for price. Integer x = new Integer(2000);
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.add(new Integer(1000)); //low value vector.add(new Integer(2000)); //high value oql.bind(vector);
Vector vector = new Vector();
vector.add(new Integer("SN3)); vector.add(new Integer("SN5)); oql.bind(vector); Updating Objects
The following code fragment selects a computer with serial number "SN1", adds a repair history, and stores the modified computer back into the database. Computer computer = (Computer)os.getObject(); //retrieves the first object in os computer.addHistory("Replaced a cpacitor"); database.update(computer); os.close();
Deleting Objects
database.deleteObjects("Computer", "repaired
== true");
Indexing The Database
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 objectIndex 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 IndexAN 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
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
The following statement compresses storage area allocated for Computer class in the database: database.compress("Computer");
Jeevan ApplicationThe 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 |