提问人:HaiderBoi 提问时间:11/16/2023 更新时间:11/17/2023 访问量:43
Spring data neo4j 客户端在数据库中没有匹配项时抛出异常
Spring data neo4j client throws exception when there's no match in database
问:
我正在使用 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)
有没有办法在结果映射到实体类之前进行空检查?或者我怎样才能避免这种情况?
谢谢
答:
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 property
property
0赞
meistermeier
11/20/2023
RelationshipProperties 不是像类那样的实体。为此,您必须手动解析它们。命名并返回它们。您将能够像访问节点一样在 nodePair 中访问它们。[r:*1..2]
{src: src, r:r, target: target}
MapValue
nodePair.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 rels
Iterable<Map<String, Object>>
评论