程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Jenabean:將JavaBeans輕松綁定到RDF

Jenabean:將JavaBeans輕松綁定到RDF

編輯:關於JAVA

Java 開發人員是幸運的,因為在 Jena 中他們可以利用一種良好的 RDF 框架。Jena 提供了一個編寫和讀取 RDF 的 API,它可以以多種方式進行保存和持久化。

Jena 的設計目標是可以良好地處理 RDF 數據模型,正如 JDBC 適合處理關系模型一樣。數據庫應用程序中編寫的大量代碼都用來保存 Java 對象,還有一些代碼用來從數據庫中聚集對象。用 Java 代碼編寫的語義 Web 應用程序面臨一個類似的問題:它們必須實現 Java 對象和 RDF 之間的相互轉換。因此,開發人員必須編寫大量的代碼來消除自身模型(一般為 JavaBeans)和 Jena 的以 RDF 為中心的 API 之間的差異。

本文展示 Jenabean 的 Java-to-RDF 綁定框架如何簡化上述過程並減少所需的代碼量。您將審視一些 Jena 客戶端代碼並將其與 Jenabean 的基於 JavaBean 的編程模型對比。首先查看一個簡單的例子,我將向您展示如何實現以下操作:

將一個 bean 保存為 RDF

將其屬性與特定的 RDF 屬性綁定

將其與其他對象關聯

再次回讀 bean

Jenabean 編程模型

考慮清單 1 中的簡單 RDF 示例,為方便閱讀,它使用了 N-triple(N3)格式:

清單 1. RDF 示例(N3 格式)

<http://www.ibm.com/developerworks/xml/library/j-jena/>
   a    dc:Article ;
   dc:creator "Philip McCarthy"^^xsd:string ;
   dc:subject "jena, rdf, java, semantic web"^^xsd:string ;
   dc:title "Introduction to Jena"^^xsd:string .

清單 1 說明了 “Jena 簡介” 這篇文章由 Philip McCarthy 撰寫並且主題包括 jena、rdf、java 和語義 web。詞匯表是 Dublin Core 元數據分類的一部分。要使用 Jena 的原始的 Java API 復制這些 RDF 聲明,您可能要執行類似清單 2 的工作:

清單 2. 使用原始的 Jena API 斷言 RDF 示例

String NS = "http://purl.org/dc/elements/1.1/";
OntModel m = createModel();
OntClass articleCls = m.createClass(NS +"Article");
Individual i = articleCls.createIndividual(
  "http://www.ibm.com/developerworks/xml/library/j-jena/");
Property title = m.getProperty(NS + "title");
Literal l = m.createTypedLiteral("Introduction to Jena");
i.setPropertyValue(title,l);
Property creator = m.getProperty(NS + "creator");
l = m.createTypedLiteral("Philip McCarthy");
i.setPropertyValue(creator,l);
Property subject = m.getProperty(NS + "subject");
l = m.createTypedLiteral("jena, rdf, java, semantic web");
i.setPropertyValue(subject,l);
m.write(System.out, "N3");

清單 2 中每個數值斷言需要三行代碼:

訪問屬性

創建典型的字母

斷言屬性關系

這個代碼的優點是使用透明、清晰的方式直接映射到 RDF 概念。這種情況與 JDBC 客戶端代碼相似,其中 API 直接應用到關系模型。

如果花大量時間研究 Jena,您將會認識到普通的面向對象代碼和與 Jena API 交互的客戶端代碼之間存在差異。您將在 Java 對象設計的方法中進行斷言,而不是使用 setPropertyValue 方法設置屬性。

清單 3 展示了使用 Jenabean 創建相同的斷言:

清單 3. 使用 Jenabean 創建相同的斷言

Model m = _
Bean2RDF writer = new Bean2RDF(m);
Article article = new Article("http://www.ibm.com/developerworks/xml/library/j-jena/");
article.setCreator("Philip McCarthy");
article.setTitle("Introduction to Jena");
article.setSubject("jena, rdf, java, semantic web");
writer.save(article);
m.write(System.out, "N3");

