Neo4j 采用 JAVA 语言开发,是一个高性能的图形数据库,NOSQL 中的一种,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎。
单机版的 Neo4j 安装简单,从官网下载安装包,在 conf
目录下找到 neo4j.conf
配置修改如下配置信息,将注释去掉即可:
dbms.default_listen_address=0.0.0.0
dbms.connector.bolt.enabled=true
dbms.connector.bolt.listen_address=:7687
dbms.connector.http.enabled=true
dbms.connector.http.listen_address=:7474
运行命令启动服务:
./bin/neo4j start # 启动
./bin/neo4j stop # 停止服务
./bin/neo4j restart # 重启服务
./bin/neo4j status # 查看状态
org.springframework.boot
spring-boot-starter-data-neo4j
neo4j-java-driver
org.neo4j.driver
org.neo4j.driver
neo4j-java-driver
4.4.5
这里主要用到注解 @Node
、@Relationship
、@Property
、@RelationshipProperties
、@Id
、@TargetNode
,分别对应的含义是,定义节点、定义关系、定义节点或关系属性、定义关系属性集合、定义SDN的主键、定义关系的另一端节点对象。如下所示:
/**
* 电影实体类
* @author ouyangrongtao
* @since 2022-05-04 12:17
*/
@Data
@NoArgsConstructor
@Node("Movie")
public class MovieEntity {
@Id
private String title;
@Property("description")
private String description;
@Relationship(type = "ACTED_IN", direction = Relationship.Direction.OUTGOING)
private List roles;
@Relationship(type = "DIRECTED", direction = Relationship.Direction.INCOMING)
private List directors;
public MovieEntity(String title, String description) {
this.title = title;
this.description = description;
}
}
/**
* 人员实体类
* @author ouyangrongtao
* @since 2022-05-04 12:17
*/
@Data
@NoArgsConstructor
@Node("Person")
public class PersonEntity {
@Id
private String name;
@Property("born")
private Integer born;
public PersonEntity(Integer born, String name) {
this.born = born;
this.name = name;
}
}
/**
* 电影-人员关系类
* @author ouyangrongtao
* @since 2022-05-04 12:13
*/
@Data
@NoArgsConstructor
@RelationshipProperties
public class Roles {
@Property("id")
private Long id;
@Property("roles")
private List roleList;
@TargetNode
private PersonEntity person;
public Roles(Long id, PersonEntity person, List roleList) {
this.id = id;
this.person = person;
this.roleList = roleList;
}
}
/**
* @author ouyangrongtao
* @since 2022-05-04 12:30
*/
@Repository
public interface MovieRepository extends Neo4jRepository {
}
/**
* @author ouyangrongtao
* @since 2022-05-04 12:50
*/
public interface MovieService {
void add();
MovieEntity findMovie();
MovieEntity testNeo4jTemplate();
Long count();
}
/**
* @autho
* r ouyangrongtao
* @since 2022-05-04 12:51
*/
@Service
public class MovieServiceImpl implements MovieService {
private final MovieRepository movieRepository;
private final Neo4jTemplate neo4jTemplate;
@Autowired
public MovieServiceImpl(MovieRepository movieRepository, Neo4jTemplate neo4jTemplate) {
this.movieRepository = movieRepository;
this.neo4jTemplate = neo4jTemplate;
}
@Override
public void add() {
MovieEntity movie = new MovieEntity("我爱我的祖国", "该片讲述了新中国成立70年间普通百姓与共和国息息相关的故事");
List rolesList = new ArrayList<>(8);
rolesList.add(new Roles(1L, new PersonEntity(1974, "黄渤"), List.of("林治远")));
rolesList.add(new Roles(2L, new PersonEntity(1978, "张译"), List.of("高远")));
rolesList.add(new Roles(3L, new PersonEntity(1974, "吴京"), List.of("陈冬冬")));
rolesList.add(new Roles(4L, new PersonEntity(1985, "杜江"), List.of("朱涛")));
rolesList.add(new Roles(5L, new PersonEntity(1957, "葛优"), List.of("张北京")));
rolesList.add(new Roles(6L, new PersonEntity(1997, "刘昊然"), List.of("沃德乐")));
movie.setRoles(rolesList);
movie.setDirectors(Collections.singletonList(new PersonEntity(1952, "陈凯歌")));
movieRepository.save(movie);
}
@Override
public MovieEntity findMovie() {
return movieRepository.findById("我爱我的祖国").orElse(null);
}
@Override
public MovieEntity testNeo4jTemplate() {
return neo4jTemplate.findById("我爱我的祖国", MovieEntity.class).orElse(null);
}
@Override
public Long count() {
return movieRepository.count();
}
}
@GetMapping("/addMovie")
public void addMovie() {
movieService.add();
}
@SpringBootTest
class MovieServiceImplTest {
@Autowired
private MovieService movieService;
@Test
void add() {
movieService.add();
}
@Test
void count() {
Long count = movieService.count();
Assertions.assertTrue(count > 0);
}
@Test
void findMovie() {
MovieEntity movie = movieService.findMovie();
Assertions.assertNotNull(movie);
}
@Test
void testNeo4jTemplate() {
MovieEntity movie = movieService.testNeo4jTemplate();
Assertions.assertNotNull(movie);
}
}
org.neo4j.driver.exceptions.DatabaseException: Index traversal aborted due to being stuck in infinite loop. This is most likely caused by an inconsistency in the index. Loop occurred when restarting search from root from page 5. | GB+Tree[file:/mnt/d/tmp/neo4j-community-4.4.6/data/databases/neo4j/neostore.labelscanstore.db, layout:TokenScanLayout[version:0.1, identifier:21483684112629824, fixedSize:true], generation:22/23]
at org.neo4j.driver.internal.util.Futures.blockingGet(Futures.java:143)
at org.neo4j.driver.internal.InternalResult.blockingGet(InternalResult.java:128)
at org.neo4j.driver.internal.InternalResult.hasNext(InternalResult.java:64)
at org.springframework.data.neo4j.core.DefaultNeo4jClient$DefaultRecordFetchSpec.one(DefaultNeo4jClient.java:329)
... 98 more
Suppressed: org.neo4j.driver.internal.util.ErrorUtil$InternalExceptionCause
at org.neo4j.driver.internal.util.ErrorUtil.newNeo4jError(ErrorUtil.java:85)
at org.neo4j.driver.internal.async.inbound.InboundMessageDispatcher.handleFailureMessage(InboundMessageDispatcher.java:105)
at org.neo4j.driver.internal.messaging.common.CommonMessageReader.unpackFailureMessage(CommonMessageReader.java:83)
at org.neo4j.driver.internal.messaging.common.CommonMessageReader.read(CommonMessageReader.java:59)
at org.neo4j.driver.internal.async.inbound.InboundMessageHandler.channelRead0(InboundMessageHandler.java:83)
at org.neo4j.driver.internal.async.inbound.InboundMessageHandler.channelRead0(InboundMessageHandler.java:35)
at org.neo4j.driver.internal.shaded.io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
at org.neo4j.driver.internal.async.inbound.MessageDecoder.channelRead(MessageDecoder.java:47)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at org.neo4j.driver.internal.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at org.neo4j.driver.internal.shaded.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
at org.neo4j.driver.internal.shaded.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at org.neo4j.driver.internal.shaded.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at org.neo4j.driver.internal.shaded.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
org.neo4j.driver.exceptions.ServiceUnavailableException: Connection to the database terminated. Please ensure that your database is listening on the correct host and port and that you have compatible encryption settings both on Neo4j server and driver. Note that the default encryption setting has changed in Neo4j 4.0.
at org.neo4j.driver.internal.util.ErrorUtil.newConnectionTerminatedError(ErrorUtil.java:56) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.util.ErrorUtil.newConnectionTerminatedError(ErrorUtil.java:49) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.async.inbound.ChannelErrorHandler.channelInactive(ChannelErrorHandler.java:74) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:389) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:831) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
at org.neo4j.driver.internal.shaded.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[neo4j-java-driver-4.4.0.jar:4.4.0-a44346cddc3aac335fd3d98cf18e489b3790ebee]
... 1 common frames omitted
在集成的过程中遇到如上的报错信息,特别是org.neo4j.driver.exceptions.DatabaseException: Index traversal aborted due to being stuck in infinite loop. This is most likely caused by an inconsistency in the index
异常,在查询问题所在时发现大家遇到这个问题的人几乎没有,也没有解决方案,但实际是因为neo4j驱动 neo4j-java-driver
的版本与数据库的版本不兼容导致;在遇到第二个问题的时候,也是因为驱动版本的原因,但需要注意配置 spring.neo4j.security.encrypted
需要等于 false
。