One of the IOPC 2 library basic requirements is database independence. This can be achieved by separating the database access logic behind a shared interface.

The original POLiTe and the POLiTe 2 libraries access the database via such interface. The problem is that they contain several SQL statements outside the database layer code. These SQL statements are written for the Oracle 7 RDBMS and porting the library to another database system means to find and to update them. At the end, recompilation of the whole library is required.

The IOPC library tried to solve this issue by providing a new interface - the DatabaseSqlStatements class. Implementation of this interface encapsulates all SQL fragments needed by the library. Moving the library to another RDBMS became quite easy, but not as easy as it could be, because whole library needs to be recompiled every time a new driver is added or updated.

In the IOPC 2 library, database drivers are separated into shared libraries. The library provides a facility for managing and accessing these drivers. Adding or updating a database driver does not involve any modifications in the library code or its recompilation. Users can use more than one driver at a time. Even all SQL code is separated into the drivers.

If the user application needs to communicate with a database, it must be linked with the iopcdb library and with at least one driver. Currently, only Oracle 10g driver iopcdriver_oracle10g is implemented. Application can however use any number of linked drivers at a time. Drivers may be enhanced with several extensions. Extensions provide additional functionalities to them. Again, only one driver extension is implemented at the time - the iopcdriverex_oracle10g_or extension. It adds the iopcdriver_oracle10g driver support for O/R mapping.

Figure 5.2, “Basic classes of the database layer” shows an overview of basic classes and subsets of their methods.


DriverManager is a central part of the driver model. A single instance of this class holds references to all drivers loaded in a user application. Users can obtain reference to a database driver by calling its method getDriver(name). Database driver is represented as an instance of the Driver class.

Next three classes - the Database, Connection and Cursor can be found in all previous versions of the IOPC and POLiTe libraries. Their interfaces were slightly modified in IOPC 2 and implementation were moved from their subclasses to subclasses of the abstract classes (interfaces) DatabaseImpl, ConnectionImpl and CursorImpl. Each database driver must implement these interfaces.

The reason for almost duplicating the Database and Cursor interfaces is that they are used in a decorator pattern to modify effects of the methods they provide. As you may see in Figure 5.3, “Using the decorator pattern”, the classes CachedDatabase and CachedConnection are designed to decorate the BasicDatabase and BasicConnection classes. BasicConnection and BasicDatabase implement the basic database independent functionality, mostly the connection and cursor management. Database dependent operations are delegated to database drivers using the -Impl interface classes. The CachedDatabase and CachedConnection classes decorate behaviour of several fundamental methods such as commit or rollback by performing a caching related operations - e.g. writing modified local copies to a database before commit.


Example 5.1, “Connecting to an Oracle database in IOPC 2” shows how a connection to Oracle database instance "XE" can be made. First we create only a simple connection allowing only basic SQL statements to be executed, then we release this connection and create a new one using the CachedConnection decorator class. This connection can be used with the O/R mapping features, see later.


Driver features reflect differences between database systems. Different database systems provide different features or services. In IOPC 2, interfaces to such services(features) can be grouped into units called driver extensions. Modules of the IOPC 2 library define interfaces (representing the features) and database driver creators optionally implement them to their drivers or group them in driver extensions. The library then asks the drivers what features they offer. Based on the answers it enables or disables some of its functionalities provided.

Driver extensions are shared libraries that are linked together with the drivers and user applications. One such extension implemented for the Oracle 10g driver is iopcdriverex_oracle10g_or. It enhances the iopcdriver_oracle10g Oracle 10g driver with the support for object-relational mapping.

Features are descendants of the DbFeature abstract class. Features declared in the iopcdb library are:

As part of the iopclib library, there are additional features declared that are needed for the object-relational mapping proccess:

Figure 5.4, “Oracle 10g database driver extensions and driver features” illustrates how the driver features and extensions are used by the Oracle 10g database driver.