Oracle® Database Semantic Technologies Developer's Guide 11g Release 2 (11.2) Part Number E11828-10 |
|
|
PDF · Mobi · ePub |
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:
Section 7.3, "Setting Up the Semantic Technologies Environment"
Section 7.6, "Additions to the SPARQL Syntax to Support Other Features"
Section 7.7, "Functions Supported in SPARQL Queries through the Jena Adapter"
Disclaimer:
The current Jena Adapter release has been tested against Jena 2.6.3, ARQ 2.8.5, and Joseki 3.4.2. Because of the nature of open source projects, you should not use this Jena Adapter with later versions of Jena, ARQ, or Joseki.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.3, the Jena Adapter, and JDK 1.6. You can set up the software environment by performing these actions:
Install Oracle Database Release 11.2 Enterprise Edition with the Oracle Spatial and Partitioning Options.
Install the 11.2.0.2 Patch Set for Oracle Database Server (https://updates.oracle.com/ARULink/PatchDetails/process_form?patch_num=10098816
).
Enable the support for Semantic Technologies, as explained in Section A.1.
Install Jena (version 2.6.3): download the .zip file from http://sourceforge.net/projects/jena/files/Jena/Jena-2.6.3/jena-2.6.3.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>.
Note that Jena 2.6.3 comes with ARQ version 2.8.4 (arq-2.8.4.jar
); however, this version of the Jena Adapter actually requires a newer ARQ version (arq-2.8.5.jar
). You can download arq-2.8.5.jar
from http://sourceforge.net/projects/jena/files/ARQ/ARQ-2.8.5/arq-2.8.5.zip/download
and unzip it to a temporary directory. Remove the arq-2.8.4.jar
file from <Jena_DIR>/Jena-2.6.3/lib/
, and copy arq-2.8.5.jar
from the temporary directory into <Jena_DIR>/Jena-2.6.3/lib/
.
Download the Jena Adapter (jena_adaptor_for_release11.2.0.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
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
.)
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
.)
If JDK 1.6 is not already installed, install it.
If the JAVA_HOME environment variable does not already refer to the JDK 1.6 installation, define it accordingly. For example:
setenv JAVA_HOME /usr/local/packages/jdk16/
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.
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.
Download and Install Oracle WebLogic Server 11g Release 1 (10.3.1). For details, see http://www.oracle.com/technology/products/weblogic/
and http://www.oracle.com/technetwork/middleware/ias/downloads/wls-main-097127.html
.
Ensure that you have Java 6 installed, because it is required by Joseki 3.4.2.
Download Joseki 3.4.2 (joseki-3.4.2.zip
) from http://sourceforge.net/projects/joseki/files/Joseki-SPARQL/
.
Unpack joseki-3.4.2.zip
into a temporary directory. For example:
mkdir /tmp/joseki cp joseki-3.4.2.zip /tmp/joseki cd /tmp/joseki unzip joseki-3.4.2.zip
Ensure that you have downloaded and unzipped the Jena Adapter for Oracle Database, as explained in Section 7.1.
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
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.2/webapps/joseki/StyleSheets /tmp/joseki.war
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.2/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
.
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".
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.
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: ojdbc5.jar sdordfclient.jar sdordf.jar arq-2.8.5.jar arq-2.8.5-sources.jar arq-2.8.5-tests.jar arq-2.8.5-test-sources.jar icu4j-3.4.4.jar iri-0.8.jar iri-0.8-sources.jar jena-2.6.3.jar jena-2.6.3-sources.jar jena-2.6.3-tests.jar jena-2.6.3-test-sources.jar jetty-6.1.10.jar jetty-util-6.1.10.jar joseki-3.4.2.jar junit-4.5.jar log4j-1.2.14.jar lucene-core-2.3.1.jar sdb-1.3.2.jar servlet-api-2.5-6.1.10.jar servlet-api-2.5.jar slf4j-api-1.5.8.jar slf4j-log4j12-1.5.8.jar stax-api-1.0.1.jar tdb-0.8.7.jar wstx-asl-3.2.9.jar xercesImpl-2.7.1.jar
If you want to build a .war
file from the /tmp/joseki.war
directory (note that a .wa
r file is required if you want to deploy Joseki to an OC4J container), enter the following commands:
cd /tmp/joseki.war jar cvf /tmp/joseki_app.war *
Start or restart WebLogic Server.
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.
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.
If you need help creating the required J2EE data source using the WebLogic Server admin console, you can follow these steps:
Login to: http://
<hostname>
:7001/console
In the Domain Structure panel, click Services.
Click JDBC
Click Data Services.
In the Summary of JDBC Data Sources panel, click New under the Data Sources table.
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
Click Next twice.
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.
Click Next.
Select (check) the target server or servers to which you want to deploy this OracleSemDS
data source.
Click Finish.
You should see a message that all changes have been activated and no restart is necessary.
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.
Note:
Effective with the Jena Adapter release in November 2010, the default name of the application table index is changed from <model_name>_triple_idx to <model_name>_idx, and a compressed index is created on the leading model ID column in the application table to save storage.For existing models created by an older version of the Jena Adapter, you can migrate the application table index name and definition by using the OracleUtils.migrateApplicationTableIndex(oracle, graph, dop)
method in the oracle.spatial.rdf.client.jena
package. (See the Javadoc for more information.)
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.
For every database connection created or used by the Jena Adapter, a client identifier is associated with the connection. The client identifier can be helpful, especially in a Real Application Cluster (RAC) environment, for isolating Jena Adapter-related activities from other database activities when you are doing performance analysis and tuning.
By default, the client identifier assigned is JenaAdapter
. However, you can specify a different value by setting the Java VM clientIdentifier
property using the following format:
-Doracle.spatial.rdf.client.jena.clientIdentifier=<identificationString>
To start the tracing of only Jena Adapter-related activities on the database side, you can use the DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE procedure. For example:
SQL> EXECUTE DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE('JenaAdapter', true, true);
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
For any non-ASCII characters in the lexical representation of RDF resources, \uHHHH
N-Triples encoding is used when the characters are inserted into the Oracle database. (For details about N-Triples encoding, see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar
.) Encoding of the constant resources in a SPARQL query is handled in a similar fashion.
Using \uHHHH
N-Triples encoding enables support for international characters, such as a mix of Norwegian and Swedish characters, in the Oracle database even if a supported Unicode character set is not being used.
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:
Connect as SYS with the SYSDBA role:
sqlplus sys/<password-for-sys> as sysdba
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;
Create the semantic network. For example:
EXECUTE sem_apis.create_sem_network('RDF_USERS');
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;
Grant the necessary privileges to this database user. For example:
GRANT connect, resource TO rdfusr;
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.10 for information about example queries.
To use the Jena Adapter with supplied example data, see Section 7.10.
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):
Reads all triples out of Test_Model
.
Does not differentiate among URI, bNode, plain literals, and typed literals, and it does not handle long literals.
Does not unescape certain characters (such as '\n'
).
Query 2 (SPARQL query executed through the Jena Adapter) also reads all triples out of Test_Model
(assume it executed a call to ModelOracleSem
referring to the same underlying Test_Model
). However, Query 2:
Reads out additional columns (as opposed to just the s
, p
, and o
columns with the SEM_MATCH table function), to differentiate URI, bNodes, plain literals, typed literals, and long literals. This is to ensure proper creation of Jena Node objects.
Unescapes those characters that are escaped when stored in Oracle Database
Blank node handling is another difference between the two approaches:
In a SEM_MATCH-based query, blank nodes are always treated as constants.
In a SPARQL query, a blank node that is not wrapped inside <
and >
is treated as a variable when the query is executed through the Jena Adapter. This matches the SPARQL standard semantics. However, a blank node that is wrapped inside <
and >
is treated as a constant when the query is executed, and the Jena Adapter adds a proper prefix to the blank node label as required by the underlying data modeling.
The maximum length for the name of a semantic model created using the Jena Adapter API is 22 characters.
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.
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.
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 are 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();
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} }
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)
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.
In Oracle Database, using bind variables can reduce query parsing time and increase query efficiency and concurrency. Bind variable support in SPARQL queries is provided through namespace pragma specifications similar to ORACLE_SEM_FS_NS.
Consider a case where an application runs two SPARQL queries, where the second (Query 2) depends on the partial or complete results of the first (Query 1). Some approaches that do not involve bind variables include:
Iterating through results of Query 1 and generating a set of queries. (However, this approach requires as many queries as the number of results of Query 1.)
Constructing a SPARQL filter expression based on results of Query 1.
Treating Query 1 as a subquery.
Another approach in this case is to use bind variables, as in the following sample scenario:
Query 1: SELECT ?x WHERE { ... <some complex query> ... }; Query 2: SELECT ?subject ?x WHERE {?subject <urn:related> ?x .};
The following example shows Query 2 with the syntax for using bind variables with the Jena Adapter:
PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#no_fall_back,s2s> PREFIX ORACLE_SEM_UEAP_NS: <http://oracle.com/semtech#x$RDFVID%20in(?,?,?)> PREFIX ORACLE_SEM_UEPJ_NS: <http://oracle.com/semtech#x$RDFVID> PREFIX ORACLE_SEM_UEBV_NS: <http://oracle.com/semtech#1,2,3> SELECT ?subject ?x WHERE { ?subject <urn:related> ?x };
This syntax includes using the following namespaces:
ORACLE_SEM_UEAP_NS is like ORACLE_SEM_AP_NS, but the value portion of ORACLE_SEM_UEAP_NS is URL Encoded. Before the value portion is used, it must be URL decoded, and then it will be treated as an additional predicate to the SPARQL query.
In this example, after URL decoding, the value portion (following the #
character) of this ORACLE_SEM_UEAP_NS prefix becomes "x$RDFVID in(?,?,?)
". The three question marks imply a binding to three values coming from Query 1.
ORACLE_SEM_UEPJ_NS specifies the additional projections involved. In this case, because ORACLE_SEM_UEAP_NS references the x$RDFVID column, which does not appear in the SELECT clause of the query, it must be specified. Multiple projections are separated by commas.
ORACLE_SEM_UEBV_NS specifies the list of bind values that are URL encoded first, and then concatenated and delimited by commas.
Conceptually, the preceding example query is equivalent to the following non-SPARQL syntax query, in which 1, 2, and 3 are treated as bind values:
SELECT ?subject ?x WHERE { ?subject <urn:related> ?x } AND ?x$RDFVID in (1,2,3);
In the preceding SPARQL example of Query 2, the three integers 1, 2, and 3 come from Query 1. You can use the oext:build-uri-for-id
function to generate such internal integer IDs for RDF resources. The following example gets the internal integer IDs from Query 1:
PREFIX oext: <http://oracle.com/semtech/jena-adaptor/ext/function#> SELECT ?x (oext:build-uri-for-id(?x) as ?xid) WHERE { ... <some complex query> ... };
The values of ?xid
have the form of <rdfvid:integer-value>. The application can strip out the angle brackets and the "rdfvid:" strings to get the integer values and pass them to Query 2.
Consider another case, with a single query structure but potentially many different constants. For example, the following SPARQL query finds the hobby for each user who has a hobby and who logs in to an application. Obviously, different users will provide different <uri> values to this SPARQL query, because users of the application are represented using different URIs.
SELECT ?hobby WHERE { <uri> <urn:hasHobby> ?hobby };
One approach, which would not use bind variables, is to generate a different SPARQL query for each different <uri> value. For example, user Jane Doe might trigger the execution of the following SPARQL query:
SELECT ?hobby WHERE { <http://www.example.com/Jane_Doe> <urn:hasHobby> ?hobby };
However, another approach is to use bind variables, as in the following example specifying user Jane Doe:
PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#no_fall_back,s2s> PREFIX ORACLE_SEM_UEAP_NS: <http://oracle.com/semtech#subject$RDFVID%20in(ORACLE_ORARDF_RES2VID(?))> PREFIX ORACLE_SEM_UEPJ_NS: <http://oracle.com/semtech#subject$RDFVID> PREFIX ORACLE_SEM_UEBV_NS: <http://oracle.com/semtech#http%3a%2f%2fwww.example.com%2fJohn_Doe> SELECT ?subject ?hobby WHERE { ?subject <urn:hasHobby> ?hobby };
Conceptually, the preceding example query is equivalent to the following non-SPARQL syntax query, in which http://www.example.com/Jane_Doe
is treated as a bind variable:
SELECT ?subject ?hobby WHERE { ?subject <urn:hasHobby> ?hobby } AND ?subject$RDFVID in (ORACLE_ORARDF_RES2VID('http://www.example.com/Jane_Doe'));
In this example, ORACLE_ORARDF_RES2VID is a function that translates URIs and literals into their internal integer ID representation. This function is created automatically when the Jena Adapter is used to connect to an Oracle database.
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'
.
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.
BEST_EFFORT_QUERY=t
, when used with the TIMEOUT=
n
option, returns all matches found in n seconds for the SPARQL query.
DEGREE=
n specifies, at the statement level, 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.
Contrast DEGREE
with DOP
, which specifies parallelism at the session level. DEGREE
is recommended over DOP
for use with the Jena Adapter, because DEGREE
involves less processing overhead.
DOP=
n specifies, at the session level, 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.
JOIN=
n
specifies how results from a SPARQL SERVICE call to a federated query can be joined with other parts of the query. For information about federated queries and the JOIN
option, see Section 7.6.4.1.
NO_FALL_BACK
causes the underlying query execution engine not to fall back on the Jena execution mechanism if a SQL exception occurs.
ODS=
n
specifies, at the statement level, the level of dynamic sampling. (For an explanation of dynamic sampling, see the section about estimating statistics with dynamic sampling in Oracle Database Performance Tuning Guide.) Valid values for n are 1 through 10. For example, you could try ODS=3
for complex queries.
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.
S2S
(SPARQL to pure SQL) causes the underlying SEM_MATCH-based query or queries generated based on the SPARQL query to be further converted into SQL queries without using the SEM_MATCH table function. The resulting SQL queries are executed by the Oracle cost-based optimizer, and the results are processed by the Jena Adapter before being passed on to the client. For more information about the S2S
option, including benefits and usage information, see Section 7.6.4.2.
TIMEOUT=
n
(query timeout) specifies the number of seconds (n) that the query will run until it is terminated. The underlying SQL generated from a SPARQL query can return many matches and can use features like subqueries and assignments, all of which can take considerable time. The TIMEOUT
and BEST_EFFORT_QUERY=t
options can be used to prevent what you consider excessive processing time for the query.
A SPARQL federated query, as described in W3C documents, is a query "over distributed data" that entails "querying one source and using the acquired information to constrain queries of the next source." For more information, see SPARQL 1.1 Federation Extensions (http://www.w3.org/2009/sparql/docs/fed/service
).
You can use the JOIN option (described in Section 7.6.4) and the SERVICE keyword in a federated query that uses the Jena Adapter. For example, assume the following query:
SELECT ?s ?s1 ?o WHERE { ?s1 ?p1 ?s . { SERVICE <http://sparql.org/books> { ?s ?p ?o } } }
If the local query portion (?s1 ?p1 ?s,
) is very selective, you can specify join=2
, as shown in the following query:
PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#join=2>
SELECT ?s ?s1 ?o
WHERE { ?s1 ?p1 ?s .
{
SERVICE <http://sparql.org/books> { ?s ?p ?o }
}
}
In this case, the local query portion (?s1 ?p1 ?s,
) is executed locally against the Oracle database. Each binding of ?s
from the results is then pushed into the SERVICE part (remote query portion), and a call is made to the service endpoint specified. Conceptually, this approach is somewhat like nested loop join.
If the remote query portion (?s ?s1 ?o
) is very selective, you can specify join=3
, as shown in the following query, so that the remote portion is executed first and results are used to drive the execution of local portion:
PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#join=3>
SELECT ?s ?s1 ?o
WHERE { ?s1 ?p1 ?s .
{
SERVICE <http://sparql.org/books> { ?s ?p ?o }
}
}
In this case, a single call is made to the remote service endpoint and each binding of ?s
triggers a local query. As with join=2
, this approach is conceptually a nested loop based join, but the difference is that the order is switched.
If neither the local query portion nor the remote query portion is very selective, then we can choose join=1, as shown in the following query:
PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#join=1>
SELECT ?s ?s1 ?o
WHERE { ?s1 ?p1 ?s .
{
SERVICE <http://sparql.org/books> { ?s ?p ?o }
}
}
In this case, the remote query portion and the local portion are executed independently, and the results are joined together by Jena. Conceptually, this approach is somewhat like a hash join.
For debugging or tracing federated queries, you can use the HTTP Analyzer in Oracle JDeveloper to see the underlying SERVICE calls.
The S2S
option, described in Section 7.6.4, provides the following potential benefits:
It works well with the RESULT_CACHE
option to improve query performance. Using the S2S
and RESULT_CACHE
options is especially helpful for queries that are executed frequently.
It reduces the parsing time of the SEM_MATCH table function, which can be helpful for applications that involve many dynamically generated SPARQL queries.
It eliminates the limit of 4000 bytes for the query body (the first parameter of the SEM_MATCH table function), which means that longer, more complex queries are supported.
The S2S option causes an internal in-memory cache to be used for translated SQL query statements. The default size of this internal cache is 1024 (that is, 1024 SQL queries); however, you can adjust the size by using the following Java VM property:
-Doracle.spatial.rdf.client.jena.queryCacheSize=<size>
When semantic data is stored, all of the resource values are hashed into IDs, which are stored in the triples table. The mappings from value IDs to full resource values are stored in the MDSYS.RDF_VALUE$ table. At query time, for each selected variable, Oracle Database must perform a join with the RDF_VALUE$ table to retrieve the resource.
However, to reduce the number of joins, you can use the midtier cache option, which causes an in-memory cache on the middle tier to be used for storing mappings between value IDs and resource values. To use this feature, include the following PREFIX pragma in the SPARQL query:
PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#midtier_cache>
To control the maximum size (in bytes) of the in-memory cache, use the oracle.spatial.rdf.client.jena.cacheMaxSize
system property. The default cache maximum size is 1GB.
Note that midtier resource caching is most effective for queries using ORDER BY or DISTINCT (or both) constructs. Midtier cache can be combined with the other options specified in Section 7.6.4.
If you want to pre-populate the cache with all of the resources in a model, use the GraphOracleSem.populateCache
method.
SPARQL queries through the Jena Adapter can use the following kinds of functions:
Functions in the function library of the Jena ARQ query engine
Native Oracle Database functions for projected variables
User-defined functions
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 }
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 spellingjena-adapt
or
, 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 }
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; /
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.
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
.
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(); }
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 |
---|---|
OracleUtils.dropSemanticModel |
|
OracleUtils.mergeModels |
|
OracleUtils.swapNames |
|
OracleUtils.removeDuplicates |
|
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).
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.
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/
.)
To load thousands to hundreds of thousands of RDF/OWL data files into an Oracle database, you can use the prepareBulk
and completeBulk
methods in the OracleBulkUpdateHandler
Java class to simplify the task.
The addInBulk method in the OracleBulkUpdateHandler class can load triples of a graph or model into an Oracle database in bulk loading style. If the graph or model is a Jena in-memory graph or model, the operation is limited by the size of the physical memory. The prepareBulk method bypasses the Jena in-memory graph or model and takes a direct input stream to an RDF data file, parses the data, and load the triples into an underlying staging table. If the staging table and an accompanying table for storing long literals do not already exist, they are created automatically.
The prepareBulk method can be invoked multiple times to load multiple data files into the same underlying staging table. It can also be invoked concurrently, assuming the hardware system is balanced and there are multiple CPU cores and sufficient I/O capacity.
Once all the data files are processed by the prepareBulk method, you can invoke completeBulk to load all the data into the semantic network.
Example 7-1 shows how to load all data files in directory dir_1
into the underlying staging table. Long literals are supported and will be stored in a separate table. The data files can be compressed using GZIP to save storage space, and the prepareBulk method can detect automatically if a data file is compressed using GZIP or not.
Example 7-1 Loading Data into the Staging Table (prepareBulk)
Oracle oracle = new Oracle(szJdbcURL, szUser, szPasswd); GraphOracleSem graph = new GraphOracleSem(oracle, szModelName); PrintStream psOut = System.out; String dirname = "dir_1"; File fileDir = new File(dirname); String[] szAllFiles = fileDir.list(); // loop through all the files in a directory for (int idx = 0; idx < szAllFiles.length; idx++) { String szIndFileName = dirname + File.separator + szAllFiles[idx]; psOut.println("process to [ID = " + idx + " ] file " + szIndFileName); psOut.flush(); try { InputStream is = new FileInputStream(szIndFileName); graph.getBulkUpdateHandler().prepareBulk( is, // input stream "http://example.com", // base URI "RDF/XML", // data file type: can be RDF/XML, N-TRIPLE, etc. "SEMTS", // tablespace null, // flags null, // listener null // staging table name. ); is.close(); } catch (Throwable t) { psOut.println("Hit exception " + t.getMessage()); } } graph.close(); oracle.dispose();
The code in Example 7-1, starting from creating a new Oracle object and ending with disposing of the Oracle object, can be executed in parallel. Assume there is a quad-core CPU and enough I/O capacity on the database hardware system; you can divide up all the data files and save them into four separate directories: dir_1
, dir_2
, dir_3
, and dir_4
. Four Java threads of processes can be started to work on those directories separately and concurrently.
After all data files are processed, you can invoke, just once, the completeBulk method to load the data from staging table into the semantic network, as shown in Example 7-2. Triples with long literals will be loaded also.
Example 7-2 Loading Data from the Staging Table into the Semantic Network (completeBulk)
graph.getBulkUpdateHandler().completeBulk( null, // flags for invoking SEM_APIS.bulk_load_from_staging_table null // staging table name );
The prepareBulk
method can also take a Jena model as an input data source, in which case triples in that Jena model are loaded into the underlying staging table. For more information, see the Javadoc.
In addition to loading triples from Jena models and data files, the prepareBulk
method supports RDFa, as shown in Example 7-3. (RDFa is explained in http://www.w3.org/TR/xhtml-rdfa-primer/
.)
Example 7-3 Using prepareBulk with RDFa
graph.getBulkUpdateHandler().prepareBulk( rdfaUrl, // url to a web page using RDFa "SEMTS", // tablespace null, // flags null, // listener null // staging table name );
To parse RDFa, the relevant java-rdfa
libraries must be included in the classpath. No additional setup or API calls are required. (For information about java-rdfa, see http://www.rootdev.net/maven/projects/java-rdfa/
and the other topics there under Project Information.)
Note that if the rdfaUrl
is located outside a firewall, you may need to set the following HTTP Proxy-related Java VM properties:
-Dhttp.proxyPort=... -Dhttp.proxyHost=...
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:
Count asserted triples and asserted plus inferred triples in an example "university" ontology, both by referencing the ontology by a URL and by bulk loading the ontology from a local file
Run several SPARQL queries using a "family" ontology, including features such as LIMIT, OFFSET, TIMEOUT, DOP (degree of parallelism), ASK, DESCRIBE, CONSTRUCT, GRAPH, ALLOW_DUP (duplicate triples with multiple models), SPARUL (inserting data)
Use the ARQ built-in function
Use a SELECT cast query
Instantiate Oracle Database using OracleConnection
Use Oracle Database connection pooling
To run a query, you must do the following:
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.
Compile the Java source file. For example:
> javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test.java
Note:
Thejavac
and java
commands must each be on a single command line.Run the compiled file. For example:
> java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.jar Test jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
Example 7-4 specifies that John is the father of Mary, and it selects and displays the subject and object in each fatherOf
relationship
Example 7-4 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-4, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.jar Test jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
---------------------------------------------------------
| f | k |
=========================================================
| <http://example.com/John> | <http://example.com/Mary> |
---------------------------------------------------------
Example 7-5 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-5 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-5, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test6.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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.
Example 7-6 loads the same OWL ontology as in Section 7.10.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-6 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-6, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test7.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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.
Example 7-7 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-7 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-7, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test8.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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> | |
----------------------------------
Example 7-8 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-8 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-8, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test9.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.jar Test9 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
------------------------------
| s | o | gkid |
==============================
| <u:John> | <u:Jack> | |
------------------------------
Example 7-9 shows the SPARQL query from Section 7.10.5 with additional features, including a timeout setting (TIMEOUT=1, in seconds) and parallel execution setting (DOP=4).
Example 7-9 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-9, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test10.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.jar Test10 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
------------------------------
| s | o | gkid |
==============================
| <u:Mary> | <u:Jill> | |
------------------------------
Example 7-10 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-10 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-10, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test11.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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> |
------------------------------------------------------------------------
Example 7-11 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.
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-11, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test12.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.jar Test12 jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> M1
ask result = TRUE
Example 7-12 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-12 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-12, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test13.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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} | >
Example 7-13 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-13 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-13, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test14.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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} | >
Example 7-14 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-14 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-14, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test15.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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} | >
Example 7-15 inserts two triples into a model.
Example 7-15 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-15, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test16.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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"
Example 7-16 inserts data about two books, and it displays the book titles in all uppercase characters and the length of each title string.
Example 7-16 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-16, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test17.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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 |
----------------------------------------------------------
Example 7-17 "converts" two Fahrenheit temperatures (18.1 and 32.0) to Celsius temperatures.
Example 7-17 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-17, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test18.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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> |
------------------------------------------------------------------------
Example 7-18 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-18 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-18, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test19.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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> |
-----------------------
Example 7-19 uses Oracle Database connection pooling.
Example 7-19 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(); } }
The following are the commands to compile and run Example 7-19, as well as the expected output of the java
command.
javac -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:/slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar Test20.java
java -classpath ./:./jena-2.6.3.jar:./sdordfclient.jar:./ojdbc5.jar:./slf4j-api-1.5.8.jar:./slf4j-log4j12-1.5.8.jar:./arq-2.8.5.jar:./xercesImpl-2.7.1.jar:./iri-0.8.jar:./icu4j-3.4.4.jar:./log4j-1.2.14.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