Jena2 Database Interface - HowTo Create Persistent Models

28 August, 2003

The Jena2  persistent storage subsystem implements an extension of the Model class that provides transparent persistence for models through the use of a database engine. Three database engines are currently supported, MySQL, Oracle, PostgreSQL, on two platforms, Linux and WindowsXP. The Jena2 persistence subsystem is largely compatible with Jena1 but does not support the various Jena1 layouts. Existing Jena1 databases cannot be accessed by Jena2 and must be reloaded.

This document provides a brief overview of creating and accessing Jena2 persistent models. Note that the recommended mechanism for creating and opening persistent models has changed from Jena1 and also from the preliminary releases of Jena2. Users are now encouraged to use the new factory mechanisms described in model-factory. Previous mechanisms based on ModelRDB are now deprecated. However, the factory mechanism are still under development and are not yet a complete replacement for ModelRDB. Consequently, the deprecated Jena2 mechanisms may also be needed and are reviewed here as well.

The various options for configuring and accessing persistent models are described in Options.  For details on installing and configuring the various database engines for use with Jena2, see the database engine-specific howto documents ( MySQL-HowTo, Oracle-HowTo, PostgreSQL-HowTo).

Creating and Accessing Persistent Models

In Jena2, all databases are multi-model and each model is, by default, stored in separate tables. Models may share database tables using the StoreWithModel option. Currently, model names may be any string however users are encouraged to use URIs as model names for compatibility with planned future Jena features. Note that the model name "DEFAULT" is reserved for use by Jena (as the name of the default model) and attempts to create such a named model will cause an exception.

As mentioned above, there are two mechanisms for creating persistent models, one using factory methods and another using constructors for the ModelRDB class. However, the factory methods do not return a ModelRDB instance. Consequently, certain methods defined on ModelRDB are not available for factory-created models, e.g., remove, setDoDuplicateCheck. If an application needs these methods, the ModelRDB constructors should be used. This is an interim measure until the factory-created models support all the ModelRDB capabilities. Below we review creating and opening models for each mechanism.

Factory Methods

Creating or opening a model is a three-step process. First, the driver class must be loaded and a connection established to the database. Note that in Jena2, the database type is specified as part of the database connection unlike in Jena1 where it is part of the model constructor. Second, a model maker class is constructed. The model maker creates persistent instances of the Model class. Third, the model maker class is invoked to create new models or to open existing models. The following examples show how this is done.

static String M_DB_URL = "jdbc:mysql://localhost/test"; // database URL
static String M_DB_USER = "test";     // database user id
static String M_DB_PASSWD = "";   // database user password
static String M_DB = "MySQL";  // database engine
static String M_DBDRIVER_CLASS = "com.mysql.jdbc.Driver";  // database driver
// load the the driver class
Class.forName(M_DBDRIVER_CLASS);
// create a database connection
IDBConnection conn = new DBConnection(M_DB_URL, M_DB_USER, M_DB_PASSWD, M_DB);
// create a model maker with the given connection parameters
ModelMaker maker = ModelFactory.createModelRDBMaker(conn);
// create a default model
Model defModel = maker.createModel();
...
// create a named model
Model nmModel = maker.createModel("MyNamedModel");
...
// open a previously created model
Model prvModel = maker.openModel("AnExistingModel");

 

ModelRDB Methods

Database-backed RDF models are instances of the class jena.db.ModelRDB which supports the full jena.model.Model interface and also provides static methods to create, extend and reopen database instances. For backwards-compatibility, ModelRDB supports Jena1 methods for creating and opening databases (see release notes for details on changes).

ModelRDB supports several options (see HowTol). Some options alter the underlying database table structure and must be specified before the database is formatted. These methods are invoked on the underlying database driver instance for the connection. Ideally, the driver class need not be exposed to Jena applications. Consequently, use of the driver class to set these options should be considered an interim measure until the option setting can be integrated into the factory methods. See Enabling URI Compression for an example of setting these options. Other options apply to models. See Disable Duplicate Checking for an example of setting these types of options.

Creating an instance of ModelRDB is a two-step process. As with the factory methods, the first step is to load the driver class and establish a database connection. Second, the static methods on ModelRDB are used to create new ModelRDB instances or to open existing ones. The following examples show how this is done.

static String M_DB_URL = "jdbc:mysql://localhost/test"; // database URL
static String M_DB_USER = "test";     // database user id
static String M_DB_PASSWD = "";   // database user password
static String M_DB = "MySQL";  // database engine
static String M_DBDRIVER_CLASS = "com.mysql.jdbc.Driver";  // database driver
// load the the driver class
Class.forName(M_DBDRIVER_CLASS);
// create a database connection
IDBConnection conn = new DBConnection(M_DB_URL, M_DB_USER, M_DB_PASSWD, M_DB);
// create a default model
ModelRDB defModel = ModelRDB.createModel(conn);
...
// create a named model
ModelRDB nmModel = ModelRDB.createModel(conn,"MyModelName");
...
// open a previously created model
ModelRDB prvModel = maker.openModel(conn,"AnExistingModel");

Enable URI prefix compression

As an example of setting a database configuration option, the following shows how URI prefix compression is enabled. By default, URIs are stored fully expanded in the statement tables. Also shown is doubling the size of the prefix cache.

Class.forName(M_DBDRIVER_CLASS);
DBConnection dbcon = new DBConnection(M_DB_URL, M_DB_USER, M_DB_PASSWD, M_DB);
conn.getDriver().setDoCompressURI(true);
ModelRDB model = ModelRDB.createModel(dbcon, "myModelName");
// double the size of the prefix cache
int cacheSize = conn.getDriver().getCompressCacheSize();
conn.getDriver().setCompressCacheSize(cacheSize*2);

Detect multiple models per database

In Jena2, all databases are multi-model and each model is, by default, stored in separate tables. Here is an example that checks to see if a specific named model exists and then creates or reopens it as necessary:

Class.forName(M_DBDRIVER_CLASS);
DBConnection dbcon = new DBConnection(M_DB_URL, M_DB_USER, M_DB_PASSWD, M_DB);
ModelRDB model;
if( !dbcon.containsModel("myModelName")
	model = ModelRDB.createModel(dbcon, "myModelName");
else
	model = ModelRDB.open(dbcon, "myModelName");
Share tables among  models

In this example, a configuration option is used to specify that a new model should share the tables of an existing model. Unlike the previous option, this option can be set after the database is formatted. It affects only subsequently created models.

Class.forName(M_DBDRIVER_CLASS);
DBConnection dbcon = new DBConnection(M_DB_URL, M_DB_USER, M_DB_PASSWD, M_DB);
ModelRDB model1, model2;
model1 = ModelRDB.createModel(dbcon, "myModel1");  // create a new model model
conn.getDriver().setStoreWithModel("myModelName");
model2 = ModelRDB.createModel(dbcon, "myModel2"); // model2 is stored with model1

Disable duplicate checking

Some options apply to ModelRDB, e.g., query processing options. This example show how checking for duplicate statements can be disabled, as might be desirable when loading a large number of statements that the user is certain are duplicate-free.

Class.forName(M_DBDRIVER_CLASS);
DBConnection dbcon = new DBConnection(M_DB_URL, M_DB_USER, M_DB_PASSWD, M_DB);
ModelRDB model = ModelRDB.createModel(dbcon, "myModelName");
model.setDoDuplicateCheck(false);  // disable duplicate checking