You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data Neo4j中@Query传入关系类型参数失败的问题

Neo4j Repository动态传入关系类型报错的解决方法

问题场景

原本以下代码可正常运行:

interface MyRepository : Neo4jRepository<Character?, Long?> {
    @Query("MATCH (c1:Character)-[:positive]->(c2:Character) WHERE c1.id = \$id RETURN c2")
    fun findRelations(relation: String, id: Long): List<Character>
}

但想要将关系类型(比如示例中的positive)作为参数动态传入,修改后的代码执行时出现语法错误:

interface MyRepository : Neo4jRepository<Character?, Long?> {
    @Query("MATCH (c1:Character)-[:\$relation]->(c2:Character) WHERE c1.id = \$id RETURN c2")
    fun findRelations(relation: String, id: Long): List<Character>
}

报错信息:

org.springframework.dao.InvalidDataAccessResourceUsageException:
Invalid input '$': expected "%", "(" or an identifier (line 1,
column 24 (offset: 23))\n"MATCH
(c1:Character)-[:$relation]->(c2:Character) WHERE c1.id = $id RETURN
c2"\n ^; Error code
'Neo.ClientError.Statement.SyntaxError

尝试按照提示改用%,调整代码后仍报错:

interface MyRepository : Neo4jRepository<Character?, Long?> {
    @Query("MATCH (c1:Character)-[:\\%relation]->(c2:Character) WHERE c1.id = \$id RETURN c2")
    fun findRelations(relation: String, id: Long): List<Character>
}

对应的错误信息:

org.springframework.dao.InvalidDataAccessResourceUsageException:
Invalid input '': expected "%", "(" or an identifier (line 1,
column 25 (offset: 24))\n"MATCH
(c1:Character)-[:%relation]->(c2:Character) WHERE c1.id = $id RETURN
c2"\n ^; Error code
'Neo.ClientError.Statement.SyntaxError

原因与解决方案

核心原因

Cypher语法中,关系类型属于语法结构元素,不能像普通参数那样用$relation直接占位。Spring Data Neo4j需要通过SpEL表达式来动态拼接这类语法元素。

正确代码写法

使用Spring的SpEL表达式#{#relation}替换关系类型,同时建议用反引号包裹以兼容特殊字符并避免注入风险:

interface MyRepository : Neo4jRepository<Character?, Long?> {
    @Query("MATCH (c1:Character)-[:`#{#relation}`]->(c2:Character) WHERE c1.id = \$id RETURN c2")
    fun findRelations(relation: String, id: Long): List<Character>
}

如果你的关系类型不包含特殊字符或空格,也可以省略反引号:

interface MyRepository : Neo4jRepository<Character?, Long?> {
    @Query("MATCH (c1:Character)-[:#{#relation}]->(c2:Character) WHERE c1.id = \$id RETURN c2")
    fun findRelations(relation: String, id: Long): List<Character>
}

补充说明

  • SpEL表达式#{#paramName}会在查询执行前被Spring解析,将参数值直接替换到Cypher语句中,生成合法的语法结构。
  • 反引号的作用是将关系类型作为标识符处理,即使关系类型包含空格、特殊字符也能正常识别,同时能有效防止Cypher注入攻击,推荐始终使用。

内容的提问来源于stack exchange,提问作者JasSy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 22:57:53