入門
我們為 SDN 提供了一個 Spring Boot starter。請透過您的依賴管理引入 starter 模組,並配置要使用的 bolt URL,例如 spring.neo4j.uri=bolt://:7687
。該 starter 假定伺服器已停用身份驗證。由於 SDN starter 依賴於 Java Driver 的 starter,因此那裡提到的所有配置事項也適用於此處。有關可用屬性的參考,請使用您 IDE 在 spring.neo4j
名稱空間下的自動完成功能。
SDN 支援
-
眾所周知且易於理解的指令式程式設計模型(與 Spring Data JDBC 或 JPA 非常相似)
-
基於 Reactive Streams 的響應式程式設計,包括對響應式事務的完全支援。
所有這些都包含在同一個二進位制檔案中。響應式程式設計模型需要資料庫端使用 4+ 版本的 Neo4j 伺服器,另一端使用響應式 Spring。
準備資料庫
對於此示例,我們使用 電影圖,因為每個 Neo4j 例項都免費附帶此圖。
如果您沒有執行中的資料庫,但安裝了 Docker,請執行
docker run --publish=7474:7474 --publish=7687:7687 -e 'NEO4J_AUTH=neo4j/secret' neo4j:5
您現在可以訪問 https://:7474。上述命令將伺服器密碼設定為 secret
。請注意提示符中已準備好執行的命令 (:play movies
)。執行該命令以用一些測試資料填充您的資料庫。
建立一個新的 Spring Boot 專案
設定 Spring Boot 專案最簡單的方法是使用 start.spring.io(此網站也整合在主要的 IDE 中,如果您不想使用網站的話)。
選擇 "Spring Web Starter" 以獲取建立基於 Spring 的 Web 應用程式所需的所有依賴。Spring Initializr 將為您建立一個有效的專案結構,其中包含所選構建工具的所有檔案和設定。
使用 Maven
您可以對 Spring Initializer 發起 curl 請求來建立一個基本的 Maven 專案
curl https://start.spring.io/starter.tgz \
-d dependencies=webflux,data-neo4j \
-d bootVersion=3.2.0 \
-d baseDir=Neo4jSpringBootExample \
-d name=Neo4j%20SpringBoot%20Example | tar -xzvf -
這將建立一個新資料夾 Neo4jSpringBootExample
。由於此 starter 尚未新增到 initializer 中,您必須手動將以下依賴新增到您的 pom.xml
中
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
如果專案已存在,您也可以手動新增此依賴。
使用 Gradle
思路相同,只需生成一個 Gradle 專案即可
curl https://start.spring.io/starter.tgz \
-d dependencies=webflux,data-neo4j \
-d type=gradle-project \
-d bootVersion=3.2.0 \
-d baseDir=Neo4jSpringBootExampleGradle \
-d name=Neo4j%20SpringBoot%20Example | tar -xzvf -
Gradle 的依賴如下所示,必須新增到 build.gradle
中
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-neo4j'
}
如果專案已存在,您也可以手動新增此依賴。
配置專案
現在在您喜歡的 IDE 中開啟這些專案。找到 application.properties
並配置您的 Neo4j 憑據
spring.neo4j.uri=bolt://:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=verysecret
這是連線到 Neo4j 例項所需的最低配置。
使用此 starter 時,無需新增任何驅動程式的程式化配置。SDN repository 將透過此 starter 自動啟用。 |
配置 Neo4j Cypher-DSL
根據您執行應用程式所使用的 Neo4j 版本,建議配置 Neo4j Cypher-DSL 執行的方言。預設使用的方言是針對 Neo4j 的 LTS 版本 4.4。可以透過定義一個 Cypher-DSL Configuration
bean 來更改此設定。
@Bean
Configuration cypherDslConfiguration() {
return Configuration.newConfig()
.withDialect(Dialect.NEO4J_5).build();
}
儘管 Spring Data Neo4j 會盡力相容 Neo4j 5 和預設方言的組合,但始終建議明確定義方言。例如,這將導致更最佳化的查詢,併為較新的 Neo4j 版本利用 elementId() 。 |
在模組路徑上執行
Spring Data Neo4j 可以在模組路徑上執行。它的自動模組名稱是 spring.data.neo4j
。由於當前 Spring Data 構建設定的限制,它本身不提供模組。因此,它使用一個自動但穩定的模組名稱。然而,它確實依賴於一個模組化的庫(Cypher-DSL)。由於上述限制,我們無法在您的專案上表達對此庫的需求,因為缺少 module-info.java
。
因此,您的專案要在模組路徑上執行 Spring Data Neo4j 6.1+ 所需的最少 module-info.java
如下所示
module-info.java
module your.module {
requires org.neo4j.cypherdsl.core;
requires spring.data.commons;
requires spring.data.neo4j;
opens your.domain to spring.core; (1)
exports your.domain; (2)
}
1 | Spring Data Neo4j 使用 Spring Data Commons 及其反射能力,因此您至少需要將您的域包開放給 spring.core 。 |
2 | 我們在此假設 your.domain 也包含 repositories:它們必須匯出才能被 spring.beans 、spring.context 和 spring.data.commons 訪問。如果您不想將它們匯出到所有模組,可以將它們限制為這些模組。 |
建立您的域
我們的域層應完成兩件事
-
將您的圖對映到物件
-
提供對這些物件的訪問
節點實體示例
SDN 完全支援不可修改的實體,適用於 Java 和 Kotlin 中的 data
類。因此,我們將重點關注這裡的不可變實體,MovieEntity.java 展示了這樣的實體。
SDN 支援 Neo4j Java Driver 支援的所有資料型別,請參閱章節“Cypher 型別系統”中的 將 Neo4j 型別對映到本機語言型別。未來的版本將支援額外的轉換器。 |
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;
import org.springframework.data.neo4j.core.schema.Relationship;
import org.springframework.data.neo4j.core.schema.Relationship.Direction;
@Node("Movie") (1)
public class MovieEntity {
@Id (2)
private final String title;
@Property("tagline") (3)
private final String description;
@Relationship(type = "ACTED_IN", direction = Direction.INCOMING) (4)
private List<Roles> actorsAndRoles = new ArrayList<>();
@Relationship(type = "DIRECTED", direction = Direction.INCOMING)
private List<PersonEntity> directors = new ArrayList<>();
public MovieEntity(String title, String description) { (5)
this.title = title;
this.description = description;
}
// Getters omitted for brevity
}
1 | @Node 用於將此類標記為託管實體。它還用於配置 Neo4j 標籤。如果只使用簡單的 @Node ,標籤預設為類名。 |
2 | 每個實體都必須有一個 ID。此處顯示的 Movie 類使用屬性 title 作為唯一的業務鍵。如果您沒有這樣的唯一鍵,可以使用 @Id 和 @GeneratedValue 的組合來配置 SDN 使用 Neo4j 的內部 ID。我們還提供了 UUID 的生成器。 |
3 | 這展示了 @Property 作為一種方式,使得欄位名稱可以與圖屬性的名稱不同。 |
4 | 這定義了與 PersonEntity 型別的類的關係以及關係型別 ACTED_IN |
5 | 這是供您的應用程式程式碼使用的建構函式。 |
普遍的說法:使用內部生成 ID 的不可變實體有點矛盾,因為 SDN 需要一種方法來使用資料庫生成的值設定欄位。
如果您找不到好的業務鍵或不想使用 ID 生成器,下面是使用內部生成 ID 的相同實體,結合常規建構函式和所謂的 wither 方法,SDN 使用此方法
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;
import org.springframework.data.annotation.PersistenceConstructor;
@Node("Movie")
public class MovieEntity {
@Id @GeneratedValue
private Long id;
private final String title;
@Property("tagline")
private final String description;
public MovieEntity(String title, String description) { (1)
this.id = null;
this.title = title;
this.description = description;
}
public MovieEntity withId(Long id) { (2)
if (this.id.equals(id)) {
return this;
} else {
MovieEntity newObject = new MovieEntity(this.title, this.description);
newObject.id = id;
return newObject;
}
}
}
1 | 這是供您的應用程式程式碼使用的建構函式。它將 ID 設定為 null,因為包含內部 ID 的欄位不應該被修改。 |
2 | 這是 id 屬性的所謂 wither 方法。它建立一個新實體並相應地設定欄位,而不修改原始實體,從而使其不可變。 |
當然,您可以使用 Kotlin 的資料類與 SDN 一起建模您的域。如果您想或需要完全使用 Java,Project Lombok 是另一種選擇。
宣告 Spring Data repository
您基本上有兩種選擇:您可以以儲存無關的方式使用 SDN 並使您的領域特定 repository 擴充套件以下介面之一
-
org.springframework.data.repository.Repository
-
org.springframework.data.repository.CrudRepository
-
org.springframework.data.repository.reactive.ReactiveCrudRepository
-
org.springframework.data.repository.reactive.ReactiveSortingRepository
相應地選擇命令式或響應式。
雖然技術上不禁止,但不建議在同一個應用程式中混合使用命令式和響應式資料庫訪問。我們不會為您提供此類場景的支援。 |
另一種選擇是選擇特定儲存的實現並獲得我們開箱即用的所有方法。這種方法的優點也是其最大的缺點:一旦公開,所有這些方法都將成為您 API 的一部分。大多數時候,移除某些內容比之後新增東西更困難。此外,使用特定於儲存的方法會將您的儲存洩露到您的域中。從效能角度來看,沒有懲罰。
一個適用於上述任何電影實體的響應式 repository 如下所示
import reactor.core.publisher.Mono;
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
public interface MovieRepository extends ReactiveNeo4jRepository<MovieEntity, String> {
Mono<MovieEntity> findOneByTitle(String title);
}
響應式程式碼的測試使用 reactor.test.StepVerifier 完成。請參閱 Project Reactor 的相應文件或檢視我們的示例程式碼。 |