Apache TinkerPop 是圖計算框架的標準,其核心介面 Blueprints** 為屬性圖模型提供了類似 JDBC 的統一存取層。本文示範如何在 Java 專案中整合 TinkerPop Blueprints,搭配 JPA 實現將圖資料(頂點、邊、屬性)持久化至 Apache Derby 嵌入式資料庫,並完成基本 CRUD 操作。
Blueprints** 定義了圖資料庫的標準介面:Graph、Vertex、Edge、Property。不同圖資料庫(Neo4j、Titan、OrientDB 等)提供各自實現。Blueprints JPA Graph** 是第三方實現,將圖結構映射到關聯式資料庫表,透過 Hibernate/JPA 進行 ORM 持久化,適合已有 RDBMS 基礎設施、運維成本敏感的場景。

4.0.0 tinkerpop-demo tinkerpop-demo 1.0 wingnest-repo wingnest repo https://www.wingnest.com/mvn-repo/ org.apache.tinkerpop gremlin-core 3.0.0.M9-incubating org.apache.tinkerpop gremlin-driver 3.0.0.M9-incubating com.tinkerpop.blueprints blueprints-core 2.6.0 com.wingnest.blueprints blueprints-jpa-graph 2.5.0_01 org.hibernate hibernate-core 4.3.10.Final org.hibernate hibernate-entitymanager 4.3.10.Final org.apache.derby derby 10.11.1.1 org.apache.derby derbytools 10.11.1.1 test org.slf4j slf4j-log4j12 1.7.5 test org.slf4j slf4j-simple 1.6.1 test junit junit 4.12 src/main/java src/main/resources true org.apache.maven.plugins maven-compiler-plugin 2.5.1 1.7 1.7 UTF-8 org.apache.maven.plugins maven-resources-plugin 2.4
package com.tinkerpop.demo;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.tg.TinkerGraph;
import com.wingnest.blueprints.impls.jpa.JpaGraph;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class TinkerPopDemo {
private JpaGraph jpaGraph = null;
@Before
public void setUp() {
// 初始化 JPA Graph,自動建表 (Hibernate hbm2ddl.auto=update)
Map props = new HashMap<>();
props.put("javax.persistence.jdbc.url", "jdbc:derby:db/HibernateUnit_test_perf;create=true");
// 如需 MySQL:props.put("javax.persistence.jdbc.url", "jdbc:mysql://localhost:3306/graphdb?createDatabaseIfNotExist=true");
jpaGraph = new JpaGraph("HibernateUnit", props);
}
@After
public void tearDown() throws Exception {
jpaGraph.shutdown();
}
@Test
public void testCreate() {
// 建立三個頂點
Vertex zhangsan = jpaGraph.addVertex(null);
zhangsan.setProperty("name", "zhangsan");
System.out.println("zhangsan: " + zhangsan.getId());
Vertex lisi = jpaGraph.addVertex(null);
lisi.setProperty("name", "lisi");
System.out.println("lisi: " + lisi.getId());
Vertex wangwu = jpaGraph.addVertex(null);
wangwu.setProperty("name", "wangwu");
System.out.println("wangwu: " + wangwu.getId());
// 建立邊:朋友關係
Edge friend1 = jpaGraph.addEdge(null, zhangsan, lisi, "friend");
Edge friend2 = jpaGraph.addEdge(null, wangwu, lisi, "friend");
System.out.println("create finish");
}
@Test
public void testQuery() {
queryAll();
queryZhansanFriends();
System.out.println("query finish");
}
private void queryAll() {
Iterable allVertex = jpaGraph.getVertices();
System.out.println("###################### query all ######################");
for (Vertex vertex : allVertex) {
System.out.println("name: " + vertex.getProperty("name") + ", id: " + vertex.getId());
}
}
private void queryZhansanFriends() {
Vertex zhangsan = jpaGraph.getVertex(1); // 假設 ID=1
System.out.println("###################### query zhangsan friends ######################");
Iterable friends = zhangsan.getVertices(Direction.OUT, "friend");
for (Vertex vertex : friends) {
System.out.println("name: " + vertex.getProperty("name") + ", id: " + vertex.getId());
}
}
@Test
public void testDelete() {
Vertex lisi = jpaGraph.getVertex(2); // 假設 ID=2
jpaGraph.removeVertex(lisi);
// 刪除後驗證
queryAll();
queryZhansanFriends();
}
}
執行測試後,Hibernate 自動建立以下表結構(Derby):
ENTITY:儲存頂點與邊的基礎資訊INDEX_BASE、INDEX、KEY_INDEX:支援屬性索引PROPERTY:儲存動態屬性 Key-Valuezhangsan:1 lisi:2 wangwu:3 create finish ###################### query all ###################### name: zhangsan, id: 1 name: lisi, id: 2 name: wangwu, id: 3 ###################### query zhangsan friends ###################### name: lisi, id: 2 query finish
只需修改 JDBC URL 與 Dialect,其餘程式碼完全不變:
props.put("javax.persistence.jdbc.url", "jdbc:mysql://localhost:3306/graphdb?createDatabaseIfNotExist=true");
props.put("javax.persistence.jdbc.driver", "com.mysql.jdbc.Driver");
props.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
pom.xml + 一個 Java 類,即可將圖資料落地關聯式資料庫。TitanGraph 或 Neo4jGraph,業務程式碼僅需更換 Graph 實現類。本範例展示了 Blueprints 介面的威力:一次開發,多引擎部署,是圖應用架構演進的理想起點。