使用spring数据从Neo4j查询数据一直返回null

Posted

技术标签:

【中文标题】使用spring数据从Neo4j查询数据一直返回null【英文标题】:Querying data from Neo4j using spring data returns null all the time 【发布时间】:2020-05-20 07:03:24 【问题描述】:

我正在尝试通过 spring boot 和 spring 数据来使用 neo4j。 我已经在我的 neo4j 中存储了数据,并且我的所有查询都返回 null,除非我使用我的应用程序存储数据,这让我感到困惑。 我想也许我正在使用嵌入式数据库,但我想情况并非如此,因为我的依赖项中没有它。 这是我的 pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>me.neo4j</groupId>
    <artifactId>neo4jpoc</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-neo4j</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-neo4j</artifactId>
        </dependency>

        <!-- add this dependency if you want to use the bolt driver -->
        <dependency>
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j-ogm-bolt-driver</artifactId>
        </dependency>

        <!-- add this dependency if you want to use the HTTP driver -->
        <!--<dependency>
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j-ogm-http-driver</artifactId>
        </dependency>-->

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

这是我的 application.properties:

spring.data.neo4j.uri=bolt://localhost:7687
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=neo4j
logging.level.org.neo4j.driver.GraphDatabase = debug
logging.level.org.neo4j.driver.Driver = debug
logging.level.org.neo4j.driver.OutboundMessageHandler = debug
logging.level.org.neo4j.driver.InboundMessageDispatcher = debug

这是我的 db.properties:

URI=bolt://localhost
username=neo4j
password=neo4j

这是我的实体:

package me.neo4j.neo4jpoc.graph.entity;

import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.annotation.Relationship;

import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@NodeEntity
public class MyEntity 

    @Id
    @GeneratedValue
    private Long id;

    @Property(name = "NAME")
    private String name;

    @Relationship(type = "CONSISTS_OF", direction = Relationship.UNDIRECTED)
    public Set<MyEntity> children;

    @Relationship(type = "BELONGS_TO", direction = Relationship.UNDIRECTED)
    public Set<MyEntity> parents;

    public void consistsOf(MyEntity child) 
        if (children == null) 
            children = new HashSet<>();
        
        children.add(child);
    

    public void belongsTo(MyEntity parent) 
        if (parents == null) 
            parents = new HashSet<>();
        
        parents.add(parent);
    

    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String toString() 
        return this.name + "'s children => "
                + Optional.ofNullable(this.children).orElse(
                Collections.emptySet()).stream()
                .map(MyEntity::getName)
                .collect(Collectors.toList()) + "'s parents => "
                + Optional.ofNullable(this.parents).orElse(
                Collections.emptySet()).stream()
                .map(MyEntity::getName)
                .collect(Collectors.toList());
    

这是我的 Spring 数据存储库:

package me.neo4j.neo4jpoc.graph.repo;

import me.neo4j.neo4jpoc.graph.entity.MyEntity;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.repository.CrudRepository;

public interface MyEntityRepository extends CrudRepository<MyEntity, Long> 

    @Query("MATCH (l:MAIN) RETURN l")
    MyEntity findQuery();

这是我的 Spring Boot 配置:

package me.neo4j.neo4jpoc;

import org.neo4j.ogm.config.ClasspathConfigurationSource;
import org.neo4j.ogm.config.ConfigurationSource;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableNeo4jRepositories(basePackages = "me.neo4j.neo4jpoc.graph.repo")
@EnableTransactionManagement
public class Neo4jConfiguration 

    @Bean
    public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory) 
        return new Neo4jTransactionManager(sessionFactory);
    

    @Bean
    public SessionFactory sessionFactory(org.neo4j.ogm.config.Configuration configuration) 
        // with domain entity base package(s)
        return new SessionFactory(configuration, "me.neo4j.neo4jpoc.graph.entity");
    

    @Bean
    public org.neo4j.ogm.config.Configuration configuration() 
        ConfigurationSource properties = new ClasspathConfigurationSource("db.properties");
        return new org.neo4j.ogm.config.Configuration.Builder(properties).build();
    



最后是我的 Spring Boot 应用程序类:

package me.neo4j.neo4jpoc;

import me.neo4j.neo4jpoc.graph.entity.MyEntity;
import me.neo4j.neo4jpoc.graph.repo.MyEntityRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class AccessingDataNeo4jApplication 

    private static final Logger LOG = LoggerFactory.getLogger(AccessingDataNeo4jApplication.class);

    public static void main(String[] args) 
        SpringApplication.run(AccessingDataNeo4jApplication.class, args);
    

    @Bean
    CommandLineRunner run(MyEntityRepository repository) 
        return args -> 

            MyEntity myEntity = repository.findQuery();
            System.out.println("myEntity = " + myEntity);
            LOG.debug("myEntity = ", myEntity);
        ;
    

这里还有用于存储我通过 neo4j 浏览器存储在我的 neo4j 数据库中的数据的密码:

CREATE(l:PARENT NAME:'ParentX')
CREATE(w:MAIN NAME:'Node1')
CREATE(t:CHILD NAME:'ChildY')
CREATE (l)-[:CONSISTS_OF]->(w),(w)-[:CONSISTS_OF]->(t)
CREATE (l)<-[:BELONGS_TO]-(w),(w)<-[:BELONGS_TO]-(t)

任何输入都将不胜感激,因为我不知道它为什么不检索数据。

【问题讨论】:

【参考方案1】:

您的(单个)实体类名为MyEntity,其@NodeEntity 注释未指定label 名称,因此关联的节点标签也默认为MyEntity。因此,您的 Java 代码只会创建和搜索带有 MyEntity 标签的节点。

另一方面,您的 Cypher 代码正在创建标签为 PARENTMAINCHILD 的节点。

这就是为什么您的 Java 代码永远不会找到您的 Cypher 代码创建的任何节点的原因。

您将更改 Java 和/或 Cypher 代码以使用相同的节点标签。您可能还需要更新数据库中的现有节点以使用正确的标签。

【讨论】:

那么这是否意味着对于每个标签我需要有一个由@NodeEntity 注释的单独类?这里我需要添加 MainEntity、ParentEntity 和 ChildEntity。对吗? 好吧愚蠢的错误。我应该重新设计我的图表。谢谢@cybersam 顺便问一下,你知道有没有办法与未知类型建立关系?我的意思是假设我的图表中的父级可以有多个不同类型的子级。一个 MAIN 类型的孩子,两个 AUX 类型的孩子和 2 个 AUX2 类型的孩子。但是后来我想将它们全部加载到同一个集合中,因为它们都是父级的子级,但是我不希望它们在 neo4j 中具有相同的标签。 当然。有关更多信息,请参阅docs。如果您仍需要帮助,请创建一个新问题。

以上是关于使用spring数据从Neo4j查询数据一直返回null的主要内容,如果未能解决你的问题,请参考以下文章

如何禁用登录spring数据neo4j

Neo4j 第八篇:投射和过滤

Neo4J 和 Spring 返回空关系

Neo4j,在返回可分页结果的同时查询多个 lucene 索引

如何使用 Neo4J 的 Cypher 查询返回关系类型?

针对 Neo4j 图数据库的关系样式查询