Tuesday, May 27, 2008

Abstract

In order to support an object-oriented paradigm that now has become the standard in information systems development, Oracle has implemented an object-oriented model within its database management system. This paper explores the advantages gained by using an object-oriented approach to database management systems based on Oracle’s object-relational database system.
User-defined object types are the foundation of the Oracle object model. The means by which these object types are produced and used to create object-oriented databases are introduced in this paper. Detailed specifics are also given to describe the ways object types are used in implementing the object-oriented characteristics of abstraction, encapsulation, and inheritance. Finally, future implications of the increasing use of the object model in database analysis and design are explored.

Introduction

Significant hardware improvements over the last few years have led the way for the development of extremely complicated applications. In order to create these new sophisticated software systems, which consist of complex objects related by complex relationships, software engineers and developers must rely on logic that is scalable, solid, and reusable (Cáceres, 2002). To fill this need object-oriented programming has emerged as the principal methodology for building systems that meet these requirements. By implementing object-oriented design and programming, large-scale systems are made easier to understand, simpler to debug, and faster to update.
In order to support the object-oriented paradigm that these new applications rely on, Oracle, beginning with Oracle 8 Universal Data Server, started implementing object-oriented principals within the database management system (Oracle, 1997a, p. 2). While implementing objected-oriented functionality, Oracle kept its traditional relational framework as well, thus making it Oracle’s first hybrid database server. This type of database is know as an object-relational database and it contains both relational and object technologies (Hanson, 2002, p. 1).
These object-oriented features are expected to help developers in many different ways. Donald Burleson describes the impact these new object-oriented additions are going to have in a recent article published by TechRepublic,
These additions are anything but mundane. They are going to change the way databases are designed, implemented, and used in ways that Oracle developers have not been able to imagine (Burleson, 2001, p. 1).
According to Oracle, two of the major object-oriented support goals that where realized in the development in the object-relational databases were as follows:
• Provide the ability for users to model business objects in the database by
allowing users to define and use user-defined types.
• Provide infrastructure to support object-based access to object data in
the database while closely matching the data model being used in applications
(Oracle, 1997a, p. 2).
Oracle object types are user-defined data types that allow the modeling of complicated real-world entities into a structure that treats each entity as a single atomic unit in the database.
Oracle’s object model is like the class system found in C++, Microsoft .NET, and Java. This allows for a real object-oriented architecture to be implemented in the database. Complicated real-life entities and logic can be modeled easily while allowing the reuse of objects that make developing database applications faster and more efficient (Oracle, 2002d, p. 1). Application developers can directly access Oracle object types without the need for any additional layers between the database and the client. Instances of objects types can be placed in the database as rows in tables or as values in columns (Oracle, 2002b, p. 1). Additionally, applications using Oracle’s object types are easier to understand and maintain because Oracle’s object types fully support the object-oriented characteristics of abstraction and encapsulation of object behaviors.
While database tables contain data only, objects in Oracle have the capability to act upon the data in various ways. For example, an application can call an exposed method of an object to retrieve detailed information. A couple simple examples of how this may work is described in the Oracle literature,
A purchase order object might include a method to sum the cost of all the
items purchased. Or a customer object might have methods to return the
customer name, reference number, address, or even his buying history and
payment pattern (Oracle, 2002d, p. 2).
This functionality would be encapsulated within each object and consequently provides for great efficiencies. Since object types and their methods are stored inside the database they can be accessed by any application. This can reduce and in some cases eliminate the need for every application that is using the database to re-code similar structures (Oracle, 2002d, p. 2). New applications can simply use the existing functionality.
Being able to fetch and manipulate related objects as one unit creates even more efficiencies. An application can fetch a single object that in turn retrieves additional objects that are connected to the object being fetched. For example, a request for a customer object can be given. In a single round trip between the client and the server, the customer’s name, phone number, and the multiple parts of the address can be returned (Oracle, 2002d, p. 2).
By using Oracle object types part-to-whole relationships can be more easily created. For example, trying to represent a wheel as a part of a car would be difficult in a relational system where part-to-whole relationships can only be accomplished by creating complex schemas of multiple tables (Oracle, 2002d, p. 2). By using object types, objects can have other objects as attributes. This relationship can be extended even further with each subsequent object attribute having other objects as attributes. As a result of establishing interconnected object types, object hierarchies can be established in an Oracle database.
Another advantage of using objects in Oracle is the ability to easily determine if an entity is complete by looking at the entity’s parts. This can be more easily explained by looking at an example of an address. An address object is made up of street name, street number, city, sate, and zip code. If values for any of these attributes are missing then the address object can know that it is not complete. In contrast, a relational table cannot be designed to recognize that all the columns in the table jointly make up a whole (Oracle, 2002d, p. 2).
Oracle object types allows for object type inheritance, meaning a new object subtype can be derived from a parent type definition. Similarities between the types can be shared while characteristics can be extended for the inheriting object (Oracle, 2002b, p.1). For example, a motorcycle or a car subtype could be created from a general vehicle supertype object inheriting the features of this vehicle type. The specialized object types of motorcycle and car can contain additional attributes or redefined methods of the parent object type vehicle extending their object type functionality.

