如何通过@StartNode关联查询Neo4jRepository?Cypher转Repository方法
问题分析与解决方案
你的问题出在Spring Data Neo4j(SDN)处理实体参数的默认行为上,下面是具体的原因和两种可行的解决办法:
为什么原方法无法工作?
当你定义List<SkillRating> findAllByPerson(Person person)时,SDN会默认根据传入Person对象的所有非空属性生成查询条件。比如如果你的Person对象只有id有值,其他属性(firstName、lastName等)为null,生成的Cypher会是类似这样的:
MATCH (p:Person)-[r:RATED]->(skill:Skill) WHERE p.id = $person_id AND p.firstName IS NULL AND p.lastName IS NULL AND p.birthday IS NULL AND p.email IS NULL RETURN r
显然,数据库中的Person节点这些属性都是有值的,所以这个查询会返回空结果。
解决方案1:使用Person的ID作为参数
直接修改Repository方法,用Person的id代替整个实体作为查询条件,SDN会自动生成正确的Cypher:
@Repository public interface SkillRatingRepository extends Neo4jRepository<SkillRating, Long> { List<SkillRating> findAllByPersonId(Long personId); }
调用时只需要传入目标Person的id即可,比如:
List<SkillRating> ratings = skillRatingRepository.findAllByPersonId(person.getId());
解决方案2:自定义Cypher查询(推荐,更灵活)
如果你想保留用Person实体作为参数的方式,或者需要完全自定义查询逻辑,可以用@Query注解直接写你想要的Cypher语句:
@Repository public interface SkillRatingRepository extends Neo4jRepository<SkillRating, Long> { @Query("MATCH (p)-[r:RATED]->(skill) WHERE id(p) = id($person) RETURN r") List<SkillRating> findAllByPerson(@Param("person") Person person); }
这里的id($person)是SDN的语法,可以直接提取传入Person实体对应的节点ID,刚好匹配你想要的查询逻辑。
如果你更倾向于用ID作为参数,也可以这样写:
@Query("MATCH (p)-[r:RATED]->(skill) WHERE id(p) = $personId RETURN r") List<SkillRating> findAllByPersonId(@Param("personId") Long personId);
内容的提问来源于stack exchange,提问作者alturkovic
相关产品推荐
相关产品推荐

