Spring Data Neo4j 3.1无法保存关系属性值问题求助
Spring Data Neo4j保存Store时出现NullPointerException问题解决
问题场景
n个商店对应k个商品,希望通过HasProduct关系连接商店与商品,并在该关系上存储商品的qty(数量)和price(价格)(不同商店的属性值不同)。
错误代码实现
@Data @Node public class Store { @Id @GeneratedValue private Long id; @Property private String businessType; @Property private int currentOnhandInventory; @Property private String locationId; @Property @Relationship(type = "HasProduct", value = "HasProduct", direction = Direction.OUTGOING) private List<Product> topSellingProducts; } @Data @Node public class Product { @Id @GeneratedValue private Long id; @Property private String name; @Property private String description; @Property private String department; @Property @Relationship private Store store; } @Data @RelationshipProperties public class HasProduct { @RelationshipId @GeneratedValue private Long id; @Property private String qty; @Property private Double price; @TargetNode private Product product; } @RestController @RequestMapping("/store") public class StoreController { private StoreRepository storeRepository; public StoreController(StoreRepository storeRepository) { this.storeRepository = storeRepository; } @PutMapping Mono<Store> createOrUpdateStore(@RequestBody Store newStore) { return storeRepository.save(newStore); } @GetMapping Mono<Store> getStoreById(@RequestParam Long id) { return storeRepository.findById(id); } } @org.springframework.context.annotation.Configuration public class Config { @Bean(ReactiveNeo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME) public ReactiveTransactionManager reactiveTransactionManager( Driver driver, ReactiveDatabaseSelectionProvider databaseNameProvider) { return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider); } @Bean public Configuration cypherDslConfiguration() { return Configuration.newConfig() .withDialect(Dialect.NEO4J_5) .build(); } } public interface StoreRepository extends ReactiveNeo4jRepository<Store, Long> { Mono<List<Store>> findOneById(Long id); }
错误信息
java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "valueToCheck" is null at org.springframework.data.neo4j.core.mapping.NestedRelationshipProcessingStateMachine.hasProcessedValue(NestedRelationshipProcessingStateMachine.java:178) ~[spring-data-neo4j-7.1.0.jar:7.1.0] Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Assembly trace from producer [reactor.core.publisher.FluxPeek] : reactor.core.publisher.Flux.checkpoint(Flux.java:3454) org.springframework.data.neo4j.core.ReactiveNeo4jTemplate.processNestedRelations(ReactiveNeo4jTemplate.java:1049)
问题分析与解决方案
核心错误点
- Store类关系映射错误:
topSellingProducts同时标注@Property和@Relationship,且类型为List<Product>——要存储关系属性(qty、price),必须使用关系属性类HasProduct作为集合元素,而非直接关联Product节点。 - Product类关系注解错误:
store字段错误添加@Property注解,且未指定关系类型与方向,导致双向关系映射混乱。 - 关系属性类关联逻辑缺失:
HasProduct作为关系属性类,未与Store形成正确的关联映射,导致Spring Data Neo4j无法处理关系数据。
修正后的代码实现
1. Store类修正
@Data @Node public class Store { @Id @GeneratedValue private Long id; private String businessType; // 默认映射为节点属性,无需@Property private int currentOnhandInventory; private String locationId; // 正确映射带属性的关系:用HasProduct作为集合元素 @Relationship(type = "HasProduct", direction = Direction.OUTGOING) private List<HasProduct> topSellingProducts; }
2. Product类修正
@Data @Node public class Product { @Id @GeneratedValue private Long id; private String name; private String description; private String department; // 双向关系:指定反向方向与关系类型 @Relationship(type = "HasProduct", direction = Direction.INCOMING) private List<HasProduct> stores; // 一个商品可被多店持有,用集合更合理 }
3. HasProduct关系属性类修正
@Data @RelationshipProperties public class HasProduct { @RelationshipId @GeneratedValue private Long id; private String qty; // 默认映射为关系属性,无需@Property private Double price; @TargetNode private Product product; // 可选:如需双向关联源节点,添加以下字段 // @SourceNode // private Store store; }
4. StoreRepository修正
public interface StoreRepository extends ReactiveNeo4jRepository<Store, Long> { // 原方法语义矛盾,改为符合规范的查询方法 Mono<Store> findById(Long id); }
关键说明
- 节点类字段默认自动映射为节点属性,无需额外添加
@Property(除非属性名与字段名不一致)。 - 当关系需要存储属性时,必须使用
@RelationshipProperties注解的类作为关联类型,不能直接关联节点类。 - 双向关系需明确指定
direction,避免映射冲突。 - Repository查询方法需符合Spring Data命名规范,避免语义矛盾的方法名。
内容的提问来源于stack exchange,提问作者Abhijeet Mahapatro
相关产品推荐
相关产品推荐