Object Type Implementation

Creating Types:

Lets now explore the details of implementing object types in Oracle. Here is an example of creating the structure or “class” of an address object named ADD_TY (Robbert, 2002, p. 1):
CREATE TYPE addr_ty AS OBJECT
(street varchar2(60),
city varchar2(30),
state char(2),
zip varchar(9));

Once the object type addr_ty has been defined, it can be imbedded or “nested” within another object (Robbert, 2002, p. 1):

CREATE TYPE person_ty AS OBJECT
(name varchar2(25),
address addr_ty);


CREATE TYPE student_ty AS OBJECT
(student_id varchar2(9),
person person_ty);

The sample above shows how the address type can be imbedded within the person object type. Then the student object type is defined using the person object type as one of its columns. This sort of nesting can continue indefinitely.
Now that the student_ty object type has been defined it can be used in creating an object table like the following:
CREATE TABLE STUDENT
(full_student student_ty);

Since the STUDENT table is an object table one will use it in a much different way. One important difference of an object table is that each individual row in the object table will have an object identifier value (OID). Another important difference is that each row can be referenced as an object. Once the table has been created, records can be inserted:
INSERT INTO STUDENT VALUES
(student_ty('100',
person_ty('John Q. Student',
addr_ty('1000 Chastain Rd.',
'Kennesaw', 'GA', '30144'))));
To extract data, the following query can be entered:
SELECT s.full_student.student_id ID, s.full_student.person.name NAME, s.full_student.person.address.street STREET
FROM student s
WHERE s.full_student.student_id = 100

Giving the results:
ID NAME STREET
--------- ------------------------- -----------------
100 John Q. Student 1000 Chastain Rd.

All this is done without having to do any type of relation joins. Updating and deleting is similar to what one would do in the relational model:
UPDATE STUDENT s
SET s.full_student.person.name = 'JOHN NEWNAME'
WHERE s.full_student.student_id = 100;

1 row updated.


DELETE FROM STUDENT s
WHERE s.full_student.student_id = 100;

1 row deleted.

Implementing Methods

To implement a method in a type object use the following syntax:
create or replace type newperson_ty as object
(firstname varchar2(25),
lastname varchar2(25),
birthdate date,
member function AGE(BirthDate in DATE) return NUMBER;

Everything in the syntax is fairly straightforward. The object type is defined, except we now use the line “member function” to define the function call as accepting an age parameter and returning a number. It is important that you make any modifications to object type before you use it in a table; Oracle does not allow an object type to be re-created or dropped if that object type is used in a table (Oracle, 2002d). Now we need to define the AGE function. This can be done using the following syntax (Oracle, 2002a, p. 12):
create or replace type body newperson_ty as
member function AGE(BirthDate in DATE) return NUMBER is
begin
RETURN ROUND(SysDate - BirthDate)
end;
end;

The AGE function is now available to use within a query. First, we need to set up a table holding the person_ty object type.
create table NEWPERSON of newperson_ty;

insert into NEWPERSON values
(newperson_ty('JOHN', 'DOE', TO_DATE('03-FEB-1970', 'DD-MON-YYYY')));

To test the AGE function we can do the following:

select P.PERSON.AGE(P.PERSON.Birthdate)
from NEWPERSON P;

P.PERSON.AGE(P.PERSON.Birthdate)
----------------------------------------
12005

The P.PERSON.AGE(P.PERSON.Birthdate) call executes the AGE method and the age of the person is returned in days. By using a method call, static data (like a birth date) can be used to obtain variable data at the time the variable data is needed. As a result, variable data such as age can be excluded from the database.

Referencing

While foreign keys express many-to-one relationships in the relational model a more efficient way of expressing many-to-one relationships is provided by using Oracle’s object model. As was earlier described, Oracle gives every row object a unique identifier called the OID. The OID allows other objects to reference existing row objects. To hold this reference Oracle uses a built in data type called REF (Oracle, 1997b, p. 6). Here we can see how the REF functions works:
select REF(P)
from NEWPERSON P
where LastName = ‘DOE’;

REF(P)
-----------------------------------------------------------------------
00002802095C3AD6AD3B3C4CD7B080A49C97BACD9835619CD6E25C49F8AC8879791B33DA8F0040F0590002

The REF function takes as an input the alias given to object table. In the example above it is “P”. Here we see the REF function return the actual OID for the row object selected. Using REF by itself isn’t very useful, but Oracle provides another function called DREF that translates REF output into the actual values of the row objects (Koch, 2002, p. 612).
The previously given example of the NEWPERSON table will be used for the next example where a new table is created to hold the department that people belong to.
create table NEWDEPARTMENT
(DeptName VARCHAR(30),
PersonIn REF NEWPERSON_TY);

The first part of the create table syntax looks normal, but the last line is not part of the relational model:
PersonIn REF NEWPERSON_TY);

