Spring data neo4j 客户端在数据库中没有匹配项时抛出异常

Spring data neo4j client throws exception when there's no match in database

提问人:HaiderBoi 提问时间:11/16/2023 更新时间:11/17/2023 访问量:43

问:

我正在使用 Neo4jClient 进行查询,因为我的源节点和目标节点具有相同的标签。

以下是我如何进行查询

@Repository
public class Neo4jClientRepository {
    @Autowired
    private Neo4jMappingContext neo4jMappingContext;

    @Autowired
    private Neo4jClient neo4jClient;

    public Collection<NodePair> findNodesByUniqueIds(List<String> srcUniqueIds, String nodeName) {
        BiFunction<TypeSystem, MapAccessor, Node> mappingFunction = neo4jMappingContext.getRequiredMappingFunctionFor(Node.class);

        return neo4jClient.query(
                        """
                                MATCH (src:Node)
                                WHERE src.uniqueId IN $uniqueIds
                                OPTIONAL MATCH (src:Node)-[*1..2]-(target:Node)
                                WHERE toUpper(target.name) = toUpper($name)
                                RETURN {src: src, target: target} AS nodePair
                                """)
                .bind(srcUniqueIds).to("uniqueIds")
                .bind(nodeName).to("name")
                .fetchAs(NodePair.class)
                .mappedBy((typeSystem, record) -> {
                        MapValue nodePair = (MapValue) record.get("nodePair");
                        var src = mappingFunction.apply(typeSystem, nodePair.get("src"));
                        var target = mappingFunction.apply(typeSystem, nodePair.get("target"));
                    return new NodePair(src, target);
                })
                .all();
    }
}

当数据库中存在匹配项时,该函数工作正常。

但是,对于某些业务案例,上述查询不一定具有匹配项,这意味着它将根据不同的输入返回空结果。当没有匹配项时,将引发以下异常

org.springframework.dao.InvalidDataAccessApiUsageException: NULL is not iterable; Error code 'N/A'
    at org.springframework.data.neo4j.core.Neo4jPersistenceExceptionTranslator.translateImpl(Neo4jPersistenceExceptionTranslator.java:107)
    at org.springframework.data.neo4j.core.Neo4jPersistenceExceptionTranslator.translateExceptionIfPossible(Neo4jPersistenceExceptionTranslator.java:81)
    at org.springframework.data.neo4j.core.DefaultNeo4jClient.potentiallyConvertRuntimeException(DefaultNeo4jClient.java:230)
    at org.springframework.data.neo4j.core.DefaultNeo4jClient$DefaultRecordFetchSpec.all(DefaultNeo4jClient.java:488)

有没有办法在结果映射到实体类之前进行空检查?或者我怎样才能避免这种情况?

谢谢

弹簧 spring-boot spring-data spring-data-neo4j

评论


答:

0赞 meistermeier 11/17/2023 #1

您可以将映射代码修改为

MapValue nodePair = (MapValue) record.get("nodePair");
var src = mappingFunction.apply(typeSystem, nodePair.get("src"));
if (!nodePair.get("target").isNull()) {
    var target = mappingFunction.apply(typeSystem, nodePair.get("target"));
    return new NodePair(src, target);
}
return new NodePair(src, null);

并检查在这种情况下驱动程序返回的值。null

https://github.com/spring-projects/spring-data-neo4j/issues/2821 也回答了这个问题,但想确保有同样问题的其他人也可以在这里找到答案)

评论

0赞 HaiderBoi 11/18/2023
谢谢!我应该早点想到这一点。顺便说一句,如果这两个节点之间存在关系属性,有没有办法检索它?我已经在节点类中定义了一个,但是当我使用上面的投影(NodePair包含Node src,Node target)时,即使有匹配项,结果中也是空的@Relationship("some_relationship") private SomeRelationshipProperty propertyproperty
0赞 meistermeier 11/20/2023
RelationshipProperties 不是像类那样的实体。为此,您必须手动解析它们。命名并返回它们。您将能够像访问节点一样在 nodePair 中访问它们。[r:*1..2]{src: src, r:r, target: target}MapValuenodePair.get("r").asRelationship()
0赞 HaiderBoi 11/21/2023
我明白了,这是有道理的。如果我将上面的查询修改为类似 ,通常我可以用来捕获返回的值。但在这种情况下,开始节点和结束节点是相同的标签,查询将引发异常。有没有办法通过修改上面的neo4jclient代码来检索路径信息?我试图设计一个 PathEntity 来进行映射,但这里的关系是动态的。MATCH path = (src:Node)-[*1..2]-(target:Node) WHERE toUpper(target.name) = toUpper($name) AND src.uniqueId IN $uniqueIds RETURN nodes(path) as nodes, rels(path) as relsIterable<Map<String, Object>>