spring-data-neo4j基本的一对多关系不持久 [英] spring-data-neo4j basic one-to-many relationship not persisting

查看:599
本文介绍了spring-data-neo4j基本的一对多关系不持久的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:可在 github 上获得的示例项目.

EDIT: Sample project available on github.

我正在后端项目中使用Neo4J(Rest图形数据库,由grapheneDb托管)和Spring Data.

I'm using Neo4J (Rest graph database, hosted in grapheneDb) and Spring Data in our backend project.

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

我在两个实体UserStay之间具有简单的一对多关系.

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

编辑:我认为这与问题无关,但是在看到类似问题,我想我需要更新这个问题(有一个基本的@NodeEntity类,并且两个实体都在扩展该基本类).

EDIT: I thought this wasn't relevant for the issue, but after seeing a similar problem in SDN4, I think I need to update the question (there is a basic @NodeEntity class, and both entities are extending 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'm unable to persist more than one stay. The first stay I add to the user is persisted correctly, but just the first one. The next stays added never persists, and I always retrieve the first one.

我用来创建新住宿的方法是:

The method I use to create a new stay is:

   @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.
   }

编辑:可以通过UserRepository正确检索用户修改的内容.

EDIT: User modified is retrieved correctly through UserRepository.

public interface UserRepositoryCustom {}

public interface UserRepository extends GraphRepository<User>, UserRepositoryCustom {    
   User findById(String id);
}

User user = userRepository.findById(userId);

注意:我也尝试通过存储库界面而不是Neo4jTemplate进行保存,但是我遇到了同样的问题.

两个实体都正确保存在neo4j数据库中,这只是一个持久性问题.

Both entities are correctly saved in the neo4j database, it's just a persistence issue.

我认为这应该很容易,所以我可能会丢失一些东西.

I think this should be quite easy, so I'm probably missing something..

任何帮助将不胜感激.

相关版本:

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

还有另一个 SO问题,其中有一个非常相似的问题,但到目前为止没有任何响应.

There is another SO question with a very similar problem, but without response so far.

推荐答案

这是一件棘手的事情.

您的自定义equals方法导致两个具有其节点ID集合但尚未设置其uuid-id集合的实体相等,以便在将它们加载到集合中时仅包含一个

Your custom equals method causes two entities which have their node-id set but not yet their uuid-id set, to be equal so that when loading them into a set the set will only contain one.

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;
}

如果将代码更改为在BasicNode实体中具有equals/hashcode:

If you change your code to have an equals/hashcode in your BasicNode entity:

   @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;
   }

使只有一个nodeId设置的实体具有可比性

so that entities that have only a nodeId set are comparable

并修改子类方法

   @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;
   }

然后它起作用.

如果正在使用Neo4j Server,请继续前进.我建议您查看

Going forward if you are working with Neo4j Server I recommend to you to check out SDN 4 RC2 instead which was released on Friday.

这篇关于spring-data-neo4j基本的一对多关系不持久的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