The PersonIn column does not hold any meaningful data itself, but references data that is stored somewhere else. This reference location can be anywhere as long as the row object referenced is a NEWPERSON_TY type object (Koch, 2002, p. 613). To get a full description of the table just created:
Set describe depth 2
Desc NEWDEPARTMENT

Name Null? Type
--------------- -------- -------------------
DEPTNAME VARCHAR2(30)
PERSONIN REF OF NEWPERSON_TY
FIRSTNAME VARCHAR2(25)
LASTNAME VARCHAR2(25)
BIRTHDATE DATE

METHOD
------
MEMBER FUNCTION AGE RETURNS NUMBER
Argument Name Type In/Out Default?
------------------------------ -------- ------ --------
BIRTHDATE DATE IN

To insert a record into NEWDEPARTMENT, the REF function is needed to store the NEWPERSON reference in the PersonIn column:

insert into NEWDEPARTMENT
select 'Research',
REF(P)
from NEWPERSON P
where LastName = 'DOE';

The first two lines are fairly straightforward. The literal value “Research” is inserted into the NEWPERSON table. Since the datatype of the PersonIn column is of NEWPERSON_TY, a reference to the NEWPERSON object table can be used. What takes place is the REF function returns the OID from the query on the selected NEWPERSON object. Then in the NEWDEPARTMENT table the OID is stored as a pointer to the row object in the NEWPERSON object table. The NEWDEPARTMENT table never keeps the NEWPERSON information just the name of the department (DEPTNAME) and an OID pointer (Koch, 2002, p. 614). Evidence of this can be seen by doing the following:
Select * from NEWDEPARTMENT

DEPTNAME
------------------------------
PERSONIN
-----------------------------------------------------------------------
Research
00002202085C3AD6AD3B3C4CD7B080A49C97BACD9835619CD6E25C49F8AC8879791B33DA8F

The referenced value cannot be seen unless the DREF function is used. The DREF function takes the OID and evaluates the reference to return a value.
select DEREF(D.PersonIn)
from NEWDEPARTMENT D
where DEPTNAME = 'Research'

DEREF(D.PERSONIN)(FIRSTNAME, LASTNAME, BIRTHDATE)
----------------------------------------------------
NEWPERSON_TY('JOHN', 'DOE', '03-FEB-70')

This shows that the NEWPERSON record JOHN DOE is referenced by the Research record in NEWDEPARTMENT.
There are important differences in these object queries when compared to relational queries. The first significant difference is that without specifying the join criteria, joins are performed in the background (Koch, 2002, p. 614). This was shown when a query used a reference to a row object that traveled from the table NEWDEPARTMENT to the table PERSON. The second important factor is that you can DEREF values without the need to know the name of the object table (Koch, 2002, p. 615). In the example above the only table mentioned in the query is NEWDEPARTMENT. This turns the relational model on its head. An embedded foreign key would never be needed in the NEWPERSON table to describe which department a person is in (Burleson, 2002, p. 12).
The function DEREF is used to get the reference of the object table from the relational table, but to gather the same structure of the object type of an object table the VALUE function is required (Koch, 2002).
select value(p)
from newperson p
where lastname = 'DOE'

VALUE(P)(FIRSTNAME, LASTNAME, BIRTHDATE)
-----------------------------------------
NEWPERSON_TY('JOHN', 'DOE', '03-FEB-70')

Lets take our Oracle object model to PL/SQL. Here is an example of how we can use the VALUE function to return specific attributes from our object newperson (Koch, 2002):
set serveroutput on
declare
v_person NEWPERSON_TY;
begin
select value(p) into v_person
from NEWPERSON p
where lastname = 'DOE';
DBMS_OUTPUT.PUT_LINE(v_person.firstname);
DBMS_OUTPUT.PUT_LINE(v_person.lastname);
DBMS_OUTPUT.PUT_LINE(v_person.birthdate);
end;


Giving the results:

JOHN
DOE
03-FEB-70

Next an example of an insert:
declare
v_new_newperson NEWPERSON_TY;
begin
v_new_newperson := NEWPERSON_TY('JANE', 'SMITH', '04-JAN-75');
insert into NEWPERSON
values (v_new_newperson);
end;

Inheritance

In any object-oriented system type inheritance is essential. Oracle provides the capability for the single-type inheritance model where a subtype inherits all its supertype’s attributes and methods (Oracle, 2002a). Additionally, a subtype can add new attributes and methods and override inherited methods (Oracle, 2002a, p. 6).

create type PERSON_TY as object(name varchar2(25),birthdate date
member function AGE() return number, member function PRINTME() return varchar2) not final;

This syntax creates a root type of an object hierarchy – what’s new here is the use of “NOT FINAL”. To create a subtype the following syntax can be used (Oracle, 2002a, p. 6):
create type EMPLOYEE_TY under PERSON_TY (
salary number,
member function WAGES() return number,
overriding member function PRINTME() return varchar2);

The type EMPLOYEE_TY inherits all the attributes and methods from the supertype PERSON_TY. In this example, the attribute salary and the function wages have been added. The function PRINTME is overridden to return some other sort of value as must be defined later in a “create or replace type body” construct as detailed in the Implementing Methods section of this paper.