我在這裡另外包含了 m.write(...,"N3") 行。您可以使用本文附帶的代碼(請參閱 下載)親自嘗試。

清單 2 和 清單 3 有明顯的不同,但 Jena 模型產生了幾乎相同的變化。它們都創建了 清單 1 中三元組的一個超集。清單 2 通過調用 m.createClass(...) 聲明了一篇新的文章。清單 3 通過創建 Article — new Article(...) 類的一個新實例實現同樣的操作。沒有使用 Jenabean,每個屬性斷言要求您從模型訪問屬性、創建一個字母並通過調用 setPropertyValue(...) 將聲明斷言到模型。使用 Jenabean 的 Bean2RDF 轉換器,您可以僅調用 JavaBean 的 setter 方法。清單 3 產生了對大多數 Java 開發人員來說非常熟悉的代碼。

OOP 到 RDF 的綁定

如您所見,Jenabean 的主要優勢是填補了 Java 對象和 RDF 之間的差異。這允許您使用與域模型相同的 bean 以熟悉的 OOP 風格編寫語義 Web 應用程序。但這並不是說 Java 對象和 RDF 完全相同。Java 對象和 RDF 以不同的方式表示數據。一個好的綁定工具必須解決以下三個問題。

對象到 RDF 的阻抗不匹配

通常開發人員只關心將一個本體(ontology)復制為一組 Java 對象。Java 對象和 OWL 類之間不存在一對一的關聯。OWL 允許多重繼承,允許許多類分享相同的屬性並允許屬性之間相互繼承。另外,像關系數據庫管理系統(RDBMS)一樣,對象和 RDF 在一些方面相似而在其他方面不同。這使我們需要在 Java 代碼中生成並使用 RDF。許多工具采用代碼生成方法,這些方法涉及讀取 RDF 模式或 OWL 本體並在 Java 語言中復制類和屬性。這類工具不能實現從現有的 JavaBean 類中斷言普通的 RDF 屬性。RDF 綁定工具能讓您將一個 JavaBean 屬性與一個 RDF 屬性 URI 隨意關聯(假設它們的類型兼容)。

淺(shallow)對深(deep)

任何綁定工具都需要解決的另一個問題是一個對象圖(object graph)能夠實現多大程度的持久化。將對象保存在一個密集的、具有大量連接的對象圖中將導致持久化整個模型。裝載也會出現類似的情形。綁定工具必須阻止將完整的 RDF 模型作為 JavaBeans 裝載到內存中,但在必要時允許實現這個特性。

循環

循環關系對於 RDF 和對象模型非常常見。在進行持久化和裝載時,綁定工具必須能夠檢測和處理循環。顯然,它應該防止無限循環,而且它應該檢測以前裝載的對象並通過重用這些對象來節省時間。

Jenabean 解決了這三個問題,同時盡量使該過程保持簡單。它不需要代碼生成階段、字節碼生成步驟,或者實時的字節碼處理庫。它僅需要 Jena 和它的庫。Jenabean 默認使用一種保守策略來保存對象及其直接屬性。開發人員必須表明他們希望實現 “深度” 拷貝,以便完整地保存對象及相關內容。或者使用另一種方法,即指定要保存或裝載某個實例的特定集合屬性。

為 RDF 創建 JavaBeans

如果您熟悉 Hibernate 或其他綁定工具,您也許希望知道在哪裡發生這些操作。Jenabean 使用 Java 注釋來聲明 bean 如何映射到 RDF。正如其他基於注釋的綁定層一樣,當您的模型由 Java 對象驅動時,Jenabean 最為有用。當然並不會總出現這種情況,但是如果是這樣的話,Jenabean 就可以提供幫助。

最簡單的工作示例

Jenabean 提供了許多功能來定制 bean 如何序列化為 RDF,但是如果默認設置符合您的要求,那麼就可以開始快速編寫和讀取 bean。讓我們創建一個簡單的 JavaBean 示例,使它滿足所有必需的要求。正如使用 Java Persistence API (JPA) 或 Hibernate 一樣,您需要保證對象有惟一的 ID。Jenabean 需要您將一個單獨的注釋 — @Id — 添加到至少一個 bean 字段,使用它充當惟一標識符。清單 4 展示了這個簡單的 bean:

