使用响应式编程方式来访问Neo4j,这里假设已经准备好Neo4j服务器了。
https://start.spring.io/
在这个界面初始化工程:
spring.neo4j.uri=neo4j://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=neo4j
spring.data.neo4j.database=neo4j
logging.level.org.springframework.data.neo4j=DEBUG
这里需要稍微了解一下neo4j的两种协议:
neo4j://
:这种协议主要针对neo4j集群或neo4j节点;bolt://
:主要用于管理neo4j单个节点,不支持集群。neo4j+s://
,表示使用证书认证;neo4j+ssc://
,表示使用自签名证书认证连接数据库。简单来说,+s
,表示使用证书加密连接数据库;+ssc
,表示使用自定义证书加密连接数据库。package com.example.neo4j3.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
@Node("Person")
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PersonEntity {
@Id
@GeneratedValue
private Long id;
private String name;
private Integer born;
}
package com.example.neo4j3.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.neo4j.core.schema.*;
import java.util.HashSet;
import java.util.Set;
import static org.springframework.data.neo4j.core.schema.Relationship.Direction.INCOMING;
@Node("Movie")
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MovieEntity {
@Id
@GeneratedValue
private Long id;
private String title;
@Property("tagline")
private String description;
@Relationship(type = "ACTED_IN", direction = INCOMING)
private Set<PersonEntity> actors = new HashSet<>();
@Relationship(type = "DIRECTED", direction = INCOMING)
private Set<PersonEntity> directors = new HashSet<>();
}
这主要使用ReactiveNeo4jRepository来进行操作neo4j。
package com.example.neo4j3.repository;
import com.example.neo4j3.domain.MovieEntity;
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
import reactor.core.publisher.Mono;
public interface MovieRepository extends ReactiveNeo4jRepository<MovieEntity, Long> {
Mono<MovieEntity> findOneByTitle(String title);
}
这里需要注意一下,使用响应式编程,如果返回0或1个对象需要使用Mono类包装,如果是返回一个数组需要使用Flux类包装。
package com.example.neo4j3.repository;
import com.example.neo4j3.domain.PersonEntity;
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
public interface PersonRepository extends ReactiveNeo4jRepository<PersonEntity, Long> {
}
package com.example.neo4j3.controller;
import com.example.neo4j3.domain.MovieEntity;
import com.example.neo4j3.repository.MovieRepository;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
@RestController
@RequestMapping("/movies")
public class MovieController {
@Resource
private MovieRepository movieRepository;
@PutMapping
Mono<MovieEntity> createOrUpdateMovie(@RequestBody MovieEntity newMovie) {
return movieRepository.save(newMovie);
}
@GetMapping(value = { "", "/" })
Flux<MovieEntity> getMovies() {
return movieRepository.findAll();
}
@GetMapping("/by-title")
Mono<MovieEntity> byTitle(@RequestParam String title) {
return movieRepository.findOneByTitle(title);
}
@DeleteMapping("/{id}")
Mono<Void> delete(@PathVariable Long id) {
return movieRepository.deleteById(id);
}
}
package com.example.neo4j3.config;
import org.neo4j.driver.Driver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider;
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;
import org.springframework.data.neo4j.repository.config.ReactiveNeo4jRepositoryConfigurationExtension;
import org.springframework.transaction.ReactiveTransactionManager;
@Configuration
public class Neo4jConfig {
@Bean(ReactiveNeo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME)
public ReactiveTransactionManager reactiveTransactionManager(
Driver driver,
ReactiveDatabaseSelectionProvider databaseNameProvider) {
return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider);
}
}
curl -X "PUT" "http://localhost:8080/movies" \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"title": "Aeon Flux",
"description": "Reactive is the new cool"
}'
{"id":3,"title":"Aeon Flux","description":"Reactive is the new cool","actors":[],"directors":[]}%
curl http://localhost:8080/movies
[{"id":3,"title":"Aeon Flux","description":"Reactive is the new cool","actors":[],"directors":[]}]%
curl http://localhost:8080/movies/by-title\?title\=Aeon%20Flux
{"id":3,"title":"Aeon Flux","description":"Reactive is the new cool","actors":[],"directors":[]}%
curl -X DELETE http://localhost:8080/movies/3