[ Team LiB ] Previous Section Next Section

8.4 In-Memory Versus Persistent Model Storage

All the examples to this point have used the memory model, but Jena also provides the capability to persist data to relational database storage. The databases supported are MySQL, PostgreSQL, Interbase, and Oracle. Within each database system, Jena also supports differing storage layouts:

Generic

All statements are stored in a single table, and resources and literals are indexed using integer identifiers generated by the database.

GenericProc

Similar to generic, but data access is through stored procedures.

MMGeneric

Similar to generic but can store multiple models.

Hash

Similar to generic but uses MD5 hashes to generate the identifiers.

MMHash

Similar to hash but can store multiple models.

The first step of storing a model in a database is to create the structure to store the data. The tables must be created in an already existing database, which has been formatted and had tables added. This code needs to be run once. After the database structure is created, it can then be opened directly in another application or used within the same application.

In Example 8-12, I'm storing two models in the database using a different name for each. In addition, I'm also creating the JDBC connection directly rather than having DBConnection create it for me. The model used is based on a MySQL database, using the MMGeneric layout. I'm not using the slightly more efficient hash method (MMHash), primarily because the generic layout is the better one to take if you're thinking of accessing the data directly through JDBC rather than through Jena.

At the time of this writing, using DBConnection to make the JDBC connection is failing in the second application to access the same database. Creating an instance of the JDBC connection and passing it in as a parameter to DBConnection averts this failure.

Once the database is formatted, two RDF/XML documents are opened and stored in two separate models within the database.

Example 8-12. Persisting two RDF/XML models to a MySQL database
import com.hp.hpl.mesa.rdf.jena.model.*;
import com.hp.hpl.mesa.rdf.jena.rdb.ModelRDB;
import com.hp.hpl.mesa.rdf.jena.rdb.DBConnection;
import java.sql.*;

public class pracRDFEighth extends Object {
    
    
public static void main (String args[]) {
    
// Pass two RDF documents, connection string,     
String sUri = args[0];
String sUri2 = args[1];
String sConn = args[2];
String sUser = args[3];
String sPass = args[4];
                             
try {
  // Load driver class
  Class.forName("com.mysql.jdbc.Driver").newInstance(  );

   // Establish connection - replace with your own conn info
   Connection con = DriverManager.getConnection(sConn, "user", "pass");
   DBConnection dbcon = new DBConnection(con);
   
   // Format database
   ModelRDB.create(dbcon, "MMGeneric", "Mysql"); 

   // Create and read first model
   ModelRDB model1 = ModelRDB.createModel(dbcon, "one");
   model1.read(sUri);

   // Create and read second model
   ModelRDB model2 = ModelRDB.createModel(dbcon, "two");
   model2.read(sUri2);

          
   } catch (Exception e) {
            System.out.println("Failed: " + e);
   }
 }  
}

The application expects the following command line:

java pracRDFEighth firstrdffile secondrdffile connect_string username password

You'll need to adjust the database connection string, username, and password to fit your environment. In the example, instead of reading the two models into separate databases, I could also have read them into the same database.

Once the model data is persisted, any number of applications can then access it. In Example 8-13, I'm accessing both models, dumping all of the objects in the first and writing out triples from the second.

Example 8-13. Accessing RDF models stored in MySQL database
import com.hp.hpl.mesa.rdf.jena.model.*;
import com.hp.hpl.mesa.rdf.jena.rdb.ModelRDB;
import com.hp.hpl.mesa.rdf.jena.rdb.DBConnection;
import java.sql.*;

public class pracRDFNinth extends Object {
    
    
public static void main (String args[]) {
    
String sConn = args[0];
String sUser = args[1];
String sPass = args[2];
                         
try {
  // load driver class
  Class.forName("com.mysql.jdbc.Driver").newInstance(  );

   // Establish connection - replace with your own conn info
     Connection con = DriverManager.getConnection(sConn, sUser, sPass);
   DBConnection dbcon = new DBConnection(con);

   // Open two existing models
   ModelRDB model1 = ModelRDB.open(dbcon, "one");
   ModelRDB model2 = ModelRDB.open(dbcon, "two");

   // Print out objects in first model using toString
   NodeIterator iter = model1.listObjects(  );
   while (iter.hasNext(  )) {
        System.out.println("  " + iter.next(  ).toString(  ));
   }

   // Print out triples in second model - find resource
   Resource res = model2.getResource("http://burningbird.net/articles/monsters1.htm");

   // Find properties
   StmtIterator sIter = res.listProperties(  );

   // Print out triple - subject | property | object
   while (sIter.hasNext(  )) {
        // Next statement in queue
        com.hp.hpl.mesa.rdf.jena.model.Statement stmt = sIter.next(  );

        // Get subject, print
        Resource res2 = stmt.getSubject(  );
        System.out.print(res2.getNameSpace(  ) + res2.getLocalName(  ));
        
        // Get predicate, print
        Property prop = stmt.getPredicate(  );
        System.out.print(" " + prop.getNameSpace(  ) + prop.getLocalName(  ));

        // Get object, print
        RDFNode node = stmt.getObject(  );
        System.out.println(" " + node.toString(  ) + "\n");
   }
          
   } catch (Exception e) {
            System.out.println("Failed: " + e);
   }
 }  
}

Jena uses a highly normalized data model for the RDF statements. In addition to accessing the data through the Jena API, you can also access it directly using whatever database connectivity you prefer. However, I recommend that you access the data for read-only purposes and leave updates to the Jena API.

    [ Team LiB ] Previous Section Next Section