Open-Source Internship opportunity by OpenGenus for programmers. Apply now.
This article aims to:
- Explain the object-oriented database and its principles
- Contrast the object-oriented database with the relational database
- Provide examples of object-oriented database management systems
Object-Oriented Database
So what is an object-oriented database?
An object-oriented database (also known as an object database) is a database that stores information in the form of objects and classes. Similar to object-oriented languages, object-oriented databases follow many object-oriented programming paradigms, such as inheritance, polymorphism, and encapsulation.
Principles of Object-Oriented Databases
So how do object-oriented databases implement these principles? We can take a look by examining one example of an object-oriented database: ZODB, which is used with Python.
- Encapsulation
In object-oriented programming, encapsulation is the principle that data, along with methods that modify said data, can be wrapped into some kind of category. In many object-oriented programming languages, it is often demonstrated by providing classes.
Many object databases provide the ability to define classes of data. As an example, data in ZODB (an object-oriented database management system) can be encapsulated as such:
import os
import shutil
import ZODB, ZODB.FileStorage
import transaction
import persistent
class Employee(persistent.Persistent):
def __init__(self, name, age, salary):
"""
Data class representing
an employee, with a given
name, age, and salary.
"""
self._name = name
self._age = age
self._salary = salary
def get_salary(self):
"""
Get an employee's salary.
"""
return self._salary
def set_salary(self, salary):
"""
Sets an employee's salary.
"""
self._salary = salary
def __str__(self):
return "{}: {}, ${}".format(self._name, self._age, self._salary)
class Boss(Employee, persistent.Persistent):
def __init__(self, name, age, salary):
Employee.__init__(self, name, age, salary)
self._employee = ""
def hire_employee(self, employee):
"""
A boss hiring an employee.
"""
self._employee = employee
def __str__(self):
return "{}, {} ${} employs: {}".format(self._name, self._age, self._salary, self._employee)
# creates a database file 'file.fs'
# inside a folder 'database' (any
# existing database is destroyed)
if os.path.exists('database'):
shutil.rmtree('database')
os.mkdir('database')
db = ZODB.DB('database/file.fs')
# opens (and eventually closes)
# a connection with the database file
conn = db.open()
# dictionary holding employee objects (in reality, use a BTree)
conn.root.employees = {}
conn.root.employees['jane'] = Employee('jane', 24, 87000)
boss = Boss('katie', 35, 230000)
boss.hire_employee('jane')
conn.root.employees['katie'] = boss
transaction.commit()
for employee in ['jane', 'katie']:
print(conn.root.employees[employee])
db.close()
Output:
jane: 24, $87000
katie, 35 $230000 employs: jane
Notice how the data object is defined in the same way a Python class is defined. There is practically no difference in defining data types for object databases vs. data types in Python. The "Employee" object is able to be committed to the database, without any querying language analagous to SQL.
- Inheritance
In object-oriented programming, inheritance is the principle that a class can base itself on properties of another class (in other words, inheriting its properties and methods). Just like with classes in object-oriented programming, objects in object-oriented databases can inherit properties of another data type. In the example above, note how we can define a class "Boss" that inherits from the class "Employee." We defined a new class method, hire_employee()
, as well as define all the necessary "Employee" attributes for the "Boss."
In fact, we can see from the output that the "Boss" object correctly called upon the superclass "Employee" to store its name, age, and salary. The only thing we had to do was pass the necessary arguments for the "Boss" constructor.
- Polymorphism
Polymorphism is the idea that any class derived from another class can overwrite, or override, its parent's method(s). In the example shown above, we overrode the __str__()
method for the "Boss" class, making sure to add an extra part that mentions the Boss object's current employee. As can be seen by the output, the __str__()
method for the Boss object is successfully overriden, and the employee the "Boss" object hired is now listed.
Examples of Object-Oriented Databases
What, then, are some examples of object-oriented databases?
Here are some examples:
Name | Description |
---|---|
WakandaDB | Object database that works with JavaScript web applications. |
ObjectDB | Object database that works with Java applications. |
ZODB | Object database that works with Python objects (and the example this article uses). |
As you can see, many examples of object-oriented databases are often built to interact with certain object-oriented programming languages, blurring the line between programming language and database solution.
Object-Oriented vs. Relational
In contrast to object-oriented databases, relational databases store information in the form of relations - that is, tables and rows. Relational databases usually use SQL to interact with data, such as in PostgreSQL or MySQL.
Unlike in object-databases, relational databases use a standard querying language (i.e. SQL) to store and access data. For instance, to store the two employees listed above into a relational database (i.e. MySQL), one may have to write the following in SQL:
CREATE TABLE employees (
id INTEGER NOT NULL,
name TEXT NOT NULL,
age INTEGER NOT NULL,
salary INTEGER NOT NULL
);
CREATE TABLE bosses (
id INTEGER NOT NULL,
name TEXT NOT NULL,
age INTEGER NOT NULL,
salary INTEGER NOT NULL,
employee_id INTEGER
);
INSERT INTO employees VALUES(1, 'jane', 24, 87000);
INSERT INTO bosses VALUES(2, 'katie', 35, 230000, 1);
SELECT id, name, age, salary FROM employees
UNION
SELECT id, name, age, salary FROM bosses;
Note that, because the table "bosses" has a different number of columns than "employees," it becomes harder to try and display both employees' information fully. Any multi-table query will also require the UNION
keyword, like above.
When to Use Object-Oriented Databases
So when would it be best to use object-oriented databases?
Whenever you would need more esoteric data types or data types that require some form of inheritance (i.e. managing the salaries of a group of employees and their supervisers), the object-oriented database would come more in handy than a relational database. Modeling complex data types with object-oriented databases would serve to be very natural for any programmers steeped in object-oriented programming languages, such as Java and Python. Indeed, many of the object databases listed above are often made for such languages.
However, if object-oriented programming is not an issue for your application, then it becomes harder to justify the use of object databases. Also, if you need a certain kind of language standard, as with SQL, than an object-oriented database may not be the best solution for you. The SQL language can be applied to most relational database management systems, such as PostgreSQL and MySQL. However, the same cannot be said for object databases such as ZODB or ObjectDB, which have no "standard language." In addition, many of these object-oriented databases have comparatively less documentation and support compared to the larger and more popular relational databases, such as MySQL.
Exceptions
However, there have recently been technologies that have sought to combine the advantages of object-oriented databases and relational databases. One particularly famous example is the open-source relational database management system PostgreSQL.
PostgreSQL is primarily a relational database management system, as with other such systems such as MySQL. However, PostgreSQL offers some object-oriented features that make it easier to work with complex queries. For instance, PostgreSQL allows table inheritance. That is, one table can inherit the properties of another table, without the need for duplication. In addition, PostgreSQL provides users the ability to define their own data types or extend existing data types. These kinds of features are some of the ways that some database management solutions are attempting to apply the best of both worlds.
Our SQL example of employees and bosses can be rewritten in PostgreSQL:
CREATE TABLE employees (
id INTEGER NOT NULL,
name TEXT NOT NULL,
age INTEGER NOT NULL,
salary INTEGER NOT NULL
);
CREATE TABLE bosses (
employee_id INTEGER
) INHERITS (employees);
INSERT INTO employees VALUES(1, 'jane', 24, 87000);
INSERT INTO bosses VALUES(2, 'katie', 35, 230000, 1);
SELECT id, name, age, salary FROM employees;
Output:
id | name | age | salary
----+-------+-----+--------
1 | jane | 24 | 87000
2 | katie | 35 | 230000
(2 rows)
Conclusion
So, what have we learned?
- An object-oriented database is one that treats data as objects.
- An object-oriented database usually follows key object-oriented principles, such as polymorphism, inheritance, and encapsulation.
- There are many examples of object-oriented databases, often tailored to a specific object-oriented programming language.
- Object-oriented databases are often useful when dealing with complex or esoteric data types; however, there is no theoretical standard analogous to SQL.
- Recent database technologies are attempting to combine the best of object-oriented databases and relational databases.