Spring -data-neo4j one-to-many basic relationships are not preserved

EDIT : A sample project is available on github .

I use Neo4J (a break database hosted in grapheneDb) and Spring Data in our backend project.

<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase"> 

I have a simple one-to-many relationship between two objects: User and Stay .

EDIT . I thought this did not apply to the problem, but after looking at a similar problem in SDN4, I think I need to update the question (there is a base class @NodeEntity , and both objects extend this base class).

 @NodeEntity public abstract class BasicNodeEntity implements Serializable { @GraphId private Long nodeId; } public class User extends BasicNodeEntity { @RelatedTo(type = "HAS_STAY", direction = Direction.OUTGOING) Set<Stay> stays; public void addStay(Stay stay) { stays.add(stay); } } public class Stay extends BasicNodeEntity { @RelatedTo(type = "HAS_STAY", direction = Direction.INCOMING) User user; } 

I can no longer stay in one place. The first stay that I add to the user is saved correctly, but only the first. The following additions are not saved, and I always get the first one.

The method that I use to create a new stay:

  @Autowired Neo4jOperations template; @Transactional private void createStay(Stay stay, User user) throws Exception { stay = template.save(stay); user.addStay(stay); template.save(user); // If i evaluate user at this point, it contains both stays // But if I retrieve the user from the repository, it just contains // the first stay, the second one has not persisted. } 

EDIT . User changed correctly restored using UserRepository .

 public interface UserRepositoryCustom {} public interface UserRepository extends GraphRepository<User>, UserRepositoryCustom { User findById(String id); } User user = userRepository.findById(userId); 

NOTE. I also tried saving through the repository interface instead of Neo4jTemplate, but I have the same problem.

Both objects are stored correctly in the neo4j database, this is a storage problem.

I think this should be pretty easy, so I probably missed something.

Any help would be greatly appreciated.

Relevant Versions:

 <spring.version>4.0.5.RELEASE</spring.version> <spring-data-neo4j.version>3.3.2.RELEASE</spring-data-neo4j.version> 

There is another SO question with a very similar problem, but no answer so far.

+4
source share
1 answer

This is a tricky thing.

Your equals method calls two objects with their node-id set installed but their uuid-id set not yet set to be equal so that when loading them into the set only the set contains one.

Code in: RelationshipHelper

 protected Set<Object> createEntitySetFromRelationshipEndNodes(Object entity, final MappingPolicy mappingPolicy, final Class<?> relatedType) { final Iterable<Node> nodes = getStatesFromEntity(entity); final Set<Object> result = new HashSet<Object>(); for (final Node otherNode : nodes) { Object target = template.createEntityFromState(otherNode, relatedType, mappingPolicy); result.add(target); } return result; } 

If you change your code for equals / hashcode in a BasicNode object:

  @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof BasicNodeEntity)) return false; BasicNodeEntity that = (BasicNodeEntity) o; if (nodeId != null) { if (!nodeId.equals(that.nodeId)) return false; } else { if (that.nodeId != null) return false; } return true; } @Override public int hashCode() { return nodeId != null ? nodeId.hashCode() : 0; } 

so that objects having only the nodeId set are comparable

and adapt subclass methods

  @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof IdentifiableEntity)) return false; IdentifiableEntity entity = (IdentifiableEntity) o; //change if (!super.equals(o)) return false; if (id != null) { if (!id.equals(entity.id)) return false; } else { if (entity.id != null) return false; } return true; } @Override public int hashCode() { //change if (super.hashCode() != 0) return super.hashCode(); return id != null ? id.hashCode() : 0; } 

Then it works.

Going forward if you are working with a Neo4j server, I recommend you instead of SDN 4 RC2 , which was released on Friday.

+2
source

All Articles