Skip Headers
Oracle® Database Semantic Technologies Developer's Guide
11g Release 2 (11.2)

Part Number E11828-08
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

7 Jena Adapter for Oracle Database

The Jena Adapter for Oracle Database (referred to here as the Jena Adapter) provides a Java-based interface to Oracle Database Semantic Technologies by implementing the well-known Jena Graph and Model APIs. (Jena is an open source framework developed by Hewlett-Packard and is available under a BSD-style license.)

This chapter assumes that you are familiar with major concepts explained in Chapter 1, "Oracle Database Semantic Technologies Overview" and Chapter 2, "OWL Concepts". It also assumes that you are familiar with the overall capabilities and use of the Jena Java framework. For information about the Jena framework, see http://jena.sourceforge.net/, especially the Jena Documentation page.

The Jena Adapter extends the semantic data management capabilities of Oracle Database Release 11.2 RDF/OWL.

This chapter includes the following major topics:

Note:

An update of the Jena Adapter was made available in late October, 2009. For information about the new features in that update, see the "readme" file included in the download .zip file. (These new features are integrated into the content of this chapter.)

7.1 Setting Up the Software Environment

To use the Jena Adapter, you must first ensure that the system environment has the necessary software, including Oracle Database 11g Release 2 with the Spatial and Partitioning options and with Semantic Technologies support enabled, Jena version 2.6.2, the Jena Adapter, and JDK 1.5. You can set up the software environment by performing these actions:

  1. Install Oracle Database Release 11.2 Enterprise Edition with the Oracle Spatial and Partitioning Options.

  2. Enable the support for Semantic Technologies, as explained in Section A.1.

  3. Install Jena (version 2.6.2): download the .zip file from http://sourceforge.net/projects/jena/files/Jena/Jena-2.6.2/jena-2.6.2.zip/download and unzip it. (The directory or folder into which you unzip it will be referred to as <Jena_DIR>.)

    The Java package will be unpacked into <Jena_DIR>.

  4. Download the Jena Adapter (jena_adaptor_for_release11.2.zip) from the Oracle Database Semantic Technologies page (http://www.oracle.com/technology/tech/semantic_technologies/), and unzip it into a temporary directory, such as (on a Linux system) /tmp/jena_adapter. (If this temporary directory does not already exist, create it before the unzip operation.)

    The Jena Adapter directories and files have the following structure:

    examples/
       examples/Test10.java
       examples/Test11.java
       examples/Test12.java
       examples/Test13.java
       examples/Test14.java
       examples/Test15.java
       examples/Test16.java
       examples/Test17.java
       examples/Test18.java
       examples/Test19.java
       examples/Test20.java
       examples/Test6.java
       examples/Test7.java
       examples/Test8.java
       examples/Test9.java
       examples/Test.java
    jar/
       jar/sdordfclient.jar
    javadoc/
      javadoc/javadoc.zip
    joseki/
       joseki/index.html
       joseki/application.xml
       joseki/update.html
       joseki/xml-to-html.xsl
       joseki/joseki-config.ttl
    web/
      web/web.xml
    
  5. Copy ojdbc5.jar into <Jena_DIR>/lib (Linux) or <Jena_DIR>\lib (Windows). (ojdbc5.jar is in $ORACLE_HOME/jdbc/lib or %ORACLE_HOME%\jdbc\lib.)

  6. Copy sdordf.jar into <Jena_DIR>/lib (Linux) or <Jena_DIR>\lib (Windows). (sdordf.jar is in $ORACLE_HOME/md/jlib or %ORACLE_HOME%\md\jlib.)

  7. If JDK 1.5 is not already installed, install it.

  8. If the JAVA_HOME environment variable does not already refer to the JDK 1.5 installation, define it accordingly. For example:

    setenv JAVA_HOME /usr/local/packages/jdk15/
    
  9. If the SPARQL service to support the SPARQL protocol is not set up, set it up as explained in Section 7.2.

After setting up the software environment, ensure that your Semantic Technologies environment can enable you to use the Jena Adapter to perform queries, as explained in Section 7.3.

7.2 Setting Up the SPARQL Service

Setting up a SPARQL endpoint using the Jena Adapter involves downloading Joseki, an open source HTTP engine that supports the SPARQL protocol and SPARQL queries. This section explains how to set up a SPARQL service using a servlet deployed in WebLogic Server. The number and complexity of the steps reflect the fact that Oracle is not permitted to bundle all the dependent third-party libraries in a .war or .ear file.

  1. Download and Install Oracle WebLogic Server 11g Release 1 (10.3.1). For details, see http://www.oracle.com/technology/products/weblogic/.

  2. Ensure that you have Java 6 installed, because it is required by Joseki 3.4.0.

  3. Download Joseki 3.4.0 (joseki-3.4.0.zip) from http://sourceforge.net/projects/joseki/files/Joseki-SPARQL/.

  4. Unpack joseki-3.4.0.zip into a temporary directory. For example:

    mkdir /tmp/joseki
    cp joseki-3.4.0.zip /tmp/joseki
    cd /tmp/joseki
    unzip joseki-3.4.0.zip
    
  5. Ensure that you have downloaded and unzipped the Jena Adapter for Oracle Database, as explained in Section 7.1.

  6. Create a directory named joseki.war at the same level as the jena_adapter directory, and go to it. For example:

    mkdir /tmp/joseki.war
    cd /tmp/joseki.war
    
  7. Copy necessary files into the directory created in the preceding step:

    cp /tmp/jena_adapter/joseki/*  /tmp/joseki.war
    cp -rf /tmp/joseki/Joseki-3.4.0/webapps/joseki/StyleSheets  /tmp/joseki.war
    
  8. Create directories and copy necessary files into them, as follows:

    mkdir /tmp/joseki.war/WEB-INF
    cp /tmp/jena_adapter/web/*  /tmp/joseki.war/WEB-INF
     
    mkdir /tmp/joseki.war/WEB-INF/lib
    cp /tmp/joseki/Joseki-3.4.0/lib/*.jar   /tmp/joseki.war/WEB-INF/lib
    cp /tmp/jena_adapter/jar/*.jar   /tmp/joseki.war/WEB-INF/lib
    ##
    ## Assume ORACLE_HOME points to the home directory of a Release 11.2 Oracle Database.
    ##
    cp $ORACLE_HOME/md/jlib/sdordf.jar /tmp/joseki.war/WEB-INF/lib
    cp $ORACLE_HOME/jdbc/lib/ojdbc5.jar /tmp/joseki.war/WEB-INF/lib
    

    Note that in the last command, you can specify ojdbc6.jar instead of ojdbc5.jar if you are using JDK 6.

  9. Using the WebLogic Server Administration console, create a J2EE data source named OracleSemDS. During the data source creation, you can specify a user and password for the database schema that contains the relevant semantic data against which SPARQL queries are to be executed.

    If you need help in creating this data source, see Section 7.2.1, "Creating the Required Data Source Using WebLogic Server".

  10. Go to the autodeploy directory of WebLogic Server and copy files, as follows. (For information about auto-deploying applications in development domains, see: http://download.oracle.com/docs/cd/E11035_01/wls100/deployment/autodeploy.html)

    cd <domain_name>/autodeploy
    cp -rf  /tmp/joseki.war  <domain_name>/autodeploy
    

    In the preceding example, <domain_name> is the name of a WebLogic Server domain.

    Note that while you can run a WebLogic Server domain in two different modes, development and production, only development mode allows you use the auto-deployment feature.

  11. Check the files and the directory structure, as in the following example:

    autodeploy/% ls -1R ./joseki.war/
     
        ./joseki.war:
        application.xml
        index.html
        joseki-config.ttl
        StyleSheets/
        update.html
        WEB-INF/
        xml-to-html.xsl
     
        ./joseki.war/StyleSheets:
        joseki.css
     
        ./joseki.war/WEB-INF:
        lib/
        web.xml
     
        ./joseki.war/WEB-INF/lib:
        arq-2.8.0.jar
        arq-2.8.0-tests.jar
        icu4j-3.4.4.jar
        iri-0.7.jar
        jena-2.6.2.jar
        jenatest-2.6.2.jar
        jetty-6.1.10.jar
        jetty-util-6.1.10.jar
        joseki-3.4.0.jar
        junit-4.5.jar
        log4j-1.2.12.jar
        lucene-core-2.3.1.jar
        ojdbc5.jar
        sdordfclient.jar
        sdordf.jar
        servlet-api-2.5-6.1.10.jar
        servlet-api-2.5.jar
        slf4j-api-1.5.6.jar
        slf4j-log4j12-1.5.6.jar
        stax-api-1.0.1.jar
        wstx-asl-3.2.9.jar
        xercesImpl-2.7.1.jar
    
  12. Start or restart WebLogic Server.

  13. Verify your deployment by using your Web browser to connect to a URL in the following format (assume that the Web application is deployed at port 7001): http://<hostname>:7001/joseki

    You should see a page titled Oracle SPARQL Service Endpoint using Joseki, and the first text box should contain an example SPARQL query.

  14. Click Submit Query.

    You should see a page titled Oracle SPARQL Endpoint Query Results. There may or may not be any results, depending on the underlying semantic model against which the query is executed.

7.2.1 Creating the Required Data Source Using WebLogic Server

If you need help creating the required J2EE data source using the WebLogic Server admin console, you can follow these steps:

  1. Login to: http://<hostname>:7001/console

  2. In the Domain Structure panel, click Services.

  3. Click JDBC

  4. Click Data Services.

  5. In the Summary of JDBC Data Sources panel, click New under the Data Sources table.

  6. In the Create a New JDBC Data Source panel, enter or select the following values.

    Name: OracleSemDS

    JNDI Name: OracleSemDS

    Database Type: Oracle

    Database Driver: Oracle's Driver (Thin) Versions: 9.0.1,9.2.0,10,11

  7. Click Next twice.

  8. In the Connection Properties panel, enter the appropriate values for the Database Name, Host Name, Port, Database User Name (schema that contains semantic data), Password fields.

  9. Click Next.

  10. Select (check) the target server or servers) to which you want to deploy this OracleSemDS data source.

  11. Click Finish.

    You should see a message that all changes have been activated and no restart is necessary.

7.2.2 Configuring the SPARQL Service

By default, the SPARQL Service endpoint assumes that the queries are to be executed against a semantic model with a pre-set name. This semantic model is owned by the schema specified in the J2EE data source with JNDI name OracleSemDS. Note that you do not need to create this model explicitly using PL/SQL or Java; if the model does not exist in the network, it will be automatically created, along with the necessary application table and index.

However, you must configure the SPARQL service by editing the joseki-config.ttl configuration file, which is in <domain_name>/autodeploy/joseki.war.

The supplied joseki-config.ttl file includes a section similar to the following for the Oracle data set:

#
## Datasets
#
[] ja:loadClass "oracle.spatial.rdf.client.jena.assembler.OracleAssemblerVocab" .
 
oracle:Dataset  rdfs:subClassOf  ja:RDFDataset .
 
<#oracle> rdf:type oracle:Dataset;
    joseki:poolSize     1 ;         ## Number of concurrent connections allowed to this dataset.
    oracle:connection
    [ a oracle:OracleConnection ;
    ];
    oracle:defaultModel [ oracle:firstModel "TEST_MODEL" ] .

In this section of the file, you can:

  • Modify the joseki:poolSize value, which specifies the number of concurrent connections allowed to this Oracle data set (<#oracle> rdf:type oracle:Dataset;), which points to various RDF models in the database.

  • Modify the name (or the object value of oracle:firstModel predicate) of the defaultModel, to use a different semantic model for queries. You can also specify multiple models, and one or more rulebases for this defaultModel.

    For example, the following specifies two models (named ABOX and TBOX) and an OWLPRIME rulebase for the default model. Note that models specified using the oracle:modelName predicate must exist; they will not be created automatically.

    <#oracle> rdf:type oracle:Dataset;
        joseki:poolSize     1 ;         ## Number of concurrent connections allowed to this dataset.
        oracle:connection
        [ a oracle:OracleConnection ;
        ];
        oracle:defaultModel [ oracle:firstModel "ABOX";
                                          oracle:modelName "TBOX";
                                          oracle:rulebaseName "OWLPRIME" ] .
    
  • Use a virtual model for queries by adding oracle:useVM "TRUE", as shown in the following example. Note that if the specified virtual model does not exist, it will automatically be created on demand.

    <#oracle> rdf:type oracle:Dataset;
        joseki:poolSize     1 ;         ## Number of concurrent connections allowed to this dataset.
        oracle:connection
        [ a oracle:OracleConnection ;
        ];
        oracle:defaultModel [ oracle:firstModel "ABOX";
                                         oracle:modelName "TBOX";
                                         oracle:rulebaseName "OWLPRIME";
                                         oracle:useVM "TRUE"
        ] .
    

    For more information, see Section 7.8.1, "Virtual Models Support".

  • Set the queryOptions and inferenceMaintenance properties to change the query behavior and inference update mode. (See the Javadoc for information about QueryOptions and InferenceMaintenanceMode.)

    By default, QueryOptions.ALLOW_QUERY_INVALID_AND_DUP and InferenceMaintenanceMode.NO_UPDATE are set, for maximum query flexibility and efficiency.

7.2.3 Terminating Long-Running SPARQL Queries

Because some applications need to be able to terminate long-running SPARQL queries, an abort framework has been introduced with the Jena Adapter and the Joseki setup. Basically, for queries that may take a long time to run, you must stamp each with a unique query ID (qid) value.

For example, the following SPARQL query selects out the subject of all triples. A query ID (qid) is set so that this query can be terminated upon request.

PREFIX ORACLE_SEM_FS_NS:  <http://example.com/semtech#qid=8761>
SELECT ?subject WHERE {?subject ?property ?object }

The qid attribute value is of long integer type. You can choose a value for the qid for a particular query based on your own application needs.

To terminate a SPARQL query that has been submitted with a qid value, applications can send an abort request to a servlet in the following format and specify a matching QID value

http://<hostname>:7001/joseki/querymgt?abortqid=8761

7.3 Setting Up the Semantic Technologies Environment

To use the Jena Adapter to perform queries, you can connect as any user (with suitable privileges) and use any models in the semantic network. If your Semantic Technologies environment already meets the requirements, you can go directly to compiling and running Java code that uses the Jena Adapter. If your Semantic Technologies environment is not yet set up to be able to use the Jena Adapter, you can perform actions similar to the following example steps:

  1. Connect as SYS with the SYSDBA role:

    sqlplus sys/<password-for-sys> as sysdba
    
  2. Create a tablespace for the system tables. For example:

    CREATE TABLESPACE rdf_users datafile 'rdf_users01.dbf' 
        size 128M reuse autoextend on next 64M 
        maxsize unlimited segment space management auto;
    
  3. Create the semantic network. For example:

    EXECUTE sem_apis.create_sem_network('RDF_USERS');
    
  4. Create a database user (for connecting to the database to use the semantic network and the Jena Adapter). For example:

    CREATE USER rdfusr IDENTIFIED BY <password-for-udfusr>
                       DEFAULT TABLESPACE rdf_users;
    
  5. Grant the necessary privileges to this database user. For example:

    GRANT connect, resource TO rdfusr;
    
  6. To use the Jena Adapter with your own semantic data, perform the appropriate steps to store data, create a model, and create database indexes, as explained in Section 1.9, "Quick Start for Using Semantic Data". Then perform queries by compiling and running Java code; see Section 7.9 for information about example queries.

    To use the Jena Adapter with supplied example data, see Section 7.9.

7.4 SEM_MATCH and Jena Adapter Queries Compared

There are two ways to query semantic data stored in Oracle Database: SEM_MATCH-based SQL statements and SPARQL queries through the Jena Adapter. Queries using each approach are similar in appearance, but there are important behavioral differences. To ensure consistent application behavior, you must understand the differences and use care when dealing with query results coming from SEM_MATCH queries and SPARQL queries.

The following simple examples show the two approaches.

Query 1 (SEM_MATCH-based)

select s, p, o
    from table(sem_match('{?s ?p ?o}', sem_models('Test_Model'), ....))

Query 2 (SPARQL query through the Jena Adapter)

select ?s ?p ?o
where {?s ?p ?o}

These two queries perform the same kind of functions; however, there are some important differences. Query 1 (SEM_MATCH-based):

Query 2 (SPARQL query executed through the Jena Adapter) also reads all triples out of Test_Model (assume it is executed a call to ModelOracleSem referring to the same underlying Test_Model). However, Query 2:

Blank node handling is another difference between the two approaches:

The maximum length for the name of a semantic model created using the Jena Adapter API is 22 characters.

7.5 Optimized Handling of SPARQL Queries

This section describes some performance-related features of the Jena Adapter that can enhance SPARQL query processing. These features are performed automatically by default.

This section assumes that you are familiar with SPARQL, including the CONSTRUCT feature and property paths.

7.5.1 Compilation of SPARQL queries to a single SEM_MATCH Call

SPARQL queries involving DISTINCT, OPTIONAL, FILTER, UNION, ORDER BY, and LIMIT are converted to a single Oracle SEM_MATCH table function. If a query cannot be converted directly to SEM_MATCH because it uses SPARQL features not supported by SEM_MATCH (for example, CONSTRUCT), the Jena Adapter employs a hybrid approach and tries to execute the largest portion of the query using a single SEM_MATCH function while executing the rest using the Jena ARQ query engine.

For example, the following SPARQL query is directly translated to a single SEM_MATCH table function:

PREFIX dc:  <http://purl.org/dc/elements/1.1/> 
PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
PREFIX foaf: <http://xmlns.com/foaf/0.1/> 
SELECT ?person ?name 
  WHERE {
                 {?alice foaf:knows ?person . }
               UNION { 
                 ?person ?p ?name. OPTIONAL { ?person ?x ?name1 } 
                     }
        }

However, the following example query is not directly translatable to a single SEM_MATCH table function because of the CONSTRUCT keyword:

PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#> 
CONSTRUCT  { <http://example.org/person#Alice> vcard:FN ?obj } 
  WHERE  { { ?x <http://pred/a> ?obj.}
         UNION
         { ?x <http://pred/b> ?obj.}  }

In this case, the Jena Adapter converts the inner UNION query into a single SEM_MATCH table function, and then passes on the result set to the Jena ARQ query engine for further evaluation.

7.5.2 Optimized Handling of Property Paths

As defined in Jena, a property path is a possible route through an RDF graph between two graph nodes. Property paths are an extension of SPARQL and are more expressive than basic graph pattern queries, because regular expressions can be used over properties for pattern matching RDF graphs. For more information about property paths, see the documentation for the Jena ARQ query engine.

The Jena Adapter supports all Jena property path types through the integration with the Jena ARQ query engine, but it converts some common path types directly to native SQL hierarchical queries (not based on SEM_MATCH) to improve performance. The following types of property paths care directly converted to SQL by the Jena Adapter:

  • Predicate alternatives: (p1 | p2 | … | pn) where pi is a property URI

  • Predicate sequences: (p1 / p2 / … / pn) where pi is a property URI

  • Reverse paths : ( ^ p ) where p is a predicate URI

  • Complex paths: p+, p*, p{0, n} where p could be an alternative, sequence, reverse path, or property URI

Path expressions that cannot be captured in this grammar are not translated directly to SQL by the Jena Adapter, and they are answered using the Jena query engine.

The following example contains a code snippet using a property path expression with path sequences:

String m = "PROP_PATH";
 
ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, m);
 
GraphOracleSem graph = new GraphOracleSem(oracle, m);    
    
// populate the RDF Graph
    graph.add(Triple.create(Node.createURI("http://a"),
    Node.createURI("http://p1"),
    Node.createURI("http://b")));
 
graph.add(Triple.create(Node.createURI("http://b"),
 Node.createURI("http://p2"),
 Node.createURI("http://c")));
 
graph.add(Triple.create(Node.createURI("http://c"),
 Node.createURI("http://p5"),
 Node.createURI("http://d")));
 
String query =
" SELECT ?s  " +
" WHERE {?s (<http://p1>/<http://p2>/<http://p5>)+ <http://d>.}";
   
QueryExecution qexec = 
      QueryExecutionFactory.create(QueryFactory.create(query, 
 Syntax.syntaxARQ), model);
 
try {
  ResultSet results = qexec.execSelect();
  ResultSetFormatter.out(System.out, results);
}
finally {
  if (qexec != null)
    qexec.close();
}
     
OracleUtils.dropSemanticModel(oracle, m);
model.close();

7.5.3 Optimized Handling of Plain BGP and OPTIONAL Queries

The Jena Adapter automatically translates basic graph pattern (BGP) and parallel OPTIONAL queries directly to native SQL (not based on SEM_MATCH). The advantage of this approach is that you can specify directives such as RESULT_CACHE in the query to improve performance.

The following queries are translated directly to SQL:

  • Plain BGP queries. For example:

    SELECT ?x ?y WHERE {?x urn:a ?o. ?o ?p ?y}
    
  • Queries using parallel OPTIONAL clauses. For example:

    SELECT ?x ?y      
    WHERE {?x urn:a ?o. 
           OPTIONAL {?x urn:b ?b} 
           OPTIONAL {?x urn:c ?c} }
    
  • Queries using property paths (see Section 7.5.2, "Optimized Handling of Property Paths"). For example:

    SELECT ?x ?y  
    WHERE {?x urn:a ?o. OPTIONAL {?x urn:b* ?b} }
    

7.6 Additions to the SPARQL Syntax to Support Other Features

The Jena Adapter allows you to pass in hints and additional query options. It implements these capabilities by overloading the SPARQL namespace prefix syntax by using Oracle-specific namespaces that contain query options. The namespaces are in the form PREFIX ORACLE_SEM_xx_NS, where xx indicates the type of feature (such as HT for hint or AP for additional predicate)

7.6.1 SQL Hints

SQL hints can be passed to a SEM_MATCH query including a line in the following form:

PREFIX ORACLE_SEM_HT_NS: <http://oracle.com/semtech#hint>

Where hint can be any hint supported by SEM_MATCH. For example:

PREFIX ORACLE_SEM_HT_NS: <http://oracle.com/semtech#leading(t0,t1)> 
SELECT ?book ?title ?isbn     
WHERE { ?book <http://title> ?title. ?book <http://ISBN> ?isbn }

In this example, t0,t1 refers to the first and second patterns in the query.

Note the slight difference in specifying hints when compared to SEM_MATCH. Due to restrictions of namespace value syntax, a comma (,) must be used to separate t0 and t1 (or other hint components) instead of a space.

For more information about using SQL hints, see Section 1.6, "Using the SEM_MATCH Table Function to Query Semantic Data", specifically the material about the HINT0 keyword in the options attribute.

7.6.2 Additional WHERE Clause Predicates

The SEM_MATCH filter attribute can specify additional selection criteria as a string in the form of a WHERE clause without the WHERE keyword. Additional WHERE clause predicates can be passed to a SEM_MATCH query including a line in the following form:

PREFIX ORACLE_SEM_AP_NS: <http://oracle.com/semtech#pred>

Where pred reflects the WHERE clause content to be appended to the query. For example:

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX ORACLE_SEM_AP_NS:<http://www.oracle.com/semtech#label$RDFLANG='fr'>  
SELECT DISTINCT ?inst ?label
  WHERE { ?inst a <http://someCLass>. ?inst rdfs:label ?label . }
  ORDER BY (?label) LIMIT 20

In this example, a restriction is added to the query that the language type of the label variable must be 'fr'.

7.6.3 Additional Query Options

Additional query options can be passed to a SEM_MATCH query including a line in the following form:

PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#option>

Where option reflects a query option (or multiple query options delimited by commas) to be appended to the query. For example:

PREFIX ORACLE_SEM_FS_NS:   
<http://oracle.com/semtech#timeout=3,dop=4,INF_ONLY,ORDERED,ALLOW_DUP=T>
SELECT * WHERE {?subject ?property ?object }

The following query options are supported:

  • ALLOW_DUP=t chooses a faster way to query multiple semantic models, although duplicate results may occur.

  • DOP=n specifies the degree of parallelism (n) for the query. With multi-core or multi-CPU processors, experimenting with different DOP values (such as 4 or 8) may improve performance.

  • INF_ONLY causes only the inferred model to be queried.

  • JENA_EXECUTOR disables the compilation of SPARQL queries to SEM_MATCH (or native SQL); instead, the Jena native query executor will be used.

  • ORDERED is translated to a LEADING SQL hint for the query triple pattern joins, while performing the necessary RDF_VALUE$ joins last.

  • PLAIN_SQL_OPT=F disables the native compilation of queries directly to SQL.

  • QID=n specifies a query ID number; this feature can be used to cancel the query if it is not responding.

  • RESULT_CACHE uses the Oracle RESULT_CACHE directive for the query.

  • REWRITE=F disables ODCI_Table_Rewrite for the SEM_MATCH table function.

  • SKIP_CLOB=T causes CLOB values not to be returned for the query.

  • TIMEOUT=n (query timeout) specifies the number of seconds (n) that the query will run until it is terminated.

7.7 Functions Supported in SPARQL Queries through the Jena Adapter

SPARQL queries through the Jena Adapter can use the following kinds of functions:

7.7.1 Functions in the ARQ Function Library

SPARQL queries through the Jena Adapter can use functions in the function library of the Jena ARQ query engine. These queries are executed in the middle tier.

The following examples use the upper-case and namespace functions. In these examples, the prefix fn is <http://www.w3.org/2005/xpath-functions#> and the prefix afn is <http://jena.hpl.hp.com/ARQ/function#>.

PREFIX  fn: <http://www.w3.org/2005/xpath-functions#>
PREFIX  afn: <http://jena.hpl.hp.com/ARQ/function#>
SELECT (fn:upper-case(?object) as ?object1)
WHERE { ?subject dc:title ?object }

PREFIX  fn: <http://www.w3.org/2005/xpath-functions#>
PREFIX  afn: <http://jena.hpl.hp.com/ARQ/function#>
SELECT ?subject (afn:namespace(?object) as ?object1)
WHERE { ?subject <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?object } 

7.7.2 Native Oracle Database Functions for Projected Variables

SPARQL queries through the Jena Adapter can use native Oracle Database functions for projected variables. These queries and the functions are executed inside the database. Note that the functions described in this section should not be used together with ARQ functions (described in Section 7.7.1).

This section lists the supported native functions and provides some examples. In the examples, the prefix oext is <http://oracle.com/semtech/jena-adaptor/ext/function#>.

Note:

In the preceding URL, note the spelling jena-adaptor, which is retained for compatibility with existing applications and which must be used in queries. The adapter spelling is used in regular text, to follow Oracle documentation style guidelines.
  • oext:upper-literal converts literal values (except for long literals) to uppercase. For example:

    PREFIX  oext: <http://oracle.com/semtech/jena-adaptor/ext/function#>
    SELECT (oext:upper-literal(?object) as ?object1)
    WHERE { ?subject dc:title ?object }
    
  • oext:lower-literal converts literal values (except for long literals) to lowercase. For example:

    PREFIX  oext: <http://oracle.com/semtech/jena-adaptor/ext/function#>
    SELECT (oext:lower-literal(?object) as ?object1)
    WHERE { ?subject dc:title ?object }
    
  • oext:build-uri-for-id converts the value ID of a URI, bNode, or literal into a URI form. For example:

    PREFIX  oext: <http://oracle.com/semtech/jena-adaptor/ext/function#>
    SELECT (oext:build-uri-for-id(?object) as ?object1)
    WHERE { ?subject dc:title ?object }
    

    An example of the output might be: <rdfvid:1716368199350136353>

    One use of this function is to allow Java applications to maintain in memory a mapping of those value IDs to the lexical form of URIs, bNodes, or literals. The MDSYS.RDF_VALUE$ table provides such a mapping in Oracle Database.

    For a given variable ?var, if only oext:build-uri-for-id(?var) is projected, the query performance is likely to be faster because fewer internal table join operations are needed to answer the query.

  • oext:literal-strlen returns the length of literal values (except for long literals). For example:

    PREFIX  oext: <http://oracle.com/semtech/jena-adaptor/ext/function#>
    SELECT (oext:literal-strlen(?object) as ?objlen)
    WHERE { ?subject dc:title ?object }
    

7.7.3 User-Defined Functions

SPARQL queries through the Jena Adapter can use user-defined functions that are stored in the database.

In the following example, assume that you want to define a string length function (my_strlen) that handles long literals (CLOB) as well as short literals. On the SPARQL query side, this function can be referenced under the namespace of ouext, which is http://oracle.com/semtech/jena-adaptor/ext/user-def-function#.

PREFIX  ouext: <http://oracle.com/semtech/jena-adaptor/ext/user-def-function#>
SELECT ?subject ?object (ouext:my_strlen(?object) as ?obj1)
WHERE { ?subject dc:title ?object }

Inside the database, functions including my_strlen, my_strlen_cl, my_strlen_la, my_strlen_lt, and my_strlen_vt are defined to implement this capability. Conceptually, the return values of these functions are mapped as shown in Table 7-1.

Table 7-1 Functions and Return Values for my_strlen Example

Function Name Return Value

my_strlen

<VAR>

my_strlen_cl

<VAR>$RDFCLOB

my_strlen_la

<VAR>$RDFLANG

my_strlen_lt

<VAR>$RDFLTYP

my_strlen_vt

<VAR>$RDFVTYP


A set of functions (five in all) is used to implement a user-defined function that can be referenced from SPARQL, because this aligns with the internal representation of an RDF resource (in MDSYS.RDF_VALUE$). There are five major columns describing an RDF resource in terms of its value, language, literal type, long value, and value type, and these five columns can be selected out using SEM_MATCH. In this context, a user-defined function simply converts one RDF resource that is represented by five columns to another RDF resource.

These functions are defined as follows:

create or replace function my_strlen(rdfvtyp in varchar2,
                              rdfltyp in varchar2,
                              rdflang in varchar2,
                              rdfclob in clob,
                              value   in varchar2
                              ) return varchar2
 as
   ret_val  varchar2(4000);
 begin
   -- value
   if (rdfvtyp = 'LIT') then
     if (rdfclob is null) then
       return length(value);
     else
       return dbms_lob.getlength(rdfclob);
     end if;
   else
     -- Assign -1 for non-literal values so that application can
     -- easily differentiate
     return '-1';
   end if;
 end;
 /
 
 create or replace function my_strlen_cl(rdfvtyp in varchar2,
                              rdfltyp in varchar2,
                              rdflang in varchar2,
                              rdfclob in clob,
                              value   in varchar2
                              ) return clob
 as
 begin
   return null;
 end;
 /
 
 create or replace function my_strlen_la(rdfvtyp in varchar2,
                              rdfltyp in varchar2,
                              rdflang in varchar2,
                              rdfclob in clob,
                              value   in varchar2
                              ) return varchar2
 as
 begin
   return null;
 end;
 /
 
 create or replace function my_strlen_lt(rdfvtyp in varchar2,
                              rdfltyp in varchar2,
                              rdflang in varchar2,
                              rdfclob in clob,
                              value   in varchar2
                              ) return varchar2
 as
   ret_val  varchar2(4000);
 begin
   -- literal type
   return 'http://www.w3.org/2001/XMLSchema#integer';
 end;
 /
 
 create or replace function my_strlen_vt(rdfvtyp in varchar2,
                              rdfltyp in varchar2,
                              rdflang in varchar2,
                              rdfclob in clob,
                              value   in varchar2
                              ) return varchar2
 as
   ret_val  varchar2(3);
 begin
   return 'LIT';
 end;
 /

User-defined functions can also accept a parameter of VARCHAR2 type. The following five functions together define a my_shorten_str function that accepts an integer (in VARCHAR2 form) for the substring length and returns the substring. (The substring in this example is 12 characters, and it must not be greater than 4000 bytes.)

-- SPARQL query that returns the first 12 characters of literal values.
-- 
PREFIX  ouext: <http://oracle.com/semtech/jena-adaptor/ext/user-def-function#>
SELECT (ouext:my_shorten_str(?object, "12") as ?obj1) ?subject
WHERE { ?subject dc:title ?object }
 
create or replace function my_shorten_str(rdfvtyp in varchar2,
                            rdfltyp in varchar2,
                            rdflang in varchar2,
                            rdfclob in clob,
                            value   in varchar2,
                            arg     in varchar2
                            ) return varchar2
as
 ret_val  varchar2(4000);
begin
 -- value
 if (rdfvtyp = 'LIT') then
   if (rdfclob is null) then
     return substr(value, 1, to_number(arg));
   else
     return dbms_lob.substr(rdfclob, to_number(arg), 1);
   end if;
 else
   return null;
 end if;
end;
/
 
create or replace function my_shorten_str_cl(rdfvtyp in varchar2,
                            rdfltyp in varchar2,
                            rdflang in varchar2,
                            rdfclob in clob,
                            value   in varchar2,
                            arg     in varchar2
                            ) return clob
as
 ret_val  clob;
begin
 -- lob
 return null;
end;
/
 
create or replace function my_shorten_str_la(rdfvtyp in varchar2,
                            rdfltyp in varchar2,
                            rdflang in varchar2,
                            rdfclob in clob,
                            value   in varchar2,
                            arg     in varchar2
                            ) return varchar2
as
 ret_val  varchar2(4000);
begin
 -- lang
 if (rdfvtyp = 'LIT') then
   return rdflang;
 else
   return null;
 end if;
end;
/
 
create or replace function my_shorten_str_lt(rdfvtyp in varchar2,
                            rdfltyp in varchar2,
                            rdflang in varchar2,
                            rdfclob in clob,
                            value   in varchar2,
                            arg     in varchar2
                            ) return varchar2
as
 ret_val  varchar2(4000);
begin
 -- literal type
 ret_val := rdfltyp;
 return ret_val;
end;
/
 
create or replace function my_shorten_str_vt(rdfvtyp in varchar2,
                            rdfltyp in varchar2,
                            rdflang in varchar2,
                            rdfclob in clob,
                            value   in varchar2,
                            arg     in varchar2
                            ) return varchar2
as
 ret_val  varchar2(3);
begin
 return 'LIT';
end;
/

7.8 Support for Server-Side APIs

This section describes some of the Oracle Database Semantic Technologies features that are exposed by the Jena Adapter. For comprehensive documentation of the API calls that support the available features, see the Jena Adapter reference information (Javadoc). For additional information about the server-side features exposed by the Jena Adapter, see the relevant chapters in this manual.

7.8.1 Virtual Models Support

Virtual models (explained in Section 1.3.8) are specified in the GraphOracleSem constructor, and they are handled transparently. If a virtual model exists for the model-rulebase combination, it is used in query answering; if such a virtual model does not exist, it is created in the database.

Note:

Virtual model support through the Jena Adapter is available only with Oracle Database Release 11.2 or later.

The following example reuses an existing virtual model.

String modelName = "EX";
String m1 = "EX_1";
 
ModelOracleSem defaultModel = 
  ModelOracleSem.createOracleSemModel(oracle, modelName);
 
// create these models in case they don't exist
ModelOracleSem model1 = ModelOracleSem.createOracleSemModel(oracle, m1);
 
String vmName = "VM_" + modelName;
 
 
//create a virtual model containing EX and EX_1
oracle.executeCall(
"begin sem_apis.create_virtual_model(?,sem_models('"+ m1 + "','"+ modelName+"'),null); end;",vmName);
 
String[] modelNames = {m1};
String[] rulebaseNames = {};
 
Attachment attachment = Attachment.createInstance(modelNames, rulebaseNames, 
InferenceMaintenanceMode.NO_UPDATE, QueryOptions.ALLOW_QUERY_VALID_AND_DUP);
 
// vmName is passed to the constructor, so GraphOracleSem will use the virtual 
// model named vmname (if the current user has read privileges on it)
GraphOracleSem graph = new GraphOracleSem(oracle, modelName, attachment, vmName);
graph.add(Triple.create(Node.createURI("urn:alice"),
                        Node.createURI("http://xmlns.com/foaf/0.1/mbox"),
                        Node.createURI("mailto:alice@example")));
ModelOracleSem model = new ModelOracleSem(graph);          
 
String queryString =
 
   " SELECT ?subject ?object WHERE { ?subject ?p ?object } ";
 
Query query = QueryFactory.create(queryString) ;
QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
 
try {
   ResultSet results = qexec.execSelect() ;
   for ( ; results.hasNext() ; ) {
      QuerySolution soln = results.nextSolution() ;
      psOut.println("soln " + soln);
   }
} 
finally { 
   qexec.close() ; 
}
 
OracleUtils.dropSemanticModel(oracle, modelName);
OracleUtils.dropSemanticModel(oracle, m1);
 
oracle.dispose();

You can also use the GraphOracleSem constructor to create a virtual model, as in the following example:

GraphOracleSem graph = new GraphOracleSem(oracle, modelName, attachment, true);

In this example, the fourth parameter (true) specifies that a virtual model needs to be created for the specified modelName and attachment.

7.8.2 Connection Pooling Support

Oracle Database Connection Pooling is provided through the Jena Adapter OraclePool class. Once this class is initialized, it can return Oracle objects out of its pool of available connections. Oracle objects are essentially database connection wrappers. After dispose is called on the Oracle object, the connection is returned to the pool. More information about using OraclePool can be found in the API reference information (Javadoc).

The following example sets up an OraclePool object with five (5) initial connections.

public static void main(String[] args) throws Exception
  {      
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
 
    // test with connection properties 
    java.util.Properties prop = new java.util.Properties();
    prop.setProperty("MinLimit", "2");     // the cache size is 2 at least 
    prop.setProperty("MaxLimit", "10");
    prop.setProperty("InitialLimit", "2"); // create 2 connections at startup
    prop.setProperty("InactivityTimeout", "1800");    //  seconds
    prop.setProperty("AbandonedConnectionTimeout", "900");  //  seconds
    prop.setProperty("MaxStatementsLimit", "10");
    prop.setProperty("PropertyCheckInterval", "60"); // seconds
 
    System.out.println("Creating OraclePool");
    OraclePool op = new OraclePool(szJdbcURL, szUser, szPasswd, prop, 
               "OracleSemConnPool");
    System.out.println("Done creating OraclePool");
 
    // grab an Oracle and do something with it
    System.out.println("Getting an Oracle from OraclePool");
    Oracle oracle = op.getOracle();
    System.out.println("Done");
    System.out.println("Is logical connection:" +
        oracle.getConnection().isLogicalConnection());
    GraphOracleSem g = new GraphOracleSem(oracle, szModelName);
    g.add(Triple.create(Node.createURI("u:John"), 
                        Node.createURI("u:parentOf"), 
                        Node.createURI("u:Mary")));
    g.close();
    // return the Oracle back to the pool
    oracle.dispose();
    
    // grab another Oracle and do something else 
    System.out.println("Getting an Oracle from OraclePool");
    oracle = op.getOracle();
    System.out.println("Done");
    System.out.println("Is logical connection:" +
        oracle.getConnection().isLogicalConnection());
    g = new GraphOracleSem(oracle, szModelName);
    g.add(Triple.create(Node.createURI("u:John"), 
                        Node.createURI("u:parentOf"), 
                        Node.createURI("u:Jack")));
    g.close();
    
    OracleUtils.dropSemanticModel(oracle, szModelName); 
    
    // return the Oracle object back to the pool
    oracle.dispose();
    op.close();
}

7.8.3 Semantic Model PL/SQL Interfaces

Several semantic PL/SQL subprograms are available through the Jena Adapter. Table 7-2 lists the subprograms and their corresponding Java class and methods.

Table 7-2 PL/SQL Subprograms and Corresponding Jena Adapter Java Class and Methods

PL/SQL Subprogram Corresponding Java Class and Methods

SEM_APIS.DROP_SEM_MODEL

OracleUtils.dropSemanticModel

SEM_APIS.MERGE_MODELS

OracleUtils.mergeModels

SEM_APIS.SWAP_NAMES

OracleUtils.swapNames

SEM_APIS.REMOVE_DUPLICATES

OracleUtils.removeDuplicates

SEM_APIS.RENAME_MODEL

OracleUtils.renameModels


For information about these PL/SQL utility subprograms, see the reference information in Chapter 9. For information about the corresponding Java class and methods, see the Jena Adapter API Reference documentation (Javadoc).

7.8.4 Inference Options

You can add options to entailment calls by using the setInferenceOption(String options) procedure with the GraphOracleSem constructor. The following example enables incremental inference and specifies a parallelism value of 4 when creating an entailment.

graph.setInferenceOption("INC=T,DOP=4");

For information about inference options, see Section 2.2.

7.8.5 PelletInfGraph Class Support Deprecated

The support for the PelletInfGraph class within the Jena Adapter is deprecated. You should instead use the more optimized Oracle/Pellet integration through the PelletDb OWL 2 reasoner for Oracle Database 11g. (For information about PelletDb, see http://clarkparsia.com/pelletdb/.)

7.9 Example Queries Using the Jena Adapter

This section includes example queries using the Jena Adapter. Each example is self-contained: it typically creates a model, creates triples, performs a query that may involve inference, displays the result, and drops the model.

This section includes queries that do the following:

To run a query, you must do the following:

  1. Include the code in a Java source file. The examples used in this section are supplied in files in the examples directory of the Jena Adapter download.

  2. Compile the Java source file. For example:

    > javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test.java
    

    Note:

    The javac and java commands must each be on a single command line.
  3. Run the compiled file. For example:

    > java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
    

7.9.1 Test.java: Query Family Relationships

Example 7-1 specifies that John is the father of Mary, and it selects and displays the subject and object in each fatherOf relationship

Example 7-1 Query Family Relationships

import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.graph.*;
import com.hp.hpl.jena.query.*;
public class Test {
 
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
          
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    Model model = ModelOracleSem.createOracleSemModel(
      oracle, szModelName);
 
    model.getGraph().add(Triple.create(
          Node.createURI("http://example.com/John"),
          Node.createURI("http://example.com/fatherOf"),
          Node.createURI("http://example.com/Mary")));
    Query query = QueryFactory.create(
        "select ?f ?k WHERE {?f <http://example.com/fatherOf> ?k .}");
    QueryExecution qexec = QueryExecutionFactory.create(query, model);
    ResultSet results = qexec.execSelect();
    ResultSetFormatter.out(System.out, results, query);
    model.close();
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-1, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
 
---------------------------------------------------------
| f                         | k                         |
=========================================================
| <http://example.com/John> | <http://example.com/Mary> |
---------------------------------------------------------

7.9.2 Test6.java: Load OWL Ontology and Perform OWLPrime inference

Example 7-2 loads an OWL ontology and performs OWLPrime inference. Note that the OWL ontology is in RDF/XML format. and after it is loaded into Oracle it will be serialized out in N-TRIPLE form. The example also queries for the number of asserted and inferred triples.

The ontology in this example can be retrieved from http://www.lehigh.edu/~zhp2/2004/0401/univ-bench.owl, and it describes roles, resources, and relationships in a university environment.

Example 7-2 Load OWL Ontology and Perform OWLPrime inference

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import oracle.spatial.rdf.client.jena.*;
public class Test6 {
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    Model model = ModelOracleSem.createOracleSemModel(oracle, szModelName);
        
    // load UNIV ontology
    InputStream in = FileManager.get().open("./univ-bench.owl" );
    model.read(in, null);
    OutputStream os = new FileOutputStream("./univ-bench.nt");
    model.write(os, "N-TRIPLE");
    os.close();
 
    String queryString =
      " SELECT ?subject ?prop ?object WHERE { ?subject ?prop ?object } ";
 
    Query query = QueryFactory.create(queryString) ;
    QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
 
    try {
      int iTriplesCount = 0;
      ResultSet results = qexec.execSelect() ;
      for ( ; results.hasNext() ; ) {
        QuerySolution soln = results.nextSolution() ;
        iTriplesCount++;
      }
      System.out.println("Asserted  triples count: " + iTriplesCount);
    } 
    finally { 
      qexec.close() ; 
    }
    
    Attachment attachment = Attachment.createInstance(
        new String[] {}, "OWLPRIME",
        InferenceMaintenanceMode.NO_UPDATE, QueryOptions.DEFAULT);
 
    GraphOracleSem graph = new GraphOracleSem(oracle, szModelName, attachment);
    graph.analyze();
    graph.performInference();
 
    query = QueryFactory.create(queryString) ;
    qexec = QueryExecutionFactory.create(query,new ModelOracleSem(graph)) ;
 
    try {
      int iTriplesCount = 0;
      ResultSet results = qexec.execSelect() ;
      for ( ; results.hasNext() ; ) {
        QuerySolution soln = results.nextSolution() ;
        iTriplesCount++;
      }
      System.out.println("Asserted + Infered triples count: " + iTriplesCount);
    } 
    finally { 
      qexec.close() ; 
    }
    model.close();    
 
    OracleUtils.dropSemanticModel(oracle, szModelName);    
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-2, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test6.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test6 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
Asserted  triples count: 294
Asserted + Infered triples count: 341

Note that this output reflects an older version of the LUBM ontology. The latest version of the ontology has more triples.

7.9.3 Test7.java: Bulk Load OWL Ontology and Perform OWLPrime inference

Example 7-3 loads the same OWL ontology as in Section 7.9.2, but stored in a local file using Bulk Loader. Ontologies can also be loaded using an incremental and batch loader; these two methods are also listed in the example for completeness.

Example 7-3 Bulk Load OWL Ontology and Perform OWLPrime inference

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.graph.*;
import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.util.*;
import oracle.spatial.rdf.client.jena.*;
 
public class Test7 
{
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    // in memory Jena Model
    Model model = ModelFactory.createDefaultModel();
    InputStream is = FileManager.get().open("./univ-bench.owl");
    model.read(is, "", "RDF/XML");
    is.close();
 
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem modelDest = ModelOracleSem.createOracleSemModel(oracle, 
szModelName);
 
    GraphOracleSem g = modelDest.getGraph();
    g.dropApplicationTableIndex();
 
    int method = 2; // try bulk loader
    String tbs = "SYSAUX"; // can be customized
    if (method == 0) {
      System.out.println("start incremental");
      modelDest.add(model);
      System.out.println("end size " + modelDest.size());
    }
    else if (method == 1) {
      System.out.println("start batch load");
      g.getBulkUpdateHandler().addInBatch(
          GraphUtil.findAll(model.getGraph()), tbs);
      System.out.println("end size " + modelDest.size());
    }
    else {
      System.out.println("start bulk load");
      g.getBulkUpdateHandler().addInBulk(
          GraphUtil.findAll(model.getGraph()), tbs);
      System.out.println("end size " + modelDest.size());
    }
    g.rebuildApplicationTableIndex();
 
    long lCount = g.getCount(Triple.ANY);
    System.out.println("Asserted  triples count: " + lCount);
    model.close();    
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-3, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test7.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test7 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
start bulk load
end size 293
Asserted  triples count: 293

Note that this output reflects an older version of the LUBM ontology. The latest version of the ontology has more triples.

7.9.4 Test8.java: SPARQL OPTIONAL Query

Example 7-4 shows a SPARQL OPTIONAL query. It inserts triples that postulate the following:

  • John is a parent of Mary.

  • John is a parent of Jack.

  • Mary is a parent of Jill.

It then finds parent-child relationships, optionally including any grandchild (gkid) relationships.

Example 7-4 SPARQL OPTIONAL Query

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
 
public class Test8 
{
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, 
szModelName);
    GraphOracleSem g = model.getGraph();
 
    g.add(Triple.create(
          Node.createURI("u:John"), Node.createURI("u:parentOf"), 
Node.createURI("u:Mary")));
    g.add(Triple.create(
          Node.createURI("u:John"), Node.createURI("u:parentOf"), 
Node.createURI("u:Jack")));
    g.add(Triple.create(
          Node.createURI("u:Mary"), Node.createURI("u:parentOf"), 
Node.createURI("u:Jill")));
        
    String queryString =
  " SELECT ?s ?o ?gkid " +
  " WHERE { ?s <u:parentOf> ?o . OPTIONAL {?o <u:parentOf> ?gkid }} ";
 
    Query query = QueryFactory.create(queryString) ;
    QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
 
    try {
      int iMatchCount = 0;
      ResultSet results = qexec.execSelect() ;
      ResultSetFormatter.out(System.out, results, query);
    } 
    finally { 
      qexec.close() ; 
    }
    model.close();    
 
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-4, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test8.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test8 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
----------------------------------
| s        | o        | gkid     |
==================================
| <u:John> | <u:Mary> | <u:Jill> |
| <u:Mary> | <u:Jill> |          |
| <u:John> | <u:Jack> |          |
---------------------------------- 

7.9.5 Test9.java: SPARQL Query with LIMIT and OFFSET

Example 7-5 shows a SPARQL query with LIMIT and OFFSET. It inserts triples that postulate the following:

  • John is a parent of Mary.

  • John is a parent of Jack.

  • Mary is a parent of Jill.

It then finds one parent-child relationship (LIMIT 1), skipping the first two parent-child relationships encountered (OFFSET 2), and optionally includes any grandchild (gkid) relationships for the one found.

Example 7-5 SPARQL Query with LIMIT and OFFSET

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
public class Test9 
{
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, 
szModelName);
    GraphOracleSem g = model.getGraph();
 
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"),
                    Node.createURI("u:Mary")));
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"),
                    Node.createURI("u:Jack")));
    g.add(Triple.create(Node.createURI("u:Mary"), Node.createURI("u:parentOf"),              
                    Node.createURI("u:Jill")));
        
    String queryString =
      " SELECT ?s ?o ?gkid " +
      " WHERE { ?s <u:parentOf> ?o . OPTIONAL {?o <u:parentOf> ?gkid }} " +
      " LIMIT 1 OFFSET 2";
 
    Query query = QueryFactory.create(queryString) ;
    QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
 
    int iMatchCount = 0;
    ResultSet results = qexec.execSelect() ;
    ResultSetFormatter.out(System.out, results, query);
    qexec.close() ; 
    model.close();    
 
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-5, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test9.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test9 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
------------------------------
| s        | o        | gkid |
==============================
| <u:John> | <u:Jack> |      |
------------------------------ 

7.9.6 Test10.java: SPARQL Query with TIMEOUT and DOP

Example 7-6 shows the SPARQL query from Section 7.9.5 with additional features, including a timeout setting (TIMEOUT=1, in seconds) and parallel execution setting (DOP=4).

Example 7-6 SPARQL Query with TIMEOUT and DOP

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
 
public class Test10 {
  public static void main(String[] args) throws Exception  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, szModelName);
    GraphOracleSem g = model.getGraph();
 
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"), 
                            Node.createURI("u:Mary")));
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"), 
                        Node.createURI("u:Jack")));
    g.add(Triple.create(Node.createURI("u:Mary"), Node.createURI("u:parentOf"), 
                        Node.createURI("u:Jill")));
    String queryString =
        " PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#dop=4,timeout=1> " 
      + " SELECT ?s ?o ?gkid WHERE { ?s <u:parentOf> ?o . " 
      + " OPTIONAL {?o <u:parentOf> ?gkid }} "
      + " LIMIT 1 OFFSET 2";
 
    Query query = QueryFactory.create(queryString) ;
    QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
 
    int iMatchCount = 0;
    ResultSet results = qexec.execSelect() ;
    ResultSetFormatter.out(System.out, results, query);
    qexec.close() ; 
    model.close();    
 
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-6, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test10.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test10 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
------------------------------
| s        | o        | gkid |
==============================
| <u:Mary> | <u:Jill> |      |
------------------------------

7.9.7 Test11.java: Query Involving Named Graphs

Example 7-7 shows a query involving named graphs. It involves a default model that has information about named graph URIs and their publishers. The query finds graph names, their publishers, and within each named graph finds the mailbox value using the foaf:mbox predicate.

Example 7-7 Named Graph Based Query

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
 
public class Test11
{
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    DataSource ds = DatasetFactory.create();
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, szModelName);
    model.getGraph().add(Triple.create(Node.createURI("http://example.org/bob"),
          Node.createURI("http://purl.org/dc/elements/1.1/publisher"),
          Node.createLiteral("Bob Hacker")));
    model.getGraph().add(Triple.create(Node.createURI("http://example.org/alice"),
          Node.createURI("http://purl.org/dc/elements/1.1/publisher"),
          Node.createLiteral("alice Hacker")));
 
 
    ModelOracleSem model1 = ModelOracleSem.createOracleSemModel(oracle,
 szModelName+"1");
 
    model1.getGraph().add(Triple.create(Node.createURI("urn:bob"),
                                        Node.createURI("http://xmlns.com/foaf/0.1/name"),
                                    Node.createLiteral("Bob")));
    model1.getGraph().add(Triple.create(Node.createURI("urn:bob"),
                                     Node.createURI("http://xmlns.com/foaf/0.1/mbox"),
                                     Node.createURI("mailto:bob@example")));
 
    ModelOracleSem model2 = ModelOracleSem.createOracleSemModel(oracle,
            szModelName+"2");
    model2.getGraph().add(Triple.create(Node.createURI("urn:alice"),
                                        Node.createURI("http://xmlns.com/foaf/0.1/name"),
                                    Node.createLiteral("Alice")));
    model2.getGraph().add(Triple.create(Node.createURI("urn:alice"),
                                        Node.createURI("http://xmlns.com/foaf/0.1/mbox"),
                                    Node.createURI("mailto:alice@example")));
 
    ds.setDefaultModel(model);
    ds.addNamedModel("http://example.org/bob",model1);
    ds.addNamedModel("http://example.org/alice",model2);
 
    String queryString =  
      " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
    + " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
    + " SELECT ?who ?graph ?mbox "
    + " FROM NAMED <http://example.org/alice> "
    + " FROM NAMED <http://example.org/bob> "
    + " WHERE "
    + " { " 
    + "    ?graph dc:publisher ?who . "
    + "    GRAPH ?graph { ?x foaf:mbox ?mbox } "
    + " } ";
 
    Query query = QueryFactory.create(queryString) ;
    QueryExecution qexec = QueryExecutionFactory.create(query, ds) ;
 
    ResultSet results = qexec.execSelect() ;
    ResultSetFormatter.out(System.out, results, query);
    
    qexec.close();
    model.close();    
    model1.close();    
    model2.close();    
 
    OracleUtils.dropSemanticModel(oracle, szModelName);
    OracleUtils.dropSemanticModel(oracle, szModelName + "1");
    OracleUtils.dropSemanticModel(oracle, szModelName + "2");
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-7, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test11.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test11 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
------------------------------------------------------------------------
| who            | graph                      | mbox                   |
========================================================================
| "alice Hacker" | <http://example.org/alice> | <mailto:alice@example> |
| "Bob Hacker"   | <http://example.org/bob>   | <mailto:bob@example>   |
------------------------------------------------------------------------

7.9.8 Test12.java: SPARQL ASK Query

Example 7-8 shows a SPARQL ASK query. It inserts a triple that postulates that John is a parent of Mary. It then finds whether John is a parent of Mary.

Example 7-8 SPARQL ASK Query

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
public class Test12
{
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, 
          szModelName);
    GraphOracleSem g = model.getGraph();
 
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"), 
                        Node.createURI("u:Mary")));
    String queryString = " ASK { <u:John> <u:parentOf> <u:Mary> } ";
 
    Query query = QueryFactory.create(queryString) ;
    QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
    boolean b = qexec.execAsk();
    System.out.println("ask result = " + ((b)?"TRUE":"FALSE"));
    qexec.close() ; 
    
    model.close();    
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-8, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test12.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test12 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
ask result = TRUE

7.9.9 Test13.java: SPARQL DESCRIBE Query

Example 7-9 shows a SPARQL DESCRIBE query. It inserts triples that postulate the following:

  • John is a parent of Mary.

  • John is a parent of Jack.

  • Amy is a parent of Jack.

It then finds all relationships that involve any parents of Jack.

Example 7-9 SPARQL DESCRIBE Query

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
 
public class Test13
{
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, szModelName);
    GraphOracleSem g = model.getGraph();
 
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"), 
                    Node.createURI("u:Mary")));
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"), 
 Node.createURI("u:Jack")));
    g.add(Triple.create(Node.createURI("u:Amy"), Node.createURI("u:parentOf"), 
 Node.createURI("u:Jack")));
    String queryString = " DESCRIBE ?x WHERE {?x <u:parentOf> <u:Jack>}";
 
    Query query = QueryFactory.create(queryString) ;
    QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
    Model m = qexec.execDescribe();
    System.out.println("describe result = " + m.toString());
 
    qexec.close() ; 
    model.close();    
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-9, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test13.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test13 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
describe result = <ModelCom   {u:Amy @u:parentOf u:Jack; u:John @u:parentOf u:Jack; u:John @u:parentOf u:Mary} | >

7.9.10 Test14.java: SPARQL CONSTRUCT Query

Example 7-10 shows a SPARQL CONSTRUCT query. It inserts triples that postulate the following:

  • John is a parent of Mary.

  • John is a parent of Jack.

  • Amy is a parent of Jack.

  • Each parent loves all of his or her children.

It then constructs an RDF graph with information about who loves whom.

Example 7-10 SPARQL CONSTRUCT Query

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
 
public class Test14
{
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, szModelName);
    GraphOracleSem g = model.getGraph();
 
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"), 
 Node.createURI("u:Mary")));
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"), 
 Node.createURI("u:Jack")));
    g.add(Triple.create(Node.createURI("u:Amy"), Node.createURI("u:parentOf"), 
 Node.createURI("u:Jack")));
    String queryString = " CONSTRUCT { ?s <u:loves> ?o } WHERE {?s <u:parentOf> ?o}";
 
    Query query = QueryFactory.create(queryString) ;
    QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
    Model m = qexec.execConstruct();
    System.out.println("Construct result = " + m.toString());
 
    qexec.close() ; 
    model.close();    
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-10, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test14.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test14 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
Construct result = <ModelCom   {u:Amy @u:loves u:Jack; u:John @u:loves u:Jack; u:John @u:loves u:Mary} | >

7.9.11 Test15.java: Query Multiple Models and Specify "Allow Duplicates"

Example 7-11 queries multiple models and uses the "allow duplicates" option. It inserts triples that postulate the following:

  • John is a parent of Jack (in Model 1).

  • Mary is a parent of Jack (in Model 2).

  • Each parent loves all of his or her children.

It then finds out who loves whom. It searches both models and allows for the possibility of duplicate triples in the models (although there are no duplicates in this example).

Example 7-11 Query Multiple Models and Specify "Allow Duplicates"

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
 
public class Test15
{
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName1 = args[3];
    String szModelName2 = args[4];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem model1 = ModelOracleSem.createOracleSemModel(oracle, szModelName1);
    model1.getGraph().add(Triple.create(Node.createURI("u:John"), 
                     Node.createURI("u:parentOf"), Node.createURI("u:Jack")));
    model1.close();
 
    ModelOracleSem model2 = ModelOracleSem.createOracleSemModel(oracle, szModelName2);
    model2.getGraph().add(Triple.create(Node.createURI("u:Mary"), 
                     Node.createURI("u:parentOf"), Node.createURI("u:Jack")));
    model2.close();
 
    String[] modelNamesList = {szModelName2};
    String[] rulebasesList  = {};
    Attachment attachment = Attachment.createInstance(modelNamesList, rulebasesList, 
              InferenceMaintenanceMode.NO_UPDATE,
              QueryOptions.ALLOW_QUERY_VALID_AND_DUP);
 
    GraphOracleSem graph = new GraphOracleSem(oracle, szModelName1, attachment);
    ModelOracleSem model = new ModelOracleSem(graph);
 
    String queryString = " CONSTRUCT { ?s <u:loves> ?o } WHERE {?s <u:parentOf> ?o}";
    Query query = QueryFactory.create(queryString) ;
    QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
    Model m = qexec.execConstruct();
    System.out.println("Construct result = " + m.toString());
 
    qexec.close() ; 
    model.close();    
    OracleUtils.dropSemanticModel(oracle, szModelName1);
    OracleUtils.dropSemanticModel(oracle, szModelName2);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-11, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test15.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test15 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1 M2
Construct result = <ModelCom   {u:Mary @u:loves u:Jack; u:John @u:loves u:Jack} | >

7.9.12 Test16.java: SPARUL (SPARQL Update) Example

Example 7-12 inserts two triples into a model.

Example 7-12 SPARUL (SPARQL Update) Example

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.util.iterator.*;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
import com.hp.hpl.jena.update.*;
 
public class Test16
{
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, szModelName);
    GraphOracleSem g = model.getGraph();
    String insertString =  
      " PREFIX dc: <http://purl.org/dc/elements/1.1/> "         + 
      " INSERT DATA "                                           +
      " { <http://example/book3> dc:title    \"A new book\" ; " +
      "                         dc:creator  \"A.N.Other\" . "   + 
      " }   ";
 
    UpdateAction.parseExecute(insertString,  model);
    ExtendedIterator ei = GraphUtil.findAll(g);
    while (ei.hasNext()) {
      System.out.println("Triple " + ei.next().toString());
    }
    model.close();    
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-12, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test16.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test16 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
Triple http://example/book3 @dc:title "A new book"
Triple http://example/book3 @dc:creator "A.N.Other"

7.9.13 Test17.java: SPARQL Query with ARQ Built-In Functions

Example 7-13 inserts data about two books, and it displays the book titles in all uppercase characters and the length of each title string.

Example 7-13 SPARQL Query with ARQ Built-In Functions

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.util.iterator.*;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
import com.hp.hpl.jena.update.*;
 
public class Test17 {
  public static void main(String[] args) throws Exception  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, szModelName);
    GraphOracleSem g = model.getGraph();
    String insertString =  
      " PREFIX dc: <http://purl.org/dc/elements/1.1/> "         + 
      " INSERT DATA "                                           +
      " { <http://example/book3> dc:title    \"A new book\" ; " +
      "                         dc:creator  \"A.N.Other\" . "   + 
      "   <http://example/book4> dc:title    \"Semantic Web Rocks\" ; " +
      "                         dc:creator  \"TB\" . "   + 
      " }   ";
 
    UpdateAction.parseExecute(insertString,  model);
    String queryString = "PREFIX  dc:   <http://purl.org/dc/elements/1.1/> " +
      " PREFIX  fn: <http://www.w3.org/2005/xpath-functions#> " + 
      " SELECT ?subject (fn:upper-case(?object) as ?object1)  " + 
      "                 (fn:string-length(?object) as ?strlen) " + 
      " WHERE { ?subject dc:title ?object } " 
      ;
    Query query = QueryFactory.create(queryString, Syntax.syntaxARQ);
    QueryExecution qexec = QueryExecutionFactory.create(query, model);
    ResultSet results = qexec.execSelect();
    ResultSetFormatter.out(System.out, results, query);
    model.close();    
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-13, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test17.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test17 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
----------------------------------------------------------
| subject                | object1              | strlen |
==========================================================
| <http://example/book3> | "A NEW BOOK"         | 10     |
| <http://example/book4> | "SEMANTIC WEB ROCKS" | 18     |
----------------------------------------------------------

7.9.14 Test18.java: SELECT Cast Query

Example 7-14 "converts" two Fahrenheit temperatures (18.1 and 32.0) to Celsius temperatures.

Example 7-14 SELECT Cast Query

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.util.iterator.*;
import oracle.spatial.rdf.client.jena.*;
import com.hp.hpl.jena.graph.*;
import com.hp.hpl.jena.update.*;
 
public class Test18 {
  public static void main(String[] args) throws Exception  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
    
    Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd);
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, 
szModelName);
    GraphOracleSem g = model.getGraph();
    String insertString =  
      " PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> " +
      " INSERT DATA "                                     +
      " { <u:Object1> <u:temp>    \"18.1\"^^xsd:float ; " +
      "               <u:name>    \"Foo... \" . "         + 
      "   <u:Object2> <u:temp>    \"32.0\"^^xsd:float ; " +
      "               <u:name>    \"Bar... \" . "         + 
      " }   ";
 
    UpdateAction.parseExecute(insertString,  model);
    String queryString = 
      " PREFIX  fn: <http://www.w3.org/2005/xpath-functions#> " + 
      " SELECT ?subject ((?temp - 32.0)*5/9 as ?celsius_temp) " +
      "WHERE { ?subject <u:temp> ?temp } " 
      ;
    Query query = QueryFactory.create(queryString, Syntax.syntaxARQ);
    QueryExecution qexec = QueryExecutionFactory.create(query, model);
    ResultSet results = qexec.execSelect();
    ResultSetFormatter.out(System.out, results, query);
 
    model.close();    
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-14, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test18.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test18 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
------------------------------------------------------------------------
| subject     | celsius_temp                                           |
========================================================================
| <u:Object1> | "-7.7222223"^^<http://www.w3.org/2001/XMLSchema#float> |
| <u:Object2> | "0.0"^^<http://www.w3.org/2001/XMLSchema#float>        |
------------------------------------------------------------------------

7.9.15 Test19.java: Instantiate Oracle Database Using OracleConnection

Example 7-15 shows a different way to instantiate an Oracle object using a given OracleConnection object. (In a J2EE Web application, users can normally get an OracleConnection object from a J2EE data source.)

Example 7-15 Instantiate Oracle Database Using OracleConnection

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.util.iterator.*;
import com.hp.hpl.jena.graph.*;
import com.hp.hpl.jena.update.*;
import oracle.spatial.rdf.client.jena.*;
import oracle.jdbc.pool.*;
import oracle.jdbc.*;
        
public class Test19 {
  public static void main(String[] args) throws Exception {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
 
    OracleDataSource ds = new OracleDataSource();
    ds.setURL(szJdbcURL);
    ds.setUser(szUser);
    ds.setPassword(szPasswd);
    OracleConnection conn = (OracleConnection) ds.getConnection();
    Oracle oracle = new Oracle(conn);
 
    ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, 
szModelName);
    GraphOracleSem g = model.getGraph();
 
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"), 
                        Node.createURI("u:Mary")));
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"),   
                        Node.createURI("u:Jack")));
    g.add(Triple.create(Node.createURI("u:Mary"), Node.createURI("u:parentOf"), 
         Node.createURI("u:Jill")));
    String queryString =
       " SELECT ?s ?o  WHERE { ?s <u:parentOf> ?o .} ";
    Query query = QueryFactory.create(queryString) ;
    QueryExecution qexec = QueryExecutionFactory.create(query, model) ;
 
    ResultSet results = qexec.execSelect() ;
    ResultSetFormatter.out(System.out, results, query);
    qexec.close() ; 
    model.close();    
    OracleUtils.dropSemanticModel(oracle, szModelName);
    oracle.dispose();
  }
}

The following are the commands to compile and run Example 7-15, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test19.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test19 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
-----------------------
| s        | o        |
=======================
| <u:John> | <u:Mary> |
| <u:John> | <u:Jack> |
| <u:Mary> | <u:Jill> |
-----------------------

7.9.16 Test20.java: Oracle Database Connection Pooling

Example 7-16 uses Oracle Database connection pooling.

Example 7-16 Oracle Database Connection Pooling

import java.io.*;
import com.hp.hpl.jena.query.*;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.util.iterator.*;
import com.hp.hpl.jena.graph.*;
import com.hp.hpl.jena.update.*;
import oracle.spatial.rdf.client.jena.*;
import oracle.jdbc.pool.*;
import oracle.jdbc.*;
 
public class Test20
{
  public static void main(String[] args) throws Exception
  {
    String szJdbcURL = args[0];
    String szUser    = args[1];
    String szPasswd  = args[2];
    String szModelName = args[3];
 
    // test with connection properties (taken from some example)
    java.util.Properties prop = new java.util.Properties();
    prop.setProperty("MinLimit", "2");     // the cache size is 2 at least 
    prop.setProperty("MaxLimit", "10");
    prop.setProperty("InitialLimit", "2"); // create 2 connections at startup
    prop.setProperty("InactivityTimeout", "1800");    //  seconds
    prop.setProperty("AbandonedConnectionTimeout", "900");  //  seconds
    prop.setProperty("MaxStatementsLimit", "10");
    prop.setProperty("PropertyCheckInterval", "60"); // seconds
 
    System.out.println("Creating OraclePool");
    OraclePool op = new OraclePool(szJdbcURL, szUser, szPasswd, prop, 
               "OracleSemConnPool");
    System.out.println("Done creating OraclePool");
 
    // grab an Oracle and do something with it
    System.out.println("Getting an Oracle from OraclePool");
    Oracle oracle = op.getOracle();
    System.out.println("Done");
    System.out.println("Is logical connection:" +
        oracle.getConnection().isLogicalConnection());
    GraphOracleSem g = new GraphOracleSem(oracle, szModelName);
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"), 
                        Node.createURI("u:Mary")));
    g.close();
    // return the Oracle back to the pool
    oracle.dispose();
    
    // grab another Oracle and do something else 
    System.out.println("Getting an Oracle from OraclePool");
    oracle = op.getOracle();
    System.out.println("Done");
    System.out.println("Is logical connection:" +
        oracle.getConnection().isLogicalConnection());
    g = new GraphOracleSem(oracle, szModelName);
    g.add(Triple.create(Node.createURI("u:John"), Node.createURI("u:parentOf"), 
                        Node.createURI("u:Jack")));
    g.close();
    
    OracleUtils.dropSemanticModel(oracle, szModelName); 
    
    // return the Oracle back to the pool
    oracle.dispose();
    op.close();
  }
}

The following are the commands to compile and run Example 7-16, as well as the expected output of the java command.

javac -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar Test20.java
java -classpath ./:./jena-2.6.2.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.6.jar:./slf4j-log4j12-1.5.6.jar:./arq-2.8.1.jar:./xercesImpl-2.7.1.jar:./iri-0.7.jar:./icu4j-3.4.4.jar:./log4j-1.2.13.jar  Test20 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
Creating OraclePool
Done creating OraclePool
Getting an Oracle from OraclePool
Done
Is logical connection:true
Getting an Oracle from OraclePool
Done
Is logical connection:true