无法通过Neo4J创建数据:返回201但查询不到数据求助
问题根源与解决方案
核心问题:long类型ID的默认值导致节点未实际创建
你遇到的问题本质是实体ID的类型和默认值与Spring Data Neo4j(以及你自定义的EntityGraphMapper)的节点创建逻辑冲突,导致返回201状态码但数据并未写入Neo4j。
从你提供的EntityGraphMapper代码可以看到关键判断逻辑:
if (id < 0) { // 创建新节点逻辑 nodeBuilder = compiler.newNode(id).addLabels(labels).setPrimaryIndex(primaryIndex); context.registerNewObject(id, entity); } else { // 尝试匹配已有节点逻辑 nodeBuilder = compiler.existingNode(Long.valueOf(id.toString())); nodeBuilder.addLabels(labels).setPrimaryIndex(primaryIndex); removePreviousLabelsIfRequired(entity, classInfo, nodeBuilder); }
你的Asset实体中ID是基本类型long,默认值为0,会直接进入else分支:尝试匹配ID为0的已有节点。但Neo4j中不存在这个ID的节点,此时代码并没有执行创建新节点的逻辑,最终导致数据没有被持久化,但Spring Data Rest仍返回201(请求格式合法,但底层写入未生效)。
解决方案:将ID改为包装类型Long
把实体中的ID类型从long改为Long(包装类型),让其默认值为null,这样就能触发正确的新节点创建逻辑:
修改后的Asset实体代码:
@NodeEntity(label = "Asset") public class Asset { @Id @GeneratedValue private Long id ; // 改为Long类型 private String name; private String os; // 补充你请求中用到的os字段 // getter和setter方法 public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getOs() { return os; } public void setOs(String os) { this.os = os; } }
为什么这样能解决问题?
- 包装类型
Long的默认值是null,当你没有传入ID(或传入的ID无效)时,Spring Data Neo4j的@GeneratedValue会自动生成合法的节点ID,同时也能让后续的节点创建逻辑正确识别“新节点”场景。 - 即使你在curl请求中传入
id:1000000,只要Neo4j中不存在该ID的节点,修改后的逻辑也能正确处理(如果需要支持自定义ID,可调整@GeneratedValue的策略,但当前场景下默认策略即可满足需求)。
验证步骤
- 重启应用,重新执行你的curl请求:
curl -i -X POST -H "Content-Type:application/json" -d '{ "name" : "testAsset", "os" : "test", "id":1000000}' http://192.168.10.42:8080/Asset
- 通过GET请求查询数据,比如:
curl http://192.168.10.42:8080/Asset/1000000
此时应该能正常返回你创建的Asset数据。
内容的提问来源于stack exchange,提问作者Volley
相关产品推荐
相关产品推荐

