8 RDF Semantic Graph Support for Eclipse RDF4J
Oracle RDF Graph Adapter for Eclipse RDF4Jは、一般的なEclipse RDF4Jフレームワークを使用して、Oracle DatabaseのRDFセマンティク・グラフ機能を使用するためのJava開発者サポートを提供します。
ノート:
- この機能は、以前はSesame Adapter for Oracle DatabaseまたはSesame Adapterと呼ばれていました。
- 共有デプロイメントでAutonomous Databaseインスタンスを使用している場合、RDF Semantic Graph Support for Eclipse RDF4Jには、Oracle JVMの有効化が必要です。Autonomous DatabaseインスタンスでOracle JVMを有効にするには、共有ExadataインフラストラクチャでのOracle Autonomous Databaseの使用のOracle Javaの使用を参照してください。
Eclipse RDF4Jは、RDFデータの処理とハンドリングのための強力なJavaフレームワークです。これには、RDFおよびリンクされたデータを使用した作成、解析、スケーラブルな格納、推論および問合せが含まれます。詳細は、https://rdf4j.orgを参照してください。
「RDFセマンティク・グラフの概要」と「OWLの概要」で説明されている主要な概念について十分に理解していることが前提です。Eclipse RDF4J Javaフレームワークの性能全体および使用についても十分に理解していることを前提とします。詳細は、https://rdf4j.orgを参照してください。
Oracle RDF Graph Adapter for Eclipse RDF4Jは、Java開発者に一般的な標準ベースのAPIを提供することで、Oracle Database RDF/OWLのセマンティク・データ管理機能を拡張します。
- Oracle RDF Graph Support for Eclipse RDF4Jの概要
Oracle RDF Graph Adapter for Eclipse RDF4J APIは、Eclipse RDF4J SAIL APIに準拠するAPIフレームワークおよびツールを介して、Oracleセマンティク・データへのJavaベース・インタフェースを提供します。 - Oracle RDF Graph Adapter for Eclipse RDF4Jを使用するための前提条件
Oracle RDF Graph Adapter for Eclipse RDF4Jの使用を開始する前に、システム環境が特定の前提条件を満たしていることを確認する必要があります。 - Oracle RDF Graph Adapter for Eclipse RDF4Jを使用するための設定および構成
Oracle RDF Graph Adapter for Eclipse RDF4Jを使用するには、最初にシステム環境を設定および構成する必要があります。 - データベース接続の管理
Oracle RDF Graph Adapter for Eclipse RDF4Jでは、Oracle Databaseの接続プーリングがサポートされています。 - SPARQL問合せの実行モデル
Oracle RDF Graph Adapter for Eclipse RDF4J APIを介して実行されるSPARQL問合せは、RDFデータを格納するためのOracleのリレーショナル・スキーマに対するSQL問合せとして実行されます。 - SPARQL更新の実行モデル
この項では、Oracle RDF Graph Adapter for Eclipse RDF4JのSPARQL更新の実行モデルについて説明します。 - RDFデータの効率的なロード
Oracle RDF Graph Adapter for Eclipse RDF4Jには、ファイルまたはコレクションから大量のRDFデータを効率的にロードするための追加または改善されたJavaメソッドが用意されています。 - Oracle RDF Graph Adapter for Eclipse RDF4Jのベスト・プラクティス
この項では、Oracle RDF Graph Adapter for Eclipse RDF4Jのパフォーマンスのベスト・プラクティスについて説明します。 - Oracle RDF Graph Adapter for Eclipse RDF4Jでの空白ノードのサポート
- Oracle RDF Graph Adapter for Eclipse RDF4Jでサポートされていない機能
この項では、現在のバージョンのOracle RDF Graph Adapter for Eclipse RDF4Jでサポートされていない機能について説明します。 - Oracle RDF Graph Adapter for Eclipse RDF4Jを使用した問合せの例
親トピック: 概念および使用方法に関する情報
8.1 Oracle RDF Graph Support for Eclipse RDF4Jの概要
Oracle RDF Graph Adapter for Eclipse RDF4J APIは、Eclipse RDF4J SAIL APIに準拠するAPIフレームワークおよびツールを介して、Oracleセマンティク・データへのJavaベース・インタフェースを提供します。
RDF Semantic Graph support for Eclipse RDF4Jは、RDF Semantic Graph Support for Apache Jenaで説明されているRDF Semantic Graph support for Apache Jenaに似ています。
Eclipse RDF4J用のアダプタでは、Oracle Databaseに格納されているセマンティク・データと対話するためのJava APIが提供されています。また、次のとおりEclipse RDF4Jツールを包括的に提供します。
- Eclipse RDF4J Server。HTTP SPARQLエンドポイントを提供します。
- Eclipse RDF4J Workbench。WebベースのクライアントUIで、データベースを管理し、問合せを実行します。
Eclispe RDF4J用のアダプタによって提供される機能を次に示します。
- (コンテキスト付きおよびコンテキストなしの)文のロード(バルクおよび増分)、エクスポートおよび削除
- データの問合せ(コンテキストがある場合とない場合)
- データの更新(コンテキストがある場合とない場合)
Oracle RDF Graph Adapter for Eclipse RDF4Jでは、Eclipse RDF4J Storage and Inference Layer (SAIL) APIの様々なインタフェースを実装しています。
たとえばクラスOracleSailConnection
は、Eclipse RDF4J SailConnection
インタフェースのOracle実装で、クラスOracleSailStore
はAbstractSail
を拡張した、Eclipse RDF4J Sail
インタフェースのOracle実装です。
次の例に、RDF Semantic Graph support for Eclipse RDF4Jの一般的な使用フローを示します。
例8-1 スキーマプライベート・セマンティク・ネットワークを使用した、Eclipse RDF4J用RDFセマンティク・グラフ・サポートのサンプル使用フロー
String networkOwner = "SCOTT"; String networkName = "NET1"; String modelName = "UsageFlow"; OraclePool oraclePool = new OraclePool(jdbcurl, user, password); SailRepository sr = new SailRepository(new OracleSailStore(oraclePool, modelName, networkOwner, networkName)); SailRepositoryConnection conn = sr.getConnection(); //A ValueFactory factory for creating IRIs, blank nodes, literals and statements ValueFactory vf = conn.getValueFactory(); IRI alice = vf.createIRI("http://example.org/Alice"); IRI friendOf = vf.createIRI("http://example.org/friendOf"); IRI bob = vf.createIRI("http://example.org/Bob"); Resource context1 = vf.createIRI("http://example.org/"); // Data loading can happen here. conn.add(alice, friendOf, bob, context1); String query = " PREFIX foaf: <http://xmlns.com/foaf/0.1/> " + " PREFIX dc: <http://purl.org/dc/elements/1.1/> " + " select ?s ?p ?o ?name WHERE {?s ?p ?o . OPTIONAL {?o foaf:name ?name .} } "; TupleQuery tq = conn.prepareTupleQuery(QueryLanguage.SPARQL, query); TupleQueryResult tqr = tq.evaluate(); while (tqr.hasNext()) { System.out.println((tqr.next().toString())); } tqr.close(); conn.close(); sr.shutDown();
8.2 Oracle RDF Graph Adapter for Eclipse RDF4Jを使用するための前提条件
Oracle RDF Graph Adapter for Eclipse RDF4Jの使用を開始する前に、システム環境が特定の前提条件を満たしていることを確認する必要があります。
次に、Eclipse RDF4J用のアダプタを使用するために必要な前提条件を示します。
- バージョン18c以降のOracle Database Standard Edition 2 (SE2)またはEnterprise Edition (EE) (クラウドまたはオンプレミスのユーザー管理データベース)
- Eclipse RDF4Jバージョン4.2.1
- JDK 11
さらに、バグ修正およびパフォーマンスの改善のために、次のデータベース・パッチをお薦めします。
- Patch 32562595: TRACKING BUG FOR RDF GRAPH PATCH KIT Q2 2021
現在、My Oracle Supportでリリース19.11で使用できます。
Oracle Databaseリリース19.15以降にはすでにこれらの変更が含まれており、追加のパッチは必要ないことに注意してください。
8.3 Oracle RDF Graph Adapter for Eclipse RDF4Jを使用するための設定および構成
Oracle RDF Graph Adapter for Eclipse RDF4Jを使用するには、最初にシステム環境を設定および構成する必要があります。
アダプタは、次の3つの環境で使用できます。
- Javaコードを使用したプログラムで
- SPARQLサービスとしてHTTPを介したアクセスで
- Eclipse RDF4J Workbench環境内で使用
次の項では、前述の環境でEclipse RDF4J用のアダプタを使用するためのアクションについて説明します。
8.3.1 Javaで使用するためのOracle RDF Graph Adapter for Eclipse RDF4Jの設定
Javaコードを介してOracle RDF Graph Adapter for Eclipse RDF4Jをプログラムで使用するには、Oracle RDF Graph Adapter for Eclipse RDF4Jを使用するための前提条件の説明に従って、システム環境がすべての前提条件を満たしていることを最初に確認する必要があります。
アダプタを使用してRDFグラフの格納、管理および問合せをOracleデータベースで開始する前に、セマンティク・ネットワークを作成する必要があります。セマンティク・ネットワークは、データベース・ユーザーが作成した複数のRDFグラフ(セマンティク(RDF)モデルと呼ばれる)を保持できるフォルダのように機能します。セマンティク・ネットワークは、MDSYSシステム・スキーマ(MDSYSネットワークと呼ばれます)で、またはバージョン19cからはユーザー・スキーマ(スキーマプライベート・ネットワークと呼ばれます)で作成できます。
ネットワークを作成するには、次のコマンドを実行します。
- MDSYSセマンティク・ネットワーク
sem_apis.create_sem_network(<tablespace_name>)
- スキーマプライベート・セマンティク・ネットワーク
sem_apis.create_sem_network(<tablespace_name>, network_owner=><network_owner>, network_name=><network_name>)
詳細は、セマンティク・ネットワークを参照してください。
関連項目:
Javaで使用するためのOracle RDF Graph Adapter for Eclipse RDF4Jの設定(Oracle Database 18cの場合)ノート:
RDF4Jサーバー、ワークベンチおよびSPARQLサービスでは、Oracle RDF Graph Adapter for Eclipse RDF4Jの現在のバージョンのMDSYS所有セマンティク・ネットワークのみがサポートされます。MDSYS所有セマンティク・ネットワークの作成
- DBA権限を持つ
SYSTEM
ユーザーとしてOracle Databaseに接続します。CONNECT system/<password-for-system-user>
- RDFグラフを格納するための表領域を作成します。適切なオペレーティング・システム・フォルダおよびファイル名を使用します。
CREATE TABLESPACE rdftbs DATAFILE 'rdftbs.dat' SIZE 128M REUSE AUTOEXTEND ON NEXT 64M MAXSIZE UNLIMITED SEGMENT SPACE MANAGEMENT AUTO;
rdftbs
の割当て制限をMDSYSに付与します。ALTER USER MDSYS QUOTA UNLIMITED ON rdftbs;
- ユーザー・データを格納するための表領域を作成します。適切なオペレーティング・システム・フォルダおよびファイル名を使用します。
CREATE TABLESPACE usertbs DATAFILE 'usertbs.dat' SIZE 128M REUSE AUTOEXTEND ON NEXT 64M MAXSIZE UNLIMITED SEGMENT SPACE MANAGEMENT AUTO;
- アダプタを使用してRDFグラフを作成または使用する、あるいはその両方を実行するデータベース・ユーザーを作成します。
CREATE USER rdfuser IDENTIFIED BY <password-for-rdfuser> DEFAULT TABLESPACE usertbs QUOTA 5G ON usertbs;
rdftbs
の割当て制限をRDFUSERに付与します。ALTER USER RDFUSER QUOTA 5G ON rdftbs;
- 必要な権限を新しいデータベース・ユーザーに付与します。
GRANT CONNECT, RESOURCE TO rdfuser;
- MDSYS所有セマンティク・ネットワークを作成します。
EXECUTE SEM_APIS.CREATE_SEM_NETWORK(tablespace_name =>'rdftbs');
- MDSYS所有セマンティク・ネットワークが正常に作成されていることを確認します。
SELECT table_name FROM sys.all_tables WHERE table_name = 'RDF_VALUE$' AND owner='MDSYS';
MDSYSスキーマに
RDF_VALUE$
表が存在する場合は、MDSYS所有セマンティク・ネットワークが正常に作成されています。TABLE_NAME ----------- RDF_VALUE$
スキーマプライベート・セマンティク・ネットワークの作成
- DBA権限を持つ
SYSTEM
ユーザーとしてOracle Databaseに接続します。CONNECT system/<password-for-system-user>
- ユーザー・データを格納するための表領域を作成します。適切なオペレーティング・システム・フォルダおよびファイル名を使用します。
CREATE TABLESPACE usertbs DATAFILE 'usertbs.dat' SIZE 128M REUSE AUTOEXTEND ON NEXT 64M MAXSIZE UNLIMITED SEGMENT SPACE MANAGEMENT AUTO;
- データベース・ユーザーを作成して、セマンティク・ネットワークを作成および所有します。このユーザーは、このスキーマ・プライベート・ネットワーク内でアダプタを使用して、RDFグラフを作成または使用するか、あるいはその両方を実行できます。
CREATE USER rdfuser IDENTIFIED BY <password-for-rdfuser> DEFAULT TABLESPACE usertbs QUOTA 5G ON usertbs;
- 必要な権限を新しいデータベース・ユーザーに付与します。
GRANT CONNECT, RESOURCE, CREATE VIEW TO rdfuser;
rdfuser
としてOracle Databaseに接続します。CONNECT rdfuser/<password-for-rdf-user>
NET1
という名前のスキーマ・プライベート・セマンティク・ネットワークを作成します。EXECUTE SEM_APIS.CREATE_SEM_NETWORK(tablespace_name =>'usertbs', network_owner=>'RDFUSER', network_name=>'NET1');
- スキーマプライベート・セマンティク・ネットワークが正常に作成されていることを確認します。
SELECT table_name FROM sys.all_tables WHERE table_name = 'NET1#RDF_VALUE$' AND owner='RDFUSER';
ネットワーク所有者のスキーマに
<NETWORK_NAME>#RDF_VALUE$
表が存在することは、スキーマ・プライベート・セマンティク・ネットワークが正常に作成されていることを示しています。TABLE_NAME ----------- NET1#RDF_VALUE$
これで、次のアクションを実行して、Javaコードで使用するOracle RDF Graph Adapter for Eclipse RDF4Jを設定できます。
- RDF4Jのダウンロード・ページからEclipse RDF4Jリリース4.2.1をダウンロードして構成します。
- Oracle Software Delivery Cloudから、Eclipse RDF4J (Oracle Adapter for Eclipse RDF4J)用のアダプタをダウンロードします。
- ダウンロードしたキット(V1033016-01.zip)を、Linuxシステム上の
/tmp/oracle_adapter
などの一時ディレクトリに解凍します。この一時ディレクトリがまだ作成されていない場合は、解凍操作の前に作成します。 - IDEを介してJavaコードを実行するために、次の3つのサポート・ライブラリを
CLASSPATH
に指定します。eclipse-rdf4j-4.2.1-onejar.jar
: このEclipse RDF4J jarライブラリを、RDF4Jのダウンロード・ページからダウンロードします。ojdbc8.jar
: 使用しているデータベース・バージョンに対応したこのJDBC Thinドライバを、JDBCダウンロード・ページからダウンロードします。ucp.jar
: 使用しているデータベース・バージョンに対応したこのユニバーサル接続プールjarファイルを、JDBCダウンロード・ページからダウンロードします。log4j-api-2.17.2.jar
、log4j-core-2.17.2.jar
、log4j-slf4j-impl-2.17.2.jar
、slf4j-api-1.7.36.jar
およびcommons-io-2.11.0.jar
: Apache Software Foundationからダウンロードします。
- JDK 11がまだインストールされていない場合はインストールします。
JAVA_HOME
環境変数を、JDK 11のインストールを参照するように設定します。次のコマンドを実行して、設定を定義および確認します。echo $JAVA_HOME
8.3.2 RDF4J ServerおよびWorkbenchで使用するためのOracle RDF Graph Adapter for Eclipse RDF4Jの設定
この項では、RDF4J ServerおよびRDF4J WorkbenchでのOracle RDF Graph Adapter for Eclipse RDF4Jのインストールおよび構成について説明します。
RDF4J Serverは、RDF4JリポジトリへのHTTPアクセスを提供し、SPARQLエンドポイントとして公開するデータベース管理アプリケーションです。RDF4J Workbenchには、RDF4J Serverのリポジトリを作成、問合せ、更新および検索するためのWebインタフェースが用意されています。
ノート:
RDF4Jサーバー、ワークベンチおよびSPARQLサービスでは、Oracle RDF Graph Adapter for Eclipse RDF4Jの現在のバージョンのMDSYS所有セマンティク・ネットワークのみがサポートされます。前提条件
次の前提条件が、RDF4J ServerおよびWorkbenchでEclipse RDF4J用のアダプタを使用するように構成されていることを確認します。
- Java 11 Runtime Environment
- 含めるサポート・ライブラリとして説明したサポート・ライブラリをダウンロードします。
- Java Servlet API 3.1およびJava Server Pages (JSP) 2.2以上をサポートするJavaサーブレット・コンテナ。
ノート:
この章の例はすべて、最新の安定バージョンのApache Tomcat (9.0.78)で実行されます。 - RDF4J Server、RDF4J WorkbenchおよびRDF4J Consoleの標準インストール。詳細は、RDF4J Server and Workbench InstallationおよびRDF4J Console installationを参照してください。
-
次の図8-1のドロップダウンに、Oracleがデフォルトのリポジトリとして表示されていないことを確認します。
ノート:
Oracleデータ・ソース・リポジトリがRDF4J Workbenchリポジトリにすでに設定されている場合は、上のドロップダウン・リストに表示されます。
RDF4J WorkbenchでのOracleデータ・ソース・リポジトリの追加
RDF4J WorkbenchでOracleデータ・ソース・リポジトリを追加するには、次のステップを実行する必要があります。
-
強調表示されている次のフィールドを更新して、Tomcatメイン
$CATALINA_HOME/conf/context.xml
ディレクトリのcontext.xml
にデータ・ソースを追加します。- Using JDBC driver <Resource name="jdbc/OracleSemDS" auth="Container" driverClassName="oracle.jdbc.OracleDriver" factory="oracle.jdbc.pool.OracleDataSourceFactory" scope="Shareable" type="oracle.jdbc.pool.OracleDataSource" user="<<username>>" password="<<pwd>>" url="jdbc:oracle:thin:@<< host:port:sid >>" maxActive="100" minIdle="15" maxIdel="15" initialSize="15" removeAbandonedTimeout="30" validationQuery="select 1 from dual" /> - Using UCP <Resource name="jdbc/OracleSemDS" auth="Container" factory="oracle.ucp.jdbc.PoolDataSourceImpl" type="oracle.ucp.jdbc.PoolDataSource" connectionFactoryClassName="oracle.jdbc.pool.OracleDataSource" minPoolSize="15" maxPoolSize="100" inactiveConnectionTimeout="60" abandonedConnectionTimeout="30" initialPoolSize="15" user="<<username>>" password="<<pwd>>" url="jdbc:oracle:thin:@<< host:port:sid >>" />
- Oracle jdbcおよびucpドライバをTomcatの
lib
フォルダにコピーします。cp -f ojdbc8.jar $CATALINA_HOME/lib cp -f ucp.jar $CATALINA_HOME/lib
- oracle-rdf4j-adapter-4.2.1.jarをRDF4Jサーバーの
lib
フォルダにコピーします。cp -f oracle-rdf4j-adapter-4.2.1.jar $CATALINA_HOME/webapps/rdf4j-server/WEB-INF/lib
- oracle-rdf4j-adapter-4.2.1.jarをRDF4J Workbenchの
lib
フォルダにコピーします。cp -f oracle-rdf4j-adapter-4.2.1.jar $CATALINA_HOME/webapps/rdf4j-workbench/WEB-INF/lib
- Tomcatの
$CATALINA_HOME/webapps/rdf4j-workbench/transformations
フォルダ内に構成ファイルcreate-oracle.xsl
を作成します。<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xsl:stylesheet [ <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" > ]> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sparql="http://www.w3.org/2005/sparql-results#" xmlns="http://www.w3.org/1999/xhtml"> <xsl:include href="../locale/messages.xsl" /> <xsl:variable name="title"> <xsl:value-of select="$repository-create.title" /> </xsl:variable> <xsl:include href="template.xsl" /> <xsl:template match="sparql:sparql"> <form action="create"> <table class="dataentry"> <tbody> <tr> <th> <xsl:value-of select="$repository-type.label" /> </th> <td> <select id="type" name="type"> <option value="memory"> Memory Store </option> <option value="memory-lucene"> Memory Store + Lucene </option> <option value="memory-rdfs"> Memory Store + RDFS </option> <option value="memory-rdfs-dt"> Memory Store + RDFS and Direct Type </option> <option value="memory-rdfs-lucene"> Memory Store + RDFS and Lucene </option> <option value="memory-customrule"> Memory Store + Custom Graph Query Inference </option> <option value="memory-spin"> Memory Store + SPIN support </option> <option value="memory-spin-rdfs"> Memory Store + RDFS and SPIN support </option> <option value="memory-shacl"> Memory Store + SHACL </option> <!-- disabled pending GH-1304 option value="memory-spin-rdfs-lucene"> In Memory Store with RDFS+SPIN+Lucene support </option --> <option value="native"> Native Store </option> <option value="native-lucene"> Native Store + Lucene </option> <option value="native-rdfs"> Native Store + RDFS </option> <option value="native-rdfs-dt"> Native Store + RDFS and Direct Type </option> <option value="memory-rdfs-lucene"> Native Store + RDFS and Lucene </option> <option value="native-customrule"> Native Store + Custom Graph Query Inference </option> <option value="native-spin"> Native Store + SPIN support </option> <option value="native-spin-rdfs"> Native Store + RDFS and SPIN support </option> <option value="native-shacl"> Native Store + SHACL </option> <!-- disabled pending GH-1304 option value="native-spin-rdfs-lucene"> Native Java Store with RDFS+SPIN+Lucene support </option --> <option value="remote"> Remote RDF Store </option> <option value="sparql"> SPARQL endpoint proxy </option> <option value="federate">Federation</option> <option value="lmdb">LMDB Store</option> <option value="oracle">Oracle</option> </select> </td> <td></td> </tr> <tr> <th> <xsl:value-of select="$repository-id.label" /> </th> <td> <input type="text" id="id" name="id" size="16" /> </td> <td></td> </tr> <tr> <th> <xsl:value-of select="$repository-title.label" /> </th> <td> <input type="text" id="title" name="title" size="48" /> </td> <td></td> </tr> <tr> <td></td> <td> <input type="button" value="{$cancel.label}" style="float:right" data-href="repositories" onclick="document.location.href=this.getAttribute('data-href')" /> <input type="submit" name="next" value="{$next.label}" /> </td> </tr> </tbody> </table> </form> </xsl:template> </xsl:stylesheet>
- Tomcatの
$CATALINA_HOME/webapps/rdf4j-workbench/transformations
変換フォルダ内に構成ファイルcreate.xsl
を作成します。<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xsl:stylesheet [ <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" > ]> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sparql="http://www.w3.org/2005/sparql-results#" xmlns="http://www.w3.org/1999/xhtml"> <xsl:include href="../locale/messages.xsl" /> <xsl:variable name="title"> <xsl:value-of select="$repository-create.title" /> </xsl:variable> <xsl:include href="template.xsl" /> <xsl:template match="sparql:sparql"> <form action="create"> <table class="dataentry"> <tbody> <tr> <th> <xsl:value-of select="$repository-type.label" /> </th> <td> <select id="type" name="type"> <option value="memory"> Memory Store </option> <option value="memory-lucene"> Memory Store + Lucene </option> <option value="memory-rdfs"> Memory Store + RDFS </option> <option value="memory-rdfs-dt"> Memory Store + RDFS and Direct Type </option> <option value="memory-rdfs-lucene"> Memory Store + RDFS and Lucene </option> <option value="memory-customrule"> Memory Store + Custom Graph Query Inference </option> <option value="memory-spin"> Memory Store + SPIN support </option> <option value="memory-spin-rdfs"> Memory Store + RDFS and SPIN support </option> <option value="memory-shacl"> Memory Store + SHACL </option> <!-- disabled pending GH-1304 option value="memory-spin-rdfs-lucene"> In Memory Store with RDFS+SPIN+Lucene support </option --> <option value="native"> Native Store </option> <option value="native-lucene"> Native Store + Lucene </option> <option value="native-rdfs"> Native Store + RDFS </option> <option value="native-rdfs-dt"> Native Store + RDFS and Direct Type </option> <option value="memory-rdfs-lucene"> Native Store + RDFS and Lucene </option> <option value="native-customrule"> Native Store + Custom Graph Query Inference </option> <option value="native-spin"> Native Store + SPIN support </option> <option value="native-spin-rdfs"> Native Store + RDFS and SPIN support </option> <option value="native-shacl"> Native Store + SHACL </option> <!-- disabled pending GH-1304 option value="native-spin-rdfs-lucene"> Native Java Store with RDFS+SPIN+Lucene support </option --> <option value="remote"> Remote RDF Store </option> <option value="sparql"> SPARQL endpoint proxy </option> <option value="federate">Federation</option> <option value="lmdb">LMDB Store</option> <option value="oracle">Oracle</option> </select> </td> <td></td> </tr> <tr> <th> <xsl:value-of select="$repository-id.label" /> </th> <td> <input type="text" id="id" name="id" size="16" /> </td> <td></td> </tr> <tr> <th> <xsl:value-of select="$repository-title.label" /> </th> <td> <input type="text" id="title" name="title" size="48" /> </td> <td></td> </tr> <tr> <td></td> <td> <input type="button" value="{$cancel.label}" style="float:right" data-href="repositories" onclick="document.location.href=this.getAttribute('data-href')" /> <input type="submit" name="next" value="{$next.label}" /> </td> </tr> </tbody> </table> </form> </xsl:template> </xsl:stylesheet>
- Tomcatを再起動し、
https://localhost:8080/rdf4j-workbench
に移動します。
「Oracle」は、RDF4J Workbenchのドロップダウン・リストにオプションとして表示されます。
- RDF4J Workbenchを介したAdapter for Eclipse RFD4Jの使用
リポジトリの作成および問合せには、RDF4J Workbenchを使用できます。
8.3.2.1 RDF4J Workbenchを介したAdapter for Eclipse RFD4Jの使用
リポジトリの作成および問合せには、RDF4J Workbenchを使用できます。
RDF4J Workbenchには、RDF4J Serverのリポジトリを作成、問合せ、更新および検索するためのWebインタフェースが用意されています。
RDF4J Workbenchを使用した新規リポジトリの作成
- ブラウザにURL
https://localhost:8080/rdf4j-workbench
を入力して、RDF4J Workbenchを起動します。 - サイドバー・メニューで「新規リポジトリ」をクリックし、新規リポジトリの「タイプ」として「Oracle」を選択します。
- 次の図に示すように、新しいリポジトリの「ID」と「タイトル」を入力し、「次」をクリックします。
- モデルの詳細を入力し、「作成」をクリックして新規リポジトリを作成します。
新しく作成されたリポジトリのサマリーが次のように表示されます。
新しく作成したリポジトリは、RDF4J Workbenchのリポジトリのリスト・ページで表示することもできます。
8.3.3 SPARQLサービスとして使用するためのOracle RDF Graph Adapter for Eclipse RDF4Jの設定
RDF4J Workbenchを介してSPARQLサービスを使用するには、RDF4J ServerおよびWorkbenchで使用するためのOracle RDF Graph Adapter for Eclipse RDF4Jの設定の説明に従って、Eclipse RDF4Jサーバーがインストールされ、Oracleデータ・ソース・リポジトリが構成されていることを確認します。
Eclipse RDF4Jサーバー・インストールで提供されるREST APIは、HTTPプロトコルを使用し、SPARQL 1.1プロトコルのW3C勧告に完全準拠した実装をカバーします。これにより、RDF4Jサーバーは標準に完全準拠したSPARQLエンドポイントとして機能します。この機能の詳細は、The RDF4J REST APIを参照してください。
ノート:
RDF4Jサーバー、ワークベンチおよびSPARQLサービスでは、Oracle RDF Graph Adapter for Eclipse RDF4Jの現在のバージョンのMDSYS所有セマンティク・ネットワークのみがサポートされます。次の項では、使用例を示します。
8.3.3.1 Eclipse RDF4J WorkbenchでのAdapter Over SPARQLエンドポイントの使用
この項では、Eclipse RDF4J Workbenchで提供されるSPARQLエンドポイントを介してEclipse RDF4J用のアダプタを使用する例をいくつか説明します。
例8-2 SPARQL更新を実行するリクエスト
次の例では、HTTP POSTを使用していくつかの単純なトリプルを挿入します。ファイルsparql_update.rq
の内容は次のようになっているとします。
PREFIX ex: <http://example.oracle.com/> INSERT DATA { ex:a ex:value "A" . ex:b ex:value "B" . }
その後、次のようにcurl
コマンドライン・ツールを使用して、前述のSPARQL更新を実行できます。
curl -X POST --data-binary "@sparql_update.rq" \ -H "Content-Type: application/sparql-update" \ "http://localhost:8080/rdf4j-server/repositories/MyRDFRepo/statements"
例8-3 HTTP GETを使用したSPARQL問合せの実行リクエスト
このcurl
の例は、HTTP GETを使用してSPARQL問合せを実行します。
curl -X GET -H "Accept: application/sparql-results+json" \ "http://localhost:8080/rdf4j-server/repositories/MyRDFRepo?query=SELECT%20%3Fs%20%3Fp%20%3Fo%0AWHERE%20%7B%20%3Fs%20%3Fp%20%3Fo%20%7D%0ALIMIT%2010"
前のSPARQL更新の例が空のリポジトリで実行された場合、このRESTリクエストは次のレスポンスを返すはずです。
{ "head" : { "vars" : [ "s", "p", "o" ] }, "results" : { "bindings" : [ { "p" : { "type" : "uri", "value" : "http://example.oracle.com/value" }, "s" : { "type" : "uri", "value" : "http://example.oracle.com/b" }, "o" : { "type" : "literal", "value" : "B" } }, { "p" : { "type" : "uri", "value" : "http://example.oracle.com/value" }, "s" : { "type" : "uri", "value" : "http://example.oracle.com/a" }, "o" : { "type" : "literal", "value" : "A" } } ] } }
8.4 データベース接続の管理
Oracle RDF Graph Adapter for Eclipse RDF4Jでは、Oracle Databaseの接続プーリングがサポートされています。
OracleSailStore
のインスタンスは、接続プールを使用してOracleデータベースへの接続を管理します。Oracle Databaseの接続プーリングは、OraclePool
クラスを介して利用できます。通常、OraclePool
はOraclePool (DataSource ods)
コンストラクタを使用してDataSource
で初期化されています。この場合、OraclePool
はデータソースの接続プーリング機能を使用しながらDataSource
の拡張ラッパーとして動作します。OracleSailStore
オブジェクトを作成するときには、storeコンストラクタ内にOraclePool
オブジェクトを指定するだけで十分です。続けて、Eclipse RDF4J用のアダプタによりデータベース接続が自動的に制御されるようになります。OraclePool
には、他にもいくつかのコンストラクタが用意されています。このコンストラクタを使用すると、たとえば、JDBC URL
とデータベースusername
およびpassword
を使用してOraclePool
インスタンスを作成できます。詳細は、Oracle RDF Graph Adapter for Eclipse RDF4Jのダウンロードに含まれるJavadocを参照してください。
明示的にOracle接続オブジェクト(基本的にデータベース接続ラッパーである)を取得する必要がある場合は、OraclePool.getOracle
メソッドを起動します。接続を終了した後は、OraclePool.returnOracleDBtoPool
メソッドを起動して、接続プールにオブジェクトを戻します。
OracleSailStore
からOracleSailConnection
、またはOracleRepository
からOracleSailRepositoryConnection
を取得すると、OraclePool
から新しいOracleDB
オブジェクトが取得され、RDF4J接続オブジェクトの作成に使用されます。READ_COMMITTED
トランザクション分離は、異なるRDF4J接続オブジェクト間で維持されます。
この動作の例外の1つは、OracleSailConnection
の既存のインスタンスでasRepositoryConnection
メソッドをコールしてOracleSailRepositoryConnection
を取得したときに発生します。この場合、元のOracleSailConnection
と新しく取得されたOracleSailRepositoryConnection
は、同じOracleDBオブジェクトを使用します。OracleSailConnection
またはOracleSailRepositoryConnection
オブジェクトの使用が終了したら、そのclose
メソッドをコールしてOracleDB
オブジェクトをOraclePool
に戻す必要があります。そうしないと、アプリケーションで接続リークが発生します。
8.5 SPARQL問合せの実行モデル
Oracle RDF Graph Adapter for Eclipse RDF4J APIを介して実行されるSPARQL問合せは、RDFデータを格納するためのOracleのリレーショナル・スキーマに対するSQL問合せとして実行されます。
OracleのSQLエンジンを使用すると、SPARQL問合せの実行で、パラレル問合せ実行、インメモリー列表現、Exadataスマート・スキャンなどの多くのパフォーマンス機能を利用できます。
SPARQL問合せを実行するには、次の2つの方法があります。
-
Query
またはそのサブインタフェースのいずれかの実装を、基礎となるOracleSailConnection
を持つRepositoryConnection
のprepareQuery
関数から取得できます。 -
TupleExpr
のOracle固有の実装をOracleSPARQLParser
から取得し、OracleSailConnection
のevaluate
メソッドをコールできます。
次のコード・スニペットは、最初の方法を示しています。
//run a query against the repository String queryString = "PREFIX ex: <http://example.org/ontology/>\n" + "SELECT * WHERE {?x ex:name ?y} LIMIT 1 "; TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString); try (TupleQueryResult result = tupleQuery.evaluate()) { while (result.hasNext()) { BindingSet bindingSet = result.next(); psOut.println("value of x: " + bindingSet.getValue("x")); psOut.println("value of y: " + bindingSet.getValue("y")); } }
OracleSailConnection
は、問合せを評価するときに、SPARQL問合せ文字列を使用してデータベース・サーバー上のSEM_APIS.SPARQL_TO_SQL
ストアド・プロシージャをコールし、同等のSQL問合せを取得して、データベース・サーバー上で実行します。SQL問合せの結果は、標準のRDF4J問合せ結果インタフェースのいずれかを介して処理され、戻されます。
8.5.1 BIND値の使用
Oracle RDF Graph Adapter for Eclipse RDF4Jでは、Queryインタフェースで定義されたsetBinding
プロシージャなど、標準のRDF4Jバインド値APIを介してバインド値がサポートされます。Oracleでは、元のSPARQL問合せ文字列にSPARQL BIND
句を追加することでバインド値を実装します。
SELECT * WHERE { ?s <urn:fname> ?fname }前述の問合せでは、問合せ変数
?s
に値<urn:john>
を設定できます。この場合、変換後の問合せは次のようになります。 SELECT * WHERE { BIND (<urn:john> AS ?s) ?s <urn:fname> ?fname }
ノート:
このアプローチは、SPARQLの標準の変数スコープ・ルールに従います。したがって、最も外側のグラフ・パターンで認識されない問合せ変数(副問合せから投影されない変数など)は、バインド値に置換できません。親トピック: SPARQL問合せの実行モデル
8.5.2 JDBC BIND値の使用
Oracle RDF Graph Adapter for Eclipse RDF4Jを使用すると、SPARQL問合せに対して実行される基礎となるSQL文でJDBCバインド値を使用できます。JDBCバインド値の実装は、前の項で説明した標準のRDF4Jバインド値のサポートよりもはるかに高性能です。
JDBCバインド値のサポートでは、標準のRDF4J setBinding
APIが使用されますが、バインド変数は特定の方法で宣言する必要があり、特別な問合せオプションをORACLE_SEM_SM_NS
ネームスペース接頭辞とともに渡す必要があります。問合せに対してJDBCバインド変数を有効にするには、ORACLE_SEM_SM_NS
ネームスペース接頭辞(PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#USE_BIND_VAR=JDBC>
など)にUSE_BIND_VAR=JDBC
を含める必要があります。SPARQL問合せにこの問合せオプションが含まれる場合、単純なSPARQL BIND句に表示されるすべての問合せ変数が、対応するSQL問合せでJDBCバインド値として処理されます。単純なSPARQL BIND句が、BIND (<constant> as ?var)
の形式(BIND("dummy" AS ?bindVar1
など)を持つものです。
次のコード・スニペットは、JDBCバインド値の使用方法を示しています。
例8-4 JDBCバインド値の使用
// query that uses USE_BIND_VAR=JDBC option and declares ?name as a JDBC bind variable
String queryStr =
"PREFIX ex: <http://example.org/>\n"+
"PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n"+
"PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#USE_BIND_VAR=JDBC>\n"+
"SELECT ?friend\n" +
"WHERE {\n" +
" BIND(\"\" AS ?name)\n" +
" ?x foaf:name ?name\n" +
" ?x foaf:knows ?y\n" +
" ?y foaf:name ?friend\n" +
"}";
// prepare the TupleQuery with JDBC bind var option
TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryStr);
// find friends for Jack
tupleQuery.setBinding("name", vf.createLiteral("Jack");
try (TupleQueryResult result = tupleQuery.evaluate()) {
while (result.hasNext()) {
BindingSet bindingSet = result.next();
System.out.println(bindingSet.getValue("friend").stringValue());
}
}
// find friends for Jill
tupleQuery.setBinding("name", vf.createLiteral("Jill");
try (TupleQueryResult result = tupleQuery.evaluate()) {
while (result.hasNext()) {
BindingSet bindingSet = result.next();
System.out.println(bindingSet.getValue("friend").stringValue());
}
}
ノート:
Oracle RDF Graph Adapter for Eclipse RDF4JのJDBCバインド値機能は、SEM_APIS.SPARQL_TO_SQLのバインド変数機能を使用します(SEM_APIS.SPARQL_TO_SQLによるバインド変数の使用を参照)。親トピック: SPARQL問合せの実行モデル
8.5.2.1 JDBCバインド値のサポートの制限
JDBCバインド値をサポートしているのは、SPARQL SELECTおよびASK問合せのみです。
JDBCバインド値のサポートには、次の制限があります。
- JDBCバインド値は次ではサポートされていません。
- SPARQL CONSTRUCT問合せ
- DESCRIBE問合せ
- SPARQL更新文
- 4000文字を超える長さのRDFロング・リテラル値は、JDBCバインド値として使用できません。
- 空白のノードは、JDBCバインド値として使用できません。
親トピック: JDBC BIND値の使用
8.5.3 他の機能をサポートするためのSPARQL問合せ構文への追加
Oracle RDF Graph Adapter for Eclipse RDF4Jでは、問合せを生成および実行するためのオプションを渡すことができます。問合せオプションを含むOracle固有の名前空間を使用してSPARQL名前空間接頭辞の構文をオーバーロードすることで、これらの機能を実装できます。名前空間の形式はPREFIX ORACLE_SEM_xx_NS
で、xx
は機能のタイプ(SM - SEM_MATCH
など)を示します。
8.5.3.1 問合せの実行オプション
PREFIX
を含めることで、問合せの実行オプションをデータベース・サーバーに渡すことができます。PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#option>
前述のSPARQL PREFIX
のoption
は、問合せの実行時に使用される問合せオプション(またはカンマで区切られた複数のオプション)を反映します。
次のオプションがサポートされています。
- DOP=n: 問合せに対する並列度(n)を指定します。
- ODS=n: 実行計画の生成時に使用するオプティマイザ動的サンプリングのレベルを指定します。
次の問合せ例では、ORACLE_SEM_FS_NS
接頭辞を使用して、問合せの実行に並列度4を使用することを指定しています。
PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#dop=4> PREFIX ex: <http://www.example.com/> SELECT * WHERE {?s ex:fname ?fname ; ex:lname ?lname ; ex:dob ?dob}
8.5.3.2 SPARQL_TO_SQL (SEM_MATCH)のオプション
次の形式のSPARQL PREFIX
を含めることで、SPARQL_TO_SQL
オプションをデータベース・サーバーに渡し、SPARQL問合せに対して生成されるSQLに影響を与えることができます。
PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#option>
前述のPREFIX
のoption
は、問合せの実行時に使用されるSPARQL_TO_SQL
オプション(またはカンマで区切られた複数のオプション)を反映します。
使用可能なオプションの詳細は、SEM_MATCH表関数を使用したセマンティク・データの問合せを参照してください。この接頭辞では、SEM_MATCH
またはSEM_APIS.SPARQL_TO_SQL
のオプション引数に有効としてリストされている任意の有効なキーワードまたはキーワード値ペアを使用できます。
次の問合せ例では、ORACLE_SEM_SM_NS
接頭辞を使用して、問合せ内のすべてのトリプル・パターンを結合するためにHASH結合を使用するように指定します。
PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_link_hash>
PREFIX ex: <http://www.example.org/>
SELECT *
WHERE {?s ex:fname ?fname ;
ex:lname ?lname ;
ex:dob ?dob}
8.5.4 SPARQL問合せのサポートで特に留意する点
この項では、SPARQL問合せのサポートで特に留意する点について説明します。
無制限のプロパティ・パス問合せ
デフォルトでは、Oracle RDF Graph Adapter for Eclipse RDF4Jは、無制限のSPARQLプロパティ・パス演算子+
および*
の評価を最大10回の繰返しに制限します。これは、all_max_pp_depth(n)
SPARQL_TO_SQL
オプションを使用して制御できます。n
は、+
または*
と一致する場合に許可される最大反復回数です。値をゼロに指定すると、最大反復回数は無制限になります。
all_max_pp_depth(0)
を使用します。 PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_max_pp_depth(0)> PREFIX ex: <http://www.example.org/> SELECT (COUNT(*) AS ?cnt) WHERE {ex:a ex:p1* ?y}
SPARQLデータセットの指定
Eclipse RDF4J用のアダプタでは、SPARQL問合せ文字列の外部でデータセットを指定できません。Operation
のsetDataset()
メソッドとそのサブインタフェースによるデータセットの指定はサポートされておらず、SailConnection
のevaluate
メソッドへのデータセット・オブジェクトの受渡しもサポートされていません。かわりに、SPARQL句FROM
およびFROM NAMED
を使用して、SPARQL問合せ文字列自体で問合せデータセットを指定します。
問合せタイムアウト
Operation
およびそのサブインタフェースでのsetMaxExecutionTime
メソッドによる問合せタイムアウトはサポートされていません。
ロングRDFリテラル
長さが4000バイトを超えるラージRDFリテラル値は、一部のSPARQL問合せ関数ではサポートされていません。詳細は、SEM_MATCH使用時の特別な考慮事項を参照してください。
親トピック: SPARQL問合せの実行モデル
8.6 SPARQL更新の実行モデル
この項では、Oracle RDF Graph Adapter for Eclipse RDF4JのSPARQL更新の実行モデルについて説明します。
SEM_APIS.UPDATE_MODEL
ストアド・プロシージャを実行することでSPARQL更新操作を実装します。SPARQL更新操作を実行するには、OracleSailRepositoryConnection
のインスタンスのprepareUpdate
関数からUpdate
オブジェクトを取得します。
ノート:
OracleSailRepositoryConnection
インスタンスが必要です。OracleSailStore
から作成されたプレーンなSailRepository
インスタンスでは、更新が正しく実行されません。
次の例は、RDF4J APIを使用してOracle RDFモデルを更新する方法を示します。
String updString = "PREFIX people: <http://www.example.org/people/>\n"+ "PREFIX ont: <http://www.example.org/ontology/>\n"+ "INSERT DATA { GRAPH <urn:g1> { \n"+ " people:Sue a ont:Person; \n"+ " ont:name \"Sue\" . } }"; Update upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString); upd.execute();
8.6.1 SPARQL更新のトランザクション管理
RDF4J APIを介して実行されるSPARQL更新操作は、標準のRDF4Jトランザクション管理規則に従います。SPARQL更新は、デフォルトで自動的にコミットされます。ただし、明示的なトランザクションがbegin
を使用してSailRepositoryConnection
で開始された場合、アクティブなトランザクションがcommit
を使用して明示的にコミットされるまで、後続のSPARQL更新操作はコミットされません。未コミット状態の更新操作は、rollback
を使用してロールバックできます。
親トピック: SPARQL更新の実行モデル
8.6.2 他の機能をサポートするためのSPARQL構文への追加
SPARQL問合せの場合と同様に、Oracle RDF Graph Adapter for Eclipse RDF4JではSPARQL更新を実行するためのオプションを渡すことができます。SEM_APIS.UPDATE_MODEL
オプションを含むOracle固有の名前空間を使用してSPARQL名前空間接頭辞の構文をオーバーロードすることで、これらの機能を実装できます。
8.6.2.1 UPDATE_MODELオプション
PREFIX
宣言を含めることで、SEM_APIS.UPDATE_MODEL
にオプションを渡すことができます。PREFIX ORACLE_SEM_UM_NS: <http://oracle.com/semtech#option>前述の
PREFIX
のoption
は、更新の実行時に使用されるUPDATE_MODEL
オプション(またはカンマで区切られた複数のオプション)を反映します。
使用可能なオプションの詳細は、SEM_APIS.UPDATE_MODELを参照してください。このPREFIX
では、UPDATE_MODEL
のオプション引数に有効としてリストされている任意の有効なキーワードまたはキーワード値ペアを使用できます。
次の問合せ例では、ORACLE_SEM_UM_NS
接頭辞を使用して、更新の並列度2を指定します。
PREFIX ORACLE_SEM_UM_NS: <http://oracle.com/semtech#parallel(2)> PREFIX ex: <http://www.example.org/> INSERT {GRAPH ex:g1 {ex:a ex:reachable ?y}} WHERE {ex:a ex:p1* ?y}
親トピック: 他の機能をサポートするためのSPARQL構文への追加
8.6.2.2 UPDATE_MODELの一致オプション
次の形式でPREFIX
宣言を含めることで、SEM_APIS.UPDATE_MODEL
に一致オプションを渡すことができます。
PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#option>
option
は、SPARQL更新の実行中に使用されるUPDATE_MODEL
一致オプション(またはカンマで区切られた複数の一致オプション)を反映します。
使用可能なオプションの詳細は、SEM_APIS.UPDATE_MODELを参照してください。このPREFIX
では、UPDATE_MODEL
の match_options
引数に有効としてリストされている任意の有効なキーワードまたはキーワード値ペアを使用できます。
次の例では、ORACLE_SEM_SM_NS
接頭辞を使用して、最大の無制限のプロパティ・パス深度5を指定します。
PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_max_pp_depth(5)> PREFIX ex: <http://www.example.org/> INSERT {GRAPH ex:g1 {ex:a ex:reachable ?y}} WHERE {ex:a ex:p1* ?y}
親トピック: 他の機能をサポートするためのSPARQL構文への追加
8.6.3 SPARQL更新のサポートで特に留意する点
更新操作での無制限のプロパティ・パス
前の項で説明したように、Oracle RDF Graph Adapter for Eclipse RDF4Jは、無制限のSPARQLプロパティ・パス演算子+
および*
の評価を最大10回の繰返しに制限します。このデフォルト設定は、WHERE
句でプロパティ・パスを使用するSPARQL更新操作に影響します。最大反復回数の設定は、all_max_pp_depth(n)
オプションを使用して制御できます。n
は、+
または*
と一致する場合に許可される最大反復回数です。値をゼロに指定すると、最大反復回数は無制限になります。
次の例では、完全に無制限の検索でSEM_APIS.UPDATE_MODEL
の一致オプションとしてall_max_pp_depth(0)
を使用します。
PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_max_pp_depth(0)> PREFIX ex: <http://www.example.org/> INSERT { GRAPH ex:g1 { ex:a ex:reachable ?y}} WHERE { ex:a ex:p1* ?y}
SPARQLデータセットの指定
Oracle RDF Graph Adapter for Eclipse RDF4Jでは、SPARQL更新文字列の外部でデータセットを指定できません。Operation
およびそのサブインタフェースでのsetDataset
メソッドによるデータセット指定はサポートされていません。かわりに、WITH
、USING
およびUSING NAMED SPARQL
句を使用して、SPARQL更新文字列自体でデータセットを指定します。
バインド値
SPARQL更新操作では、バインド値はサポートされていません。
ロングRDFリテラル
前の項で説明したように、長さが4000バイトを超えるラージRDFリテラル値は、一部のSPARQL問合せ関数ではサポートされていません。この制限は、ロング・リテラル・データに対してこれらの関数のいずれかを使用するSPARQL更新操作に影響します。詳細は、SEM_MATCH使用時の特別な考慮事項を参照してください。
更新タイムアウト
Operation
およびそのサブインタフェースでのsetMaxExecutionTime
メソッドによる更新タイムアウトはサポートされていません。
親トピック: SPARQL更新の実行モデル
8.7 RDFデータの効率的なロード
Oracle RDF Graph Adapter for Eclipse RDF4Jには、ファイルまたはコレクションから大量のRDFデータを効率的にロードするための追加または改善されたJavaメソッドが用意されています。
RDFデータのバルク・ロード
アダプタのバルク・ロード機能には、次の2つのステップが含まれます。
- ファイルまたは文のコレクションからステージング表へのRDFデータのロード。
- ステージング表からRDF記憶域表へのRDFデータのロード。
アダプタのOracleBulkUpdateHandler
クラスには、バルク・ロードを実装する2種類の方法を可能にするメソッドが用意されています。
addInBulk
: これらのメソッドを使用すると、RDFデータのバルク・ロードで説明されている両方のステップを1回の起動で実行できます。この方法は、ロード元のファイルまたはコレクションが1つのみの場合に適しています。prepareBulk
およびcompleteBulk
:prepareBulk
を1回以上起動できます。各コールでは、RDFデータのバルク・ロードのステップ1を実装します。後で、
completeBulk
を1回起動してRDFデータのバルク・ロードのステップ2を実行し、これら複数のprepareBulk
コールから取得したステージング表データをロードできます。この方法は、ロード元のファイルが複数ある場合に適しています。
また、アダプタの OracleSailRepositoryConnection
クラスは、SailRepositoryConnection
クラスの次のメソッドについてバルク・ロード実装を提供します。
public void add(InputStream in, String baseURI, RDFFormat dataFormat, Resource... contexts)
圧縮ファイルからのバルク・ロードもサポートされていますが、現在はgzipファイルのみに制限されています。
8.8 Oracle RDF Graph Adapter for Eclipse RDF4Jのベスト・プラクティス
この項では、Oracle RDF Graph Adapter for Eclipse RDF4Jのパフォーマンスのベスト・プラクティスについて説明します。
リソースのクローズ
アプリケーション・プログラマは、リソース・リークを避けるように注意する必要があります。Oracle RDF Graph Adapter for Eclipse RDF4Jで回避すべき2つの最も重要なタイプのリソース・リークは、JDBC接続リークとデータベース・カーソル・リークです。
JDBC接続リークの回避
OracleRepository
またはOracleSailStore
でgetConnection
をコールしてOracleSailConnection
またはOracleSailRepositoryConnection
オブジェクトを作成するたびに、OraclePoolから新しいJDBC接続が取得されます。作成したOracleSailConnection
またはOracleSailRepositoryConnection
オブジェクトでclose
メソッドを明示的にコールして、これらのJDBC接続がOraclePoolに返されることを確認する必要があります。
データベース・カーソル・リークの回避
いくつかのRDF4J APIコールはイテレータを戻します。Eclipse RDF4J用のアダプタを使用する場合、これらのイテレータの多くには、イテレータの作成時にオープンし、データベース・カーソル・リークを回避するためにクローズする必要がある、基になるJDBC ResultSetがあります。
Oracleのイテレータは、次の2通りの方法でクローズできます。
- これらを
try-with-resources
文で作成し、JavaAutoclosable
に依存してイテレータをクローズします。String queryString = "PREFIX ex: <http://example.org/ontology/>\n"+ "SELECT * WHERE {?x ex:name ?y}\n" + "ORDER BY ASC(STR(?y)) LIMIT 1 "; TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString); try (TupleQueryResult result = tupleQuery.evaluate()) { while (result.hasNext()) { BindingSet bindingSet = result.next(); System.out.println("value of x: " + bindingSet.getValue("x")); System.out..println("value of y: " + bindingSet.getValue("y")) } }
- イテレータで
close
メソッドを明示的にコールします。String queryString = "PREFIX ex: <http://example.org/ontology/>\n"+ "SELECT * WHERE {?x ex:name ?y}\n" + "ORDER BY ASC(STR(?y)) LIMIT 1 "; TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString); TupleQueryResult result = tupleQuery.evaluate(); try { while (result.hasNext()) { BindingSet bindingSet = result.next(); System.out.println("value of x: " + bindingSet.getValue("x")); System.out..println("value of y: " + bindingSet.getValue("y")) } } finally { result.close(); }
統計の収集
大量のセマンティク・データをデータベースにロードした後、推論を実行する前に、アプリケーション表、セマンティク・モデルおよび推論されたグラフ(存在する場合)を分析することをお薦めします。分析操作を実行することで統計情報が収集され、問合せの応答時にOracleオプティマイザが効率的な実行計画を選択しやすくなります。
関連する統計を収集するには、OracleSailConnection
で、次のメソッドを使用します。
OracleSailConnection.analyze
OracleSailConnection.analyzeApplicationTable
パラメータを含むこれらのメソッドの詳細は、RDF Semantic Graph Support for Eclipse RDF4JのJavadocを参照してください。
JDBCバインド値
定数値のみが異なる一連のSPARQLクエリを実行する場合は、常に、JDBCバインド値を使用することをお薦めします。バインド値を使用すると、大量の問合せコンパイル・オーバーヘッドが節約され、問合せワークロードのスループットが大幅に向上します。
JDBCバインド値の詳細は、JDBCバインド値の使用および例13: JDBCバインド値の使用を参照してください。
8.9 Oracle RDF Graph Adapter for Eclipse RDF4Jでの空白ノードのサポート
SPARQL問合せにおいて、<
と>
で囲まれていない空白ノードは、問合せがEclipse RDF4J用のアダプタのサポートを介して実行されるときに変数とみなされます。これは、SPARQL標準セマンティクと一致します。
ただし、<
と>
で囲まれた空白ノードは、問合せが実行されるときに定数とみなされ、空白ノード・ラベルには、基礎となるデータのモデル化で必要とされる適切な接頭辞が、support for Eclipse RDF4Jによって追加されます。アプリケーション表のCONTEXT
列には、空白ノードを使用しません。2つの異なるセマンティク・モデルの名前付きグラフの空白ノードが同じラベルを持つ場合、これらが同じリソースとみなされてしまうためです。これは、トリプル内の空白ノードには該当せず、異なるモデルのものは別々に格納されます。
Oracleデータベースに格納されている場合、空白ノードには、モデルID
およびグラフ名に基づく接頭辞が埋め込まれます。したがって、RDF4J APIおよびOracle Databaseで使用される空白ノード間の変換が必要です。これは次のメソッドを使用して行います。
OracleUtils.addOracleBNodePrefix
OracleUtils.removeOracleBNodePrefix
8.10 Oracle RDF Graph Adapter for Eclipse RDF4Jでサポートされていない機能
この項では、現在のバージョンのOracle RDF Graph Adapter for Eclipse RDF4Jでサポートされていない機能について説明します。
Oracle RDF Graphの次の機能は、Eclipse RDF4J用のアダプタのこのバージョンではサポートされません。
- RDFビュー・モデル
- ネイティブのUnicodeの記憶域(Oracle Databaseバージョン21c以降で使用可能)
- Oracle Autonomous DatabaseでのRDFグラフの管理
Operation
およびそのサブインタフェースでのsetDataset
メソッドを使用したSPARQLデータセット指定はサポートされていません。データセットはSPARQL問合せまたは更新文字列自体で指定する必要があります。Operation
およびそのサブインタフェースでのsetMaxExecutionTime
メソッドによる問合せおよび更新タイムアウトの指定はサポートされていません。OracleTuple
を実装していないTupleExpr
をOracleSailConnection
のevaluate
メソッドに渡すことはできません。OracleSailRepositoryConnection
以外のRepositoryConnection
実装から作成されたUpdateオブジェクトは、Oracle RDFに対して実行できません。
8.11 Oracle RDF Graph Adapter for Eclipse RDF4Jを使用した問合せの例
この項では、Oracle RDF Graph Adapter for Eclipse RDF4Jを使用するための問合せの例を示します。
これらの例を実行するには、Javaコードでアダプタを使用するためのサポート・ライブラリで説明されているすべてのサポート・ライブラリがCLASSPATH
定義に含まれていることを確認します。
- コード例をJavaソース・ファイルに含めます。
CP
という名前のCLASSPATH
環境変数を定義して、関連するjarファイルを含めます。たとえば、次のように定義できます。setenv CP .:ojdbc8.jar:ucp.jar:oracle-rdf4j-adapter-4.2.1.jar:log4j-api-2.17.2.jar:log4j-core-2.17.2.jar:log4j-slf4j-impl-2.17.2.jar:slf4j-api-1.7.36.jar:eclipse-rdf4j-4.2.1-onejar.jar:commons-io-2.11.0.jar
ノート:
前述のsetenv
コマンドは、jarファイルが現在のディレクトリにあることを前提としています。コマンドを変更して、これらのjarファイルの環境内の場所を示す必要がある場合があります。- Javaソース・ファイルをコンパイルします。たとえば、ソース・ファイル
Test.java
をコンパイルするには、次のコマンドを実行します。javac -classpath $CP Test.java
- 特定のJavaプログラムに必要なコマンドライン引数を渡して、コンパイルされたファイルを実行します。
- この項の例では、既存のMDSYSネットワークに対してコンパイルされたファイルを実行できます。たとえば、既存のMDSYSネットワークで、コンパイルされたファイルを
TestModel
という名前のRDFグラフ(モデル)で実行するには、次のコマンドを実行します。java -classpath $CP Test jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> TestModel
- この例では、スキーマプライベート・ネットワークをオプションで使用することもできます。したがって、この項の例のコンパイルされたファイルを、既存のスキーマプライベートネットワークに対して実行できます。たとえば、コンパイルされたファイルを、所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークの
TestModel
という名前のRDFグラフ(モデル)で実行するには、次のコマンドを実行します。java -classpath $CP Test jdbc:oracle:thin:@localhost:1521:orcl scott <password-for-scott> TestModel scott net1
- この項の例では、既存のMDSYSネットワークに対してコンパイルされたファイルを実行できます。たとえば、既存のMDSYSネットワークで、コンパイルされたファイルを
8.11.1 例1: 基本操作
例8-5に、add文やremove文などの基本操作を実行するBasicOper.java
ファイルを示します。
例8-5 基本操作
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.sail.SailException;
public class BasicOper {
public static void main(String[] args) throws ConnectionSetupException, SQLException, IOException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String networkOwner = (args.length > 5) ? args[4] : null;
String networkName = (args.length > 5) ? args[5] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
OracleSailConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
ValueFactory f = sr.getValueFactory();
conn = store.getConnection();
// create some resources and literals to make statements out of
IRI p = f.createIRI("http://p");
IRI domain = f.createIRI("http://www.w3.org/2000/01/rdf-schema#domain");
IRI cls = f.createIRI("http://cls");
IRI a = f.createIRI("http://a");
IRI b = f.createIRI("http://b");
IRI ng1 = f.createIRI("http://ng1");
conn.addStatement(p, domain, cls);
conn.addStatement(p, domain, cls, ng1);
conn.addStatement(a, p, b, ng1);
psOut.println("size for given contexts " + ng1 + ": " + conn.size(ng1));
// returns OracleStatements
CloseableIteration < ?extends Statement, SailException > it;
int cnt;
// retrieves all statements that appear in the repository(regardless of context)
cnt = 0;
it = conn.getStatements(null, null, null, false);
while (it.hasNext()) {
Statement stmt = it.next();
psOut.println("getStatements: stmt#" + (++cnt) + ":" + stmt.toString());
}
it.close();
conn.removeStatements(null, null, null, ng1);
psOut.println("size of context " + ng1 + ":" + conn.size(ng1));
conn.removeAll();
psOut.println("size of store: " + conn.size());
}
finally {
if (conn != null && conn.isOpen()) {
conn.close();
}
if (op != null && op.getOracleDB() != null)
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
if (sr != null) sr.shutDown();
if (store != null) store.shutDown();
if (op != null) op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP BasicOper.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP BasicOper jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP BasicOper jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel scott net1
java
コマンドの出力は、次のようになります。
size for given contexts http://ng1: 2
getStatements: stmt#1: (http://a, http://p, http://b) [http://ng1]
getStatements: stmt#2: (http://p, http://www.w3.org/2000/01/rdf-schema#domain, http://cls) [http://ng1]
getStatements: stmt#3: (http://p, http://www.w3.org/2000/01/rdf-schema#domain, http://cls) [null]
size of context http://ng1:0
size of store: 0
8.11.2 例2: TRIG形式のデータ・ファイルを追加する
LoadFile.java
ファイルを示します。
例8-6 TRIG形式のデータ・ファイルの追加
import java.io. * ;
import java.sql.SQLException;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.rio.RDFParseException;
import org.eclipse.rdf4j.sail.SailException;
import org.eclipse.rdf4j.rio.RDFFormat;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
public class LoadFile {
public static void main(String[] args) throws ConnectionSetupException,
SQLException, SailException, RDFParseException, RepositoryException,
IOException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String trigFile = args[4];
String networkOwner = (args.length > 6) ? args[5] : null;
String networkName = (args.length > 6) ? args[6] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection repConn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
repConn = sr.getConnection();
psOut.println("testBulkLoad: start: before-load Size=" + repConn.size());
repConn.add(new File(trigFile), "http://my.com/", RDFFormat.TRIG);
repConn.commit();
psOut.println("size " + Long.toString(repConn.size()));
}
finally {
if (repConn != null) {
repConn.close();
}
if (op != null) OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
if (sr != null) sr.shutDown();
if (store != null) store.shutDown();
if (op != null) op.close();
}
}
}
この例を実行するため、次のようなサンプルのTriGデータ・ファイルがtest.trig
という名前で作成されているとします。
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix swp: <http://www.w3.org/2004/03/trix/swp-1/>.
@prefix dc: <http://purl.org/dc/elements/1.1/>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix ex: <http://example.org/>.
@prefix : <http://example.org/>.
# default graph
{
<http://example.org/bob> dc:publisher "Bob Hacker".
<http://example.org/alice> dc:publisher "Alice Hacker".
}
:bob{
_:a foaf:mbox <mailto:bob@oldcorp.example.org>.
}
:alice{
_:a foaf:name "Alice".
_:a foaf:mbox <mailto:alice@work.example.org>.
}
:jack {
_:a foaf:name "Jack".
_:a foaf:mbox <mailto:jack@oracle.example.org>.
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP LoadFile.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP LoadFile jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel ./test.trig
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP LoadFile jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel ./test.trig scott net1
java
コマンドの出力は、次のようになります。
testBulkLoad: start: before-load Size=0
size 7
8.11.3 例3: 単純な問合せ
SimpleQuery.java
ファイルを示します。
例8-7 単純な問合せ
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
public class SimpleQuery {
public static void main(String[] args) throws ConnectionSetupException, SQLException, IOException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String networkOwner = (args.length > 5) ? args[4] : null;
String networkName = (args.length > 5) ? args[5] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
ValueFactory f = sr.getValueFactory();
conn = sr.getConnection();
// create some resources and literals to make statements out of
IRI alice = f.createIRI("http://example.org/people/alice");
IRI name = f.createIRI("http://example.org/ontology/name");
IRI person = f.createIRI("http://example.org/ontology/Person");
Literal alicesName = f.createLiteral("Alice");
conn.clear(); // to start from scratch
conn.add(alice, RDF.TYPE, person);
conn.add(alice, name, alicesName);
conn.commit();
//run a query against the repository
String queryString =
"PREFIX ex: <http://example.org/ontology/>\n" +
"SELECT * WHERE {?x ex:name ?y}\n" +
"ORDER BY ASC(STR(?y)) LIMIT 1 ";
TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
try (TupleQueryResult result = tupleQuery.evaluate()) {
while (result.hasNext()) {
BindingSet bindingSet = result.next();
psOut.println("value of x: " + bindingSet.getValue("x"));
psOut.println("value of y: " + bindingSet.getValue("y"));
}
}
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
sr.shutDown();
store.shutDown();
op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP SimpleQuery.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SimpleQuery jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SimpleQuery jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel scott net1
java
コマンドの出力は、次のようになります。
value of x: http://example.org/people/alice
value of y: "Alice"
8.11.4 例4: 単純なバルク・ロード
SimpleBulkload.java
ファイルを示します。
例8-8 単純なバルク・ロード
import java.io. * ;
import java.sql.SQLException;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.rio.RDFParseException;
import org.eclipse.rdf4j.sail.SailException;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.repository.Repository;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
public class SimpleBulkLoad {
public static void main(String[] args) throws ConnectionSetupException, SQLException,
SailException, RDFParseException, RepositoryException, IOException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String filename = args[4]; // N-TRIPLES file
String networkOwner = (args.length > 6) ? args[5] : null;
String networkName = (args.length > 6) ? args[6] : null;
OraclePool op = new OraclePool(jdbcUrl, user, password);
OracleSailStore store = new OracleSailStore(op, model, networkOwner, networkName);
OracleSailConnection osc = store.getConnection();
Repository sr = new OracleRepository(store);
ValueFactory f = sr.getValueFactory();
try {
psOut.println("testBulkLoad: start");
FileInputStream fis = new
FileInputStream(filename);
long loadBegin = System.currentTimeMillis();
IRI ng1 = f.createIRI("http://QuadFromTriple");
osc.getBulkUpdateHandler().addInBulk(
fis, "http://abc", // baseURI
RDFFormat.NTRIPLES, // dataFormat
null, // tablespaceName
50, // batchSize
null, // flags
ng1 // Resource... for contexts
);
long loadEnd = System.currentTimeMillis();
long size_no_contexts = osc.size((Resource) null);
long size_all_contexts = osc.size();
psOut.println("testBulkLoad: " + (loadEnd - loadBegin) +
"ms. Size:" + " NO_CONTEXTS=" + size_no_contexts + " ALL_CONTEXTS=" + size_all_contexts);
// cleanup
osc.removeAll();
psOut.println("size of store: " + osc.size());
}
finally {
if (osc != null && osc.isOpen()) osc.close();
if (op != null) OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
if (sr != null) sr.shutDown();
if (store != null) store.shutDown();
if (op != null) op.close();
}
}
}
この例を実行するため、次のようなサンプルのntripleデータ・ファイルがtest.ntriples
という名前で作成されているとします。
<urn:JohnFrench> <urn:name> "John".
<urn:JohnFrench> <urn:speaks> "French".
<urn:JohnFrench> <urn:height> <urn:InchValue>.
<urn:InchValue> <urn:value> "63".
<urn:InchValue> <urn:unit> "inch".
<http://data.linkedmdb.org/movie/onto/genreNameChainElem1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://data.linkedmdb.org/movie/genre>.
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP SimpleBulkLoad.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SimpleBulkLoad jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel ./test.ntriples
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SimpleBulkLoad jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel ./test.ntriples scott net1
java
コマンドの出力は、次のようになります。
testBulkLoad: start
testBulkLoad: 8222ms.
Size: NO_CONTEXTS=0 ALL_CONTEXTS=6
size of store: 0
8.11.5 例5: RDF/XMLのバルク・ロード
BulkLoadRDFXML.java
ファイルを示します。
例8-9 RDF/XMLのバルク・ロード
import java.io. * ;
import java.sql.SQLException;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.rio.RDFParseException;
import org.eclipse.rdf4j.sail.SailException;
import org.eclipse.rdf4j.rio.RDFFormat;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
public class BulkLoadRDFXML {
public static void main(String[] args) throws
ConnectionSetupException, SQLException, SailException,
RDFParseException, RepositoryException, IOException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String rdfxmlFile = args[4]; // RDF/XML-format data file
String networkOwner = (args.length > 6) ? args[5] : null;
String networkName = (args.length > 6) ? args[6] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
OracleSailConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
conn = store.getConnection();
FileInputStream fis = new FileInputStream(rdfxmlFile);
psOut.println("testBulkLoad: start: before-load Size=" + conn.size());
long loadBegin = System.currentTimeMillis();
conn.getBulkUpdateHandler().addInBulk(
fis,
"http://abc", // baseURI
RDFFormat.RDFXML, // dataFormat
null, // tablespaceName
null, // flags
null, // StatusListener
(Resource[]) null // Resource...for contexts
);
long loadEnd = System.currentTimeMillis();
psOut.println("testBulkLoad: " + (loadEnd - loadBegin) + "ms. Size=" + conn.size() + "\n");
}
finally {
if (conn != null && conn.isOpen()) {
conn.close();
}
if (op != null) OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
if (sr != null) sr.shutDown();
if (store != null) store.shutDown();
if (op != null) op.close();
}
}
}
この例を実行するため、次のようなサンプル・ファイルがRdfXmlData.rdfxml
という名前で作成されているとします。
<?xml version="1.0"?>
<!DOCTYPE owl [
<!ENTITY owl "http://www.w3.org/2002/07/owl#" >
<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
]>
<rdf:RDF
xmlns = "http://a/b#" xml:base = "http://a/b#" xmlns:my = "http://a/b#"
xmlns:owl = "http://www.w3.org/2002/07/owl#"
xmlns:rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs= "http://www.w3.org/2000/01/rdf-schema#"
xmlns:xsd = "http://www.w3.org/2001/XMLSchema#">
<owl:Class rdf:ID="Color">
<owl:oneOf rdf:parseType="Collection">
<owl:Thing rdf:ID="Red"/>
<owl:Thing rdf:ID="Blue"/>
</owl:oneOf>
</owl:Class>
</rdf:RDF>
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP BulkLoadRDFXML.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP BulkLoadRDFXML jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel ./RdfXmlData.rdfxml
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP BulkLoadRDFXML jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel ./RdfXmlData.rdfxml scott net1
java
コマンドの出力は、次のようになります。
testBulkLoad: start: before-load Size=0
testBulkLoad: 6732ms. Size=8
8.11.6 例6: SPARQL ASK問合せ
SparqlASK.java
ファイルを示します。
例8-10 SPARQL ASK問合せ
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailRepositoryConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.BooleanQuery;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
public class SparqlASK {
public static void main(String[] args) throws ConnectionSetupException, SQLException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String networkOwner = (args.length > 5) ? args[4] : null;
String networkName = (args.length > 5) ? args[5] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
conn = sr.getConnection();
OracleSailConnection osc =
(OracleSailConnection)((OracleSailRepositoryConnection) conn).getSailConnection();
ValueFactory vf = sr.getValueFactory();
IRI p = vf.createIRI("http://p");
IRI cls = vf.createIRI("http://cls");
conn.clear();
conn.add(p, RDFS.DOMAIN, cls);
conn.commit();
osc.analyze(); // analyze the semantic model
osc.analyzeApplicationTable(); // and then the application table
BooleanQuery tq = null;
tq = conn.prepareBooleanQuery(QueryLanguage.SPARQL, "ASK { ?x ?p <http://cls> }");
boolean b = tq.evaluate();
psOut.println("\nAnswer is " + Boolean.toString(b));
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
sr.shutDown();
store.shutDown();
op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP SparqlASK.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SparqlASK jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SparqlASK jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1
java
コマンドの出力は、次のようになります。
Answer is true
8.11.7 例7: SPARQL CONSTRUCT問合せ
SparqlConstruct.java
ファイルを示します。
例8-11 SPARQL CONSTRUCT問合せ
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailRepositoryConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.GraphQuery;
import org.eclipse.rdf4j.query.GraphQueryResult;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
public class SparqlConstruct {
public static void main(String[] args) throws ConnectionSetupException, SQLException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String networkOwner = (args.length > 5) ? args[4] : null;
String networkName = (args.length > 5) ? args[5] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
conn = sr.getConnection();
ValueFactory vf = sr.getValueFactory();
IRI p = vf.createIRI("http://p");
IRI cls = vf.createIRI("http://cls");
conn.clear();
conn.add(p, RDFS.DOMAIN, cls);
conn.commit();
OracleSailConnection osc =
(OracleSailConnection)((OracleSailRepositoryConnection) conn).getSailConnection();
osc.analyze(); // analyze the semantic model
osc.analyzeApplicationTable(); // and then the application table
GraphQuery tq = null; // Construct Query
tq = conn.prepareGraphQuery(QueryLanguage.SPARQL,
"CONSTRUCT {?x <http://new_eq_p> ?o } WHERE { ?x ?p ?o }");
psOut.println("Start construct query");
try (GraphQueryResult result = tq.evaluate()) {
while (result.hasNext()) {
Statement stmt = (Statement) result.next();
psOut.println(stmt.toString());
}
}
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
sr.shutDown();
store.shutDown();
op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP SparqlConstruct.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SparqlConstruct jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SparqlConstruct jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1
java
コマンドの出力は、次のようになります。
Start construct query
(http://p, http://new_eq_p, http://cls)
8.11.8 例8: 名前付きグラフ問合せ
NamedGraph.java
ファイルを示します。
例8-12 名前付きグラフ問合せ
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailRepositoryConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.rio.RDFFormat;
public class NamedGraph {
public static void main(String[] args) throws ConnectionSetupException, SQLException, IOException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String trigFile = args[4]; // TRIG-format data file
String networkOwner = (args.length > 6) ? args[5] : null;
String networkName = (args.length > 6) ? args[6] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
conn = sr.getConnection();
conn.begin();
conn.clear();
// load the data incrementally since it is very small file
conn.add(new File(trigFile), "http://my.com/", RDFFormat.TRIG);
conn.commit();
OracleSailConnection osc = (OracleSailConnection)((OracleSailRepositoryConnection) conn).getSailConnection();
osc.analyze(); // analyze the semantic model
osc.analyzeApplicationTable(); // and then the application table
TupleQuery tq = null;
tq = conn.prepareTupleQuery(QueryLanguage.SPARQL,
"PREFIX : <http://purl.org/dc/elements/1.1/>\n" +
"SELECT ?g ?s ?p ?o\n" +
"WHERE {?g :publisher ?o1 . GRAPH ?g {?s ?p ?o}}\n" +
"ORDER BY ?g ?s ?p ?o");
try (TupleQueryResult result = tq.evaluate()) {
int idx = 0;
while (result.hasNext()) {
idx++;
BindingSet bindingSet = result.next();
psOut.print("\nsolution " + bindingSet.toString());
}
psOut.println("\ntotal # of solution " + Integer.toString(idx));
}
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
sr.shutDown();
store.shutDown();
op.close();
}
}
}
この例を実行するため、TRIG
形式のtest.trig
ファイルが次のように作成されているとします。
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix swp: <http://www.w3.org/2004/03/trix/swp-1/>.
@prefix dc: <http://purl.org/dc/elements/1.1/>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix : <http://example.org/>.
# default graph
{
:bobGraph dc:publisher "Bob Hacker" .
:aliceGraph dc:publisher "Alice Hacker" .
}
:bobGraph {
:bob foaf:mbox <mailto:bob@oldcorp.example.org> .
}
:aliceGraph {
:alice foaf:name "Alice" .
:alice foaf:mbox <mailto:alice@work.example.org> .
}
:jackGraph {
:jack foaf:name "Jack" .
:jack foaf:mbox <mailto:jack@oracle.example.org> .
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP NamedGraph.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP NamedGraph jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel ./test.trig
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP NamedGraph jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel ./test.trig scott net1
java
コマンドの出力は、次のようになります。
solution
[p=http://xmlns.com/foaf/0.1/mbox;s=http://example.org/alice;g=http://example.org/aliceGraph;o=mailto:alice@work.example.org]
solution
[p=http://xmlns.com/foaf/0.1/name;s=http://example.org/alice;g=http://example.org/aliceGraph;o="Alice"]
solution
[p=http://xmlns.com/foaf/0.1/mbox;s=http://example.org/bob;g=http://example.org/bobGraph;o=mailto:bob@oldcorp.example.org]
total # of solution 3
8.11.9 例9: 一致件数の取得
CountQuery.java
ファイルを示します。
例8-13 一致件数の取得
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailRepositoryConnection;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
public class CountQuery {
public static void main(String[] args) throws
ConnectionSetupException, SQLException
{
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String networkOwner = (args.length > 5) ? args[4] : null;
String networkName = (args.length > 5) ? args[5] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
conn = sr.getConnection();
ValueFactory f = conn.getValueFactory();
// create some resources and literals to make statements out of
IRI alice = f.createIRI("http://example.org/people/alice");
IRI name = f.createIRI("http://example.org/ontology/name");
IRI person = f.createIRI("http://example.org/ontology/Person");
Literal alicesName = f.createLiteral("Alice");
conn.begin();
// clear model to start fresh
conn.clear();
conn.add(alice, RDF.TYPE, person);
conn.add(alice, name, alicesName);
conn.commit();
OracleSailConnection osc =
(OracleSailConnection)((OracleSailRepositoryConnection) conn).getSailConnection();
osc.analyze();
osc.analyzeApplicationTable();
// Run a query and only return the number of matches (the count ! )
String queryString = " SELECT (COUNT(*) AS ?totalCount) WHERE {?s ?p ?y} ";
TupleQuery tupleQuery = conn.prepareTupleQuery(
QueryLanguage.SPARQL, queryString);
try (TupleQueryResult result = tupleQuery.evaluate()) {
if (result.hasNext()) {
BindingSet bindingSet = result.next();
String totalCount = bindingSet.getValue("totalCount").stringValue();
psOut.println("number of matches: " + totalCount);
}
}
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
sr.shutDown();
store.shutDown();
op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP CountQuery.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP CountQuery jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP CountQuery jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1
java
コマンドの出力は、次のようになります。
number of matches: 2
8.11.10 例10: 問合せパターンの定数に対するバインド変数の指定
BindVar.java
ファイルを示します。
例8-14 問合せパターンの定数に対するバインド変数の指定
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
public class BindVar {
public static void main(String[] args) throws ConnectionSetupException, SQLException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String networkOwner = (args.length > 5) ? args[4] : null;
String networkName = (args.length > 5) ? args[5] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
conn = sr.getConnection();
ValueFactory f = conn.getValueFactory();
conn.begin();
conn.clear();
// create some resources and literals to make statements out of
// Alice
IRI alice = f.createIRI("http://example.org/people/alice");
IRI name = f.createIRI("http://example.org/ontology/name");
IRI person = f.createIRI("http://example.org/ontology/Person");
Literal alicesName = f.createLiteral("Alice");
conn.add(alice, RDF.TYPE, person);
conn.add(alice, name, alicesName);
//Bob
IRI bob = f.createIRI("http://example.org/people/bob");
Literal bobsName = f.createLiteral("Bob");
conn.add(bob, RDF.TYPE, person);
conn.add(bob, name, bobsName);
conn.commit();
String queryString =
" PREFIX ex: <http://example.org/ontology/> " +
" Select ?name \n" + " WHERE \n" + " { SELECT * WHERE { ?person ex:name ?name} }\n" +
" ORDER BY ?name";
TupleQuery tupleQuery = conn.prepareTupleQuery(
QueryLanguage.SPARQL, queryString);
// set binding for ?person = Alice
tupleQuery.setBinding("person", alice);
try (TupleQueryResult result = tupleQuery.evaluate()) {
if (result.hasNext()) {
BindingSet bindingSet = result.next();
psOut.println("solution " + bindingSet.toString());
}
}
// re-run with ?person = Bob
tupleQuery.setBinding("person", bob);
try (TupleQueryResult result = tupleQuery.evaluate()) {
if (result.hasNext()) {
BindingSet bindingSet = result.next();
psOut.println("solution " + bindingSet.toString());
}
}
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
sr.shutDown();
store.shutDown();
op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP BindVar.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP BindVar jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP BindVar jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1
java
コマンドの出力は、次のようになります。
solution [name="Alice";person=http://example.org/people/alice]
solution [name="Bob";person=http://example.org/people/bob]
8.11.11 例11: SPARQLの更新
SparqlUpdate.java
ファイルを示します。
例8-15 SPARQLの更新
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.query.Update;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
public class SparqlUpdate {
private static final String DATA_1 =
"[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y=\"Sue\"]" +
"[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]";
private static final String DATA_2 =
"[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y=\"Susan\"]" +
"[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]";
private static final String DATA_3 =
"[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y=\"Susan\"]" +
"[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]" +
"[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y=\"Susan\"]" +
"[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]";
private static final String DATA_4 =
"[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]" +
"[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y=\"Susan\"]" +
"[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]";
private static final String DATA_5 =
"[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y=\"Susan\"]" +
"[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]" +
"[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y=\"Susan\"]" +
"[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]";
private static String getRepositoryData(RepositoryConnection conn, PrintStream out)
{
String dataStr = "";
String queryString = "SELECT * WHERE { GRAPH ?g { ?x ?p ?y } } ORDER BY ?g ?x ?p ?y";
TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
try (TupleQueryResult result = tupleQuery.evaluate()) {
while (result.hasNext()) {
BindingSet bindingSet = result.next();
out.println(bindingSet.toString());
dataStr += bindingSet.toString();
}
}
return dataStr;
}
public static void main(String[] args) throws
ConnectionSetupException, SQLException
{
PrintStream out = new PrintStream(System.out);
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String networkOwner = (args.length > 5) ? args[4] : null;
String networkName = (args.length > 5) ? args[5] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
conn = sr.getConnection();
conn.clear(); // to start from scratch
// Insert some initial data
String updString = "PREFIX people: <http://example.org/people/>\n" +
"PREFIX ont: <http://example.org/ontology/>\n" +
"INSERT DATA { GRAPH <urn:g1> { \n" +
" people:Sue a ont:Person; \n" +
" ont:name \"Sue\" . } }";
Update upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
upd.execute();
conn.commit();
String repositoryData = getRepositoryData(conn, out);
if (! (DATA_1.equals(repositoryData)) ) out.println("DATA_1 mismatch");
// Change Sue's name to Susan
updString = "PREFIX people: <http://example.org/people/>\n" +
"PREFIX ont: <http://example.org/ontology/>\n" +
"DELETE { GRAPH ?g { ?s ont:name ?n } }\n" +
"INSERT { GRAPH ?g { ?s ont:name \"Susan\" } }\n" +
"WHERE { GRAPH ?g { ?s ont:name ?n FILTER (?n = \"Sue\") }}";
upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
upd.execute();
conn.commit();
repositoryData = getRepositoryData(conn, out);
if (! (DATA_2.equals(repositoryData)) ) out.println("DATA_2 mismatch");
// Copy to contents of g1 to a new graph g2
updString = "PREFIX people: <http://example.org/people/>\n" +
"PREFIX ont: <http://example.org/ontology/>\n" +
"COPY <urn:g1> TO <urn:g2>";
upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
upd.execute();
conn.commit();
repositoryData = getRepositoryData(conn, out);
if (! (DATA_3.equals(repositoryData)) ) out.println("DATA_3 mismatch");
// Delete ont:name triple from graph g1
updString = "PREFIX people: <http://example.org/people/>\n" +
"PREFIX ont: <http://example.org/ontology/>\n" +
"DELETE DATA { GRAPH <urn:g1> { people:Sue ont:name \"Susan\" } }";
upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
upd.execute();
conn.commit();
repositoryData = getRepositoryData(conn, out);
if (! (DATA_4.equals(repositoryData)) ) out.println("DATA_4 mismatch");
// Add contents of g2 to g1
updString = "PREFIX people: <http://example.org/people/>\n" +
"PREFIX ont: <http://example.org/ontology/>\n" +
"ADD <urn:g2> TO <urn:g1>";
upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
upd.execute();
conn.commit();
repositoryData = getRepositoryData(conn, out);
if (! (DATA_5.equals(repositoryData)) ) out.println("DATA_5 mismatch");
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
sr.shutDown();
store.shutDown();
op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP SparqlUpdate.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SparqlUpdate jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SparqlUpdate jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1
java
コマンドの出力は、次のようになります。
[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y="Sue"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g1;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g1;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
[p=http://example.org/ontology/name;g=urn:g2;x=http://example.org/people/Sue;y="Susan"]
[p=http://www.w3.org/1999/02/22-rdf-syntax-ns#type;g=urn:g2;x=http://example.org/people/Sue;y=http://example.org/ontology/Person]
8.11.12 例12: Oracleヒント
OracleHint.java
ファイルを示します。
例8-16 Oracleヒント
import java.sql.SQLException;
import oracle.rdf4j.adapter.OracleDB;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.query.Update;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
public class OracleHint {
public static void main(String[] args) throws ConnectionSetupException, SQLException {
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String networkOwner = (args.length > 5) ? args[4] : null;
String networkName = (args.length > 5) ? args[5] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
conn = sr.getConnection();
conn.clear(); // to start from scratch
// Insert some initial data
String updString =
"PREFIX ex: <http://example.org/>\n" +
"INSERT DATA { " +
" ex:a ex:p1 ex:b . " +
" ex:b ex:p1 ex:c . " +
" ex:c ex:p1 ex:d . " +
" ex:d ex:p1 ex:e . " +
" ex:e ex:p1 ex:f . " +
" ex:f ex:p1 ex:g . " +
" ex:g ex:p1 ex:h . " +
" ex:h ex:p1 ex:i . " +
" ex:i ex:p1 ex:j . " +
" ex:j ex:p1 ex:k . " +
"}";
Update upd = conn.prepareUpdate(QueryLanguage.SPARQL, updString);
upd.execute();
conn.commit();
// default behavior for property path is 10 hop max, so we get 11 results
String sparql =
"PREFIX ex: <http://example.org/>\n" +
"SELECT (COUNT(*) AS ?cnt)\n" +
"WHERE { ex:a ex:p1* ?y }";
TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, sparql);
try (TupleQueryResult result = tupleQuery.evaluate()) {
while (result.hasNext()) {
BindingSet bindingSet = result.next();
if (11 != Integer.parseInt(bindingSet.getValue("cnt").stringValue())) System.out.println("cnt mismatch: expecting 11");
}
}
// ORACLE_SEM_FS_NS prefix hint to use parallel(2) and dynamic_sampling(6)
// ORACLE_SEM_SM_NS prefix hint to use a 5 hop max and to use CONNECT BY instead of simple join
sparql =
"PREFIX ORACLE_SEM_FS_NS: <http://oracle.com/semtech#dop=2,ods=6>\n" +
"PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_max_pp_depth(5),all_disable_pp_sj>\n" +
"PREFIX ex: <http://example.org/>\n" +
"SELECT (COUNT(*) AS ?cnt)\n" +
"WHERE { ex:a ex:p1* ?y }";
tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, sparql, "http://example.org/");
try (TupleQueryResult result = tupleQuery.evaluate()) {
while (result.hasNext()) {
BindingSet bindingSet = result.next();
if (6 != Integer.parseInt(bindingSet.getValue("cnt").stringValue())) System.out.println("cnt mismatch: expecting 6");
}
}
// query options for SPARQL Update
sparql =
"PREFIX ORACLE_SEM_UM_NS: <http://oracle.com/semtech#parallel(2)>\n" +
"PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#all_max_pp_depth(5),all_disable_pp_sj>\n" +
"PREFIX ex: <http://example.org/>\n" +
"INSERT { GRAPH ex:g1 { ex:a ex:reachable ?y } }\n" +
"WHERE { ex:a ex:p1* ?y }";
Update u = conn.prepareUpdate(sparql);
u.execute();
// graph ex:g1 should have 6 results because of all_max_pp_depth(5)
sparql =
"PREFIX ex: <http://example.org/>\n" +
"SELECT (COUNT(*) AS ?cnt)\n" +
"WHERE { GRAPH ex:g1 { ?s ?p ?o } }";
tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, sparql, "http://example.org/");
try (TupleQueryResult result = tupleQuery.evaluate()) {
while (result.hasNext()) {
BindingSet bindingSet = result.next();
if (6 != Integer.parseInt(bindingSet.getValue("cnt").stringValue())) System.out.println("cnt mismatch: expecting 6");
}
}
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
sr.shutDown();
store.shutDown();
op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP OracleHint.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP OracleHint jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP OracleHint jdbc:oracle:thin:@localhost:1521:ORCL scott <password> TestModel scott net1
8.11.13 例13: JDBCバインド値の使用
JDBCBindVar.java
ファイルを示します。
例8-17 JDBCバインド値の使用
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OracleDB;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
public class JDBCBindVar {
public static void main(String[] args) throws ConnectionSetupException, SQLException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String networkOwner = (args.length > 5) ? args[4] : null;
String networkName = (args.length > 5) ? args[5] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
store = (networkName == null) ? new OracleSailStore(op, model) : new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
conn = sr.getConnection();
ValueFactory f = conn.getValueFactory();
conn.begin();
conn.clear();
// create some resources and literals to make statements out of
// Alice
IRI alice = f.createIRI("http://example.org/people/alice");
IRI name = f.createIRI("http://example.org/ontology/name");
IRI person = f.createIRI("http://example.org/ontology/Person");
Literal alicesName = f.createLiteral("Alice");
conn.add(alice, RDF.TYPE, person);
conn.add(alice, name, alicesName);
//Bob
IRI bob = f.createIRI("http://example.org/people/bob");
Literal bobsName = f.createLiteral("Bob");
conn.add(bob, RDF.TYPE, person);
conn.add(bob, name, bobsName);
conn.commit();
// Query using USE_BIND_VAR=JDBC option for JDBC bind values
// Simple BIND clause for ?person marks ?person as a bind variable
String queryString =
" PREFIX ORACLE_SEM_SM_NS: <http://oracle.com/semtech#USE_BIND_VAR=JDBC>\n" +
" PREFIX ex: <http://example.org/ontology/>\n" +
" Select ?name \n" +
" WHERE \n" +
" { SELECT * WHERE { \n" +
" BIND (\"\" AS ?person) \n" +
" ?person ex:name ?name } \n" +
" }\n" +
" ORDER BY ?name";
TupleQuery tupleQuery = conn.prepareTupleQuery(
QueryLanguage.SPARQL, queryString);
// set binding for ?person = Alice
tupleQuery.setBinding("person", alice);
try (TupleQueryResult result = tupleQuery.evaluate()) {
if (result.hasNext()) {
BindingSet bindingSet = result.next();
psOut.println("solution " + bindingSet.toString());
}
}
// re-run with ?person = Bob
tupleQuery.setBinding("person", bob);
try (TupleQueryResult result = tupleQuery.evaluate()) {
if (result.hasNext()) {
BindingSet bindingSet = result.next();
psOut.println("solution " + bindingSet.toString());
}
}
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
if (op != null) {
OracleDB oracleDB = op.getOracleDB();
if (networkName == null)
OracleUtils.dropSemanticModelAndTables(oracleDB, model);
else
OracleUtils.dropSemanticModelAndTables(oracleDB, model, null, null, networkOwner, networkName);
op.returnOracleDBtoPool(oracleDB);
}
sr.shutDown();
store.shutDown();
op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP JDBCBindVar.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP JDBCBindVar jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP JDBCBindVar jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel scott net1
Javaコマンドの出力は、次のようになります。
solution [name="Alice";person=http://example.org/people/alice]
solution [name="Bob";person=http://example.org/people/bob]
8.11.14 例14: 単純な推論
SimpleInference.java
ファイルを示します。このファイルは、OWL2RLルール・ベースを使用する単一のRDFグラフ(モデル)の推論を示します。
例8-18 単純な推論
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import oracle.rdf4j.adapter.Attachment;
import oracle.rdf4j.adapter.OracleSailConnection;
import oracle.rdf4j.adapter.OracleSailRepositoryConnection;
public class SimpleInference {
public static void main(String[] args) throws ConnectionSetupException, SQLException, IOException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String networkOwner = (args.length > 5) ? args[4] : null;
String networkName = (args.length > 5) ? args[5] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
// create a single-model, single-rulebase OracleSailStore object
Attachment attachment = Attachment.createInstance(Attachment.NO_ADDITIONAL_MODELS, new String[] {"OWL2RL"});
store = new OracleSailStore(op, model, attachment, networkOwner, networkName);
sr = new OracleRepository(store);
ValueFactory f = sr.getValueFactory();
conn = sr.getConnection();
// create some resources and literals to make statements out of
IRI alice = f.createIRI("http://example.org/people/alice");
IRI bob = f.createIRI("http://example.org/people/bob");
IRI friendOf = f.createIRI("http://example.org/ontology/friendOf");
IRI Person = f.createIRI("http://example.org/ontology/Person");
IRI Woman = f.createIRI("http://example.org/ontology/Woman");
IRI Man = f.createIRI("http://example.org/ontology/Man");
conn.clear(); // to start from scratch
// add some statements to the RDF graph (model)
conn.add(alice, RDF.TYPE, Woman);
conn.add(bob, RDF.TYPE, Man);
conn.add(alice, friendOf, bob);
conn.commit();
OracleSailConnection osc = (OracleSailConnection)((OracleSailRepositoryConnection)conn).getSailConnection();
// perform inference (this will not generate any inferred triples)
osc.performInference();
// prepare a query to run against the repository
String queryString =
"PREFIX ex: <http://example.org/ontology/>\n" +
"SELECT * WHERE {?x ex:friendOf ?y . ?x a ex:Person . ?y a ex:Person}\n" ;
TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
// run the query: no results will be returned because nobody is a Person
try (TupleQueryResult result = tupleQuery.evaluate()) {
int resultCount = 0;
while (result.hasNext()) {
resultCount++;
BindingSet bindingSet = result.next();
psOut.println("value of x: " + bindingSet.getValue("x"));
psOut.println("value of y: " + bindingSet.getValue("y"));
}
psOut.println("number of results: " + resultCount);
}
// add class hierarchy
conn.add(Man, RDFS.SUBCLASSOF, Person);
conn.add(Woman, RDFS.SUBCLASSOF, Person);
conn.commit();
// perform inference again
osc.performInference();
// run the same query again: returns some results because alice and bob now belong to superclass Person
try (TupleQueryResult result = tupleQuery.evaluate()) {
while (result.hasNext()) {
BindingSet bindingSet = result.next();
psOut.println("value of x: " + bindingSet.getValue("x"));
psOut.println("value of y: " + bindingSet.getValue("y"));
}
}
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
sr.shutDown();
store.shutDown();
op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP SimpleInference.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SimpleInference jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SimpleInference jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel scott net1
Javaコマンドの出力は、次のようになります。
number of results: 0
value of x: http://example.org/people/alice
value of y: http://example.org/people/bob
8.11.15 例15: 単純な仮想モデル
SimpleVirtualModel.java
ファイルを示します。
例8-19 単純な仮想モデル
import java.io.IOException;
import java.io.PrintStream;
import java.sql.SQLException;
import oracle.rdf4j.adapter.OraclePool;
import oracle.rdf4j.adapter.OracleRepository;
import oracle.rdf4j.adapter.OracleSailStore;
import oracle.rdf4j.adapter.exception.ConnectionSetupException;
import oracle.rdf4j.adapter.utils.OracleUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import oracle.rdf4j.adapter.Attachment;
public class SimpleVirtualModel {
public static void main(String[] args) throws ConnectionSetupException, SQLException, IOException {
PrintStream psOut = System.out;
String jdbcUrl = args[0];
String user = args[1];
String password = args[2];
String model = args[3];
String model2 = args[4];
String virtualModelName = args[5];
String networkOwner = (args.length > 7) ? args[6] : null;
String networkName = (args.length > 7) ? args[7] : null;
OraclePool op = null;
OracleSailStore store = null;
Repository sr = null;
RepositoryConnection conn = null;
OracleSailStore store2 = null;
Repository sr2 = null;
RepositoryConnection conn2 = null;
OracleSailStore vmStore = null;
Repository vmSr = null;
RepositoryConnection vmConn = null;
try {
op = new OraclePool(jdbcUrl, user, password);
// create two models and then a virtual model that uses those two models
// create the first model
store = new OracleSailStore(op, model, networkOwner, networkName);
sr = new OracleRepository(store);
ValueFactory f = sr.getValueFactory();
conn = sr.getConnection();
// create the second model (this one will be used as an additional model in the attachment object)
store2 = new OracleSailStore(op, model2, networkOwner, networkName);
sr2 = new OracleRepository(store2);
conn2 = sr2.getConnection();
// create a two-model virtual model OracleSailStore object
Attachment attachment = Attachment.createInstance(model2);
vmStore = new OracleSailStore(op, model, /*ignored*/true, /*useVirtualModel*/true, virtualModelName, attachment, networkOwner, networkName);
vmSr = new OracleRepository(vmStore);
vmConn = vmSr.getConnection();
// create some resources and literals to make statements out of
IRI alice = f.createIRI("http://example.org/people/alice");
IRI bob = f.createIRI("http://example.org/people/bob");
IRI friendOf = f.createIRI("http://example.org/ontology/friendOf");
IRI Person = f.createIRI("http://example.org/ontology/Person");
IRI Woman = f.createIRI("http://example.org/ontology/Woman");
IRI Man = f.createIRI("http://example.org/ontology/Man");
// clear any data (in case any of the two non-virtual models were already present)
conn.clear();
conn2.clear();
// add some statements to the first RDF model
conn.add(alice, RDF.TYPE, Woman);
conn.add(bob, RDF.TYPE, Man);
conn.add(alice, friendOf, bob);
conn.commit();
// prepare a query to run against the virtual model repository
String queryString =
"PREFIX ex: <http://example.org/ontology/>\n" +
"SELECT * WHERE {" +
"?x ex:friendOf ?y . ?x rdf:type/rdfs:subClassOf* ?xC . ?y rdf:type/rdfs:subClassOf* ?yC" +
"} ORDER BY ?x ?xC ?y ?yC\n" ;
;
TupleQuery tupleQuery = vmConn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
// run the query: no results will be returned because nobody is a Person
try (TupleQueryResult result = tupleQuery.evaluate()) {
int resultCount = 0;
while (result.hasNext()) {
resultCount++;
BindingSet bindingSet = result.next();
psOut.println("values of x | xC | y | yC: " +
bindingSet.getValue("x") + " | " + bindingSet.getValue("xC") + " | " +
bindingSet.getValue("y") + " | " + bindingSet.getValue("yC"));
}
psOut.println("number of results: " + resultCount);
}
// add class hierarchy info to the second model
conn2.add(Man, RDFS.SUBCLASSOF, Person);
conn2.add(Woman, RDFS.SUBCLASSOF, Person);
conn2.commit();
// run the same query again: returns some additional info in the results
try (TupleQueryResult result = tupleQuery.evaluate()) {
int resultCount = 0;
while (result.hasNext()) {
resultCount++;
BindingSet bindingSet = result.next();
psOut.println("values of x | xC | y | yC: " +
bindingSet.getValue("x") + " | " + bindingSet.getValue("xC") + " | " +
bindingSet.getValue("y") + " | " + bindingSet.getValue("yC"));
}
psOut.println("number of results: " + resultCount);
}
}
finally {
if (conn != null && conn.isOpen()) {
conn.clear();
conn.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model, null, null, networkOwner, networkName);
sr.shutDown();
store.shutDown();
if (conn2 != null && conn2.isOpen()) {
conn2.clear();
conn2.close();
}
OracleUtils.dropSemanticModelAndTables(op.getOracleDB(), model2, null, null, networkOwner, networkName);
sr2.shutDown();
store2.shutDown();
vmSr.shutDown();
vmStore.shutDown();
op.close();
}
}
}
この例をコンパイルするには、次のコマンドを実行します。
javac -classpath $CP SimpleVirtualModel.java
既存のMDSYSネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SimpleVirtualModel jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel TestOntology TestVM
所有者がSCOTTで名前がNET1である既存のスキーマプライベート・ネットワークに対してこの例を実行するには、次のコマンドを実行します。
java -classpath $CP SimpleVirtualModel jdbc:oracle:thin:@localhost:1521:ORCL scott <password-for-scott> TestModel TestOntology TestVM scott net1
Javaコマンドの出力は、次のようになります。
values of x | xC | y | yC: http://example.org/people/alice | http://example.org/ontology/Woman | http://example.org/people/bob | http://example.org/ontology/Man
number of results: 1
values of x | xC | y | yC: http://example.org/people/alice | http://example.org/ontology/Person | http://example.org/people/bob | http://example.org/ontology/Man
values of x | xC | y | yC: http://example.org/people/alice | http://example.org/ontology/Person | http://example.org/people/bob | http://example.org/ontology/Person
values of x | xC | y | yC: http://example.org/people/alice | http://example.org/ontology/Woman | http://example.org/people/bob | http://example.org/ontology/Man
values of x | xC | y | yC: http://example.org/people/alice | http://example.org/ontology/Woman | http://example.org/people/bob | http://example.org/ontology/Person
number of results: 4