Spring Data Neo4j执行自定义CQL返回Null问题求助
问题描述
使用Spring Data Neo4j执行自定义CQL时,代码逻辑看似完整,但调用方法始终返回Null值。在Neo4j浏览器中执行相同查询可得到预期结果,尝试更换依赖、修改返回类型均无效。以下是相关配置与代码:
配置与代码
.properties配置
spring.neo4j.uri=bolt://localhost:9486 spring.neo4j.authentication.username=neo4j spring.neo4j.authentication.password=password logging.level.org.springframework.data.neo4j=DEBUG
pom.xml依赖
<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>-->
Entity类
@Node("Job") @AllArgsConstructor @NoArgsConstructor @Data public class Children { @Id @GeneratedValue private long id; private ArrayList<Children> children; private Text text; @Getter @Setter public static class Text { public String name; } }
Repository
import com.horsefly.analyticsapi.model.node4j.Children; import org.springframework.data.neo4j.repository.Neo4jRepository; import org.springframework.data.neo4j.repository.query.Query; import org.springframework.stereotype.Repository; @Repository public interface ChildrenRepository extends Neo4jRepository<Children, Long> { @Query("MATCH (j0:Job {Position: 'supervisor', jobCountryCode:'uk'}) WHERE j0.id=1 RETURN {text:{name: j0.Position}, children: []} AS Tree") Children cqlTest(); }
Component
@Component public class Neo4jBuilder { @Autowired private ChildrenRepository childrenRepository; public String getChildren() { return childrenRepository.cqlTest(); } }
日志信息
2023-03-16 15:29:51.980 DEBUG 17480 --- [ main] o.s.d.n.r.c.StartupLogger : Bootstrapping reactive Neo4j repositories based on SDN v6.1.6 with Spring Data Commons v2.5.6 and Neo4j Driver v4.2.7-b09866e7932eff1844519ce1a75c0cfdc3c782b3. 2023-03-16 15:29:52.005 DEBUG 17480 --- [ main] o.s.d.n.r.c.StartupLogger : Bootstrapping imperative Neo4j repositories based on SDN v6.1.6 with Spring Data Commons v2.5.6 and Neo4j Driver v4.2.7-b09866e7932eff1844519ce1a75c0cfdc3c782b3.
排查与解决方案
核心原因:自定义结果无法映射到@Node实体
你的Children类标注了@Node("Job"),Spring Data Neo4j(SDN)会将其视为Neo4j数据库中Job节点的映射实体。但查询返回的是手动构造的对象结构,并非数据库中的原始节点,SDN无法将这种自定义结构映射到标注了@Node的实体类,因此返回Null。
1. 调整实体类为DTO(移除@Node注解)
如果该类仅用于接收自定义查询结果,不需要对应数据库节点,移除@Node及节点相关注解,将其作为普通DTO:
@AllArgsConstructor @NoArgsConstructor @Data public class Children { private ArrayList<Children> children; private Text text; @Getter @Setter public static class Text { public String name; } }
2. 修改查询语句,移除多余别名
查询中返回的AS Tree别名会干扰SDN的映射逻辑,直接返回构造对象即可:
@Query("MATCH (j0:Job {Position: 'supervisor', jobCountryCode:'uk'}) WHERE j0.id=1 RETURN {text:{name: j0.Position}, children: []}") Children cqlTest();
3. 推荐使用投影接口接收结果
SDN支持投影接口方式接收自定义查询结果,这种方式更灵活且类型安全:
// 定义投影接口 public interface ChildrenProjection { TextProjection getText(); List<ChildrenProjection> getChildren(); interface TextProjection { String getName(); } } // 修改Repository方法 @Repository public interface ChildrenRepository extends Neo4jRepository<Children, Long> { @Query("MATCH (j0:Job {Position: 'supervisor', jobCountryCode:'uk'}) WHERE j0.id=1 RETURN {text:{name: j0.Position}, children: []}") ChildrenProjection cqlTest(); }
4. 完善日志配置,查看查询细节
添加以下日志配置,查看实际执行的CQL及返回结果,确认映射是否正确:
logging.level.org.neo4j.driver=DEBUG logging.level.org.springframework.data.neo4j.repository.query=DEBUG
5. 修复Component中的类型转换问题
getChildren()方法返回类型为String,但cqlTest()返回的是对象,需转为JSON格式:
import com.fasterxml.jackson.databind.ObjectMapper; @Component public class Neo4jBuilder { @Autowired private ChildrenRepository childrenRepository; @Autowired private ObjectMapper objectMapper; public String getChildren() throws JsonProcessingException { Object result = childrenRepository.cqlTest(); return objectMapper.writeValueAsString(result); } }
内容的提问来源于stack exchange,提问作者Cugomastik
相关产品推荐
相关产品推荐