清單 4. 一個簡單的可直接保存的 bean

package example;
import thewebsemantic.Id;
public class Person {
  private String email;
    @Id
    public String getEmail() { return email;}
    public void setEmail(String email) { this.email = email;}
}

清單 4 為 Jenabean 提供足夠的信息來可靠地保存和裝載 Person 類實例。您沒有必要擴展任何內容或編寫 XML 描述符文件。由於電子郵件地址是惟一的,它是有效的 ID。清單 5 展示如何將 Person 實例保存到 Jena 模型:

清單 5. 使用生成的 RDF 保存 Person 類的實例

Model m = ModelFactory.createOntologyModel();
Bean2RDF writer = new Bean2RDF(m);
Person p = new Person();
p.setEmail("[email protected]");
writer.save(p);
m.write(System.out, "N3");
...
<http://example/Person>
   a    owl:Class ;
<http://thewebsemantic.com/javaclass>
   "example.Person" .
<http://example/Person/[email protected]>
   a    <http://example/Person> ;
<http://example/email>
   "[email protected]"^^xsd:string .

Bean2RDF 是一個將對象作為 RDF 編寫的 Jenabean 類。它默認情況下是淺(shallow)模式,這意味著它將保存實例和其單一屬性。如果 Person 類還沒有添加到模型中,它將斷言一個新類作為 owl:Class 的實例。注意在清單 5 中 Jenabean 使用example 包作為一個新的本體類的名稱空間。第二個斷言是一個注釋,指明用於創建個體的 Java 類。Person 實例及電子郵件地址都進行了斷言。Jenabean 首先為已保存的實例創建 URI。它還處理電子郵件屬性並將其斷言為一個 string 字母值。

從 Jena 模型中檢索 JavaBeans

用 RDF 表示的個體需要一個 URI,然而 Java 開發人員傾向於使用惟一的 ID。Jenabean 通過將聲明的 ID 字段附加到名稱空間(這種情況下默認來自包和類名)來提供幫助。創建好 URI 後,您可以使用 RDF2Bean 從模型中裝載信息:RDF2Bean reader = new RDF2Bean(m);
Person p2 = reader.load(
   Person.class,"[email protected]");

Jenabean 也可以裝載所有的 Person 實例:

Collection<Person> people = reader.load(Person.class);

這些是在模型中訪問 bean 的最簡單方法。Jenabean 還支持到 SPARQL(RDF 的 SPARQL 查詢語言)結果的綁定。簡言之,Jenabean 至少要求 bean 作者指明哪個字段保存的值對於該類型的所有實例是惟一的。保存了 bean 後,將根據類的包和名稱為 bean 的類和屬性提供默認的 URI。這允許您開始從 Java 層輕松地快速創建 RDF。

指定名稱空間和屬性

到目前為止,我已經向您展示了 Jenabean 如何根據 bean 的類路徑和名稱創建默認的 URI。Jenabean 還支持聲明您希望使用的名稱空間。您可以使用 @Namespace 注釋將 bean 映射到特定的名稱空間。作為演示,我將使用一個目前未被使用的名稱空間,Jenabean 自己的項目 URL:

@Namespace("http://jenabean.googlecode.com/")
public class Person { _
<http://jenabean.googlecode.com/Person/[email protected]>
  a    <http://jenabean.googlecode.com/Person> ;

注意,這裡為 Person 類及其屬性(而不是默認包)提供了新的名稱空間,該名稱空間與作為 @Namespace 注釋的參數提供的名稱空間匹配。默認情況下,這個名稱空間將會用於類及其屬性。

在 RDF 的世界中,可以使用常見的屬性;否則,無法開發出語義 Web。通過使用常見的屬性,您可以使數據具有更多的語義並使其他人更加熟悉數據。如果一個 spider(Web 爬行變體)遇到我從 Jenabean 項目 URL 名稱空間中生成的 RDF 片段,則無法利用這個片段。但您可以使用更常見和熟知的斷言對 bean 進行簡單地修改。FOAF(Friend of a Friend,FOAF)語言是一種用於鏈接各類人員的常見詞匯表,它為電子郵件地址提供了一個特殊的屬性:foaf:mbox。現在您所需做的全部工作是使用 Person bean 中的 @RdfProperty 注釋:

@Id
@RdfProperty("http://xmlns.com/foaf/0.1/mbox")
public String getEmail() { return email;}
<http://xmlns.com/foaf/0.1/mbox>
  "[email protected]"^^xsd:string .

現在,email 屬性將其自身斷言為一個 foaf:mbox,它將被其他對您的數據感興趣的 RDF 代理理解為一個電子郵件地址。

對象關系

在 OWL 和 RDF 世界中,通過對同一屬性的多個斷言來表達各種基數的關系。Jenabean 通過使用 java.util.Collection 接口極大簡化了這一過程。清單 6 擴展 Person 類來支持朋友關系(使用松散的 foaf:knows 方式):

清單 6. 擴展 Person 以支持朋友關系

public Collection<Person> friends = new
  LinkedList<Person>();
@RdfProperty("http://xmlns.com/foaf/0.1/knows")
public Collection<Person> getFriends() { return friends;}
public void setFriends(Collection<Person> friends) { this.friends = friends;}

這沒有什麼值得驚奇的 — 只是使用類型為 Collection<Person> 的新字段 friends,以及相關的 get 和 set 方法。現在您可以創建一個 Person 和多個 friends,並通過將每個朋友添加到 friends 集合來實現關聯。@RdfProperty 注釋是可選的,但是如果您希望將其綁定到現有的第三方詞匯表,那麼它非常重要。注釋指定您希望在 Jena 模型中將 “friend” 屬性綁定到 foaf:knows RDF 屬性。清單 7 顯示如何使用傳統的 JavaBean 技巧創建朋友關系:

清單 7. 使用生成的 RDF 表示朋友關系

Model m = ModelFactory.createOntologyModel();
Bean2RDF writer = new Bean2RDF(m);
Person p = new Person();
p.setEmail("[email protected]");
Person f1 = new Person();
f1.setEmail("[email protected]");
Person f2 = new Person();
f2.setEmail("[email protected]");
p.getFriends().add(f1);
p.getFriends().add(f2);
writer.save(p); // modifies the Jena model
m.write(System.out, "N3");
...
foaf:knows
  jb:[email protected], jb@[email protected] .

通過 Bean2RDF.write(...) 保存了簡單的 Person bean 後,模型中包含遵守 FOAF 規范的新數據。

檢索有序列表

在 RDF 中,沒有定義子節點的順序,所以不能假設 Jena 會以任何特定的順序檢索朋友列表。如果需要使用有序列表,Jenabean 將把 Java 數組映射到 RDF 序列。作為演示,我將為 Person 類提供一組電話號碼,表示為一個 String 數組,如清單 8 所示:

清單 8. 包含生成的 RDF 的示例數組屬性

private String[] phoneNumbers;
public String[] getPhoneNumbers() { return phoneNumbers;}
public void setPhoneNumbers(String[] phoneNumbers) {
   this.phoneNumbers = phoneNumbers;}
jb:phoneNumbers
   [ a    rdf:Seq ;
   rdf:_1 "321-321-3210"^^xsd:string ;
   rdf:_2 "321-321-3211"^^xsd:string
   ] ;

結束語

Jenabean 幫助您開始使用熟悉的 Jenabean 模型讀取和編寫 RDF。本文闡述了以下基本原理:如何創建、保存並讀取簡單的 bean。這只是使用 Java 語言編寫語義 Web 應用程序過程中的一小部分。訪問 Jenabean 項目的主頁了解更多相關知識、提供反饋或者尋求幫助。

來源:

http://www.ibm.com/developerworks/cn/java/j-jenabean.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved