繁体   English   中英

防止Neo4J中两个节点之间的多重关系

[英]Prevent Multiple Relationships between two nodes in Neo4J

我正在使用Spring-Data-Neo4J(4.0.0.RELEASE)构建应用程序。 该应用程序具有两个实体,一个Person实体和一个Group实体。 还有一个关系实体Member_Of,它表示一个人是一个组的成员。 实体如下图所示

@NodeEntity(label="Person")
public class Person {
   protected String uuid;
   protected String fullName;
   protected String email;

   @Relationship(type = RelationshipNames.MEMBER_OF, direction = Relationship.OUTGOING)
   protected List<GroupMembership> groupMemberships = new ArrayList<GroupMembership>() ;
}

@NodeEntity(label="Group")
public class Group implements Serializable{
   protected static final long serialVersionUID = 1L;

   @GraphId
   protected Long id;
   protected String uuid;
   protected String name;

   @Relationship(type = RelationshipNames.MEMBER_OF, direction = Relationship.INCOMING)
   protected List<GroupMembership> groupMemberships = new ArrayList<GroupMembership>() ;
}

@RelationshipEntity(type = RelationshipNames.MEMBER_OF)
public class GroupMembership implements Serializable{
   private static final long serialVersionUID = 1L;

   @GraphId Long id;
   @Property String uuid; 
   @StartNode Person member;
   @EndNode Group group;
   @DateLong
   Date date;
}

有一种将成员添加到组的方法。 该方法用@Transactional注释。 示例代码如下。

@Override
@Transactional(propagation=Propagation.REQUIRED)
public ResponseEntity<GroupVO> addMembersToGroup(String groupUuid, String personUuid, List<String> personsToAdd){
   Group group = groupRepository.findGroupByUuid(groupUuid);
   List<Person> personsToAdd = IterableUtils.toList(personRepository.findPersonsByUuid(personUuids));

    personsToAdd.forEach(personToAdd -> {
        GroupMembership existingGroupMembership = getActiveMembership(group.getUuid(), personToAdd.getUuid());
        if(existingGroupMembership==null){
            GroupMembership newGroupMembership = new GroupMembership(personToAdd, group, GroupRoleNames.MEMBER, member.getUuid(), new Date());
            personToAdd.getGroupMemberships().add(newGroupMembership);
            group.getGroupMemberships().add(newGroupMembership);
   }
   groupRepository.save(group);
}

它试图做的是,它搜索personToAdd和组之间的现有关系。 如果返回null,即不存在任何关系,则将其添加到组中。

问题有时是同一个人多次添加到同一组中。 当两个人正在运行该应用程序并且他们都试图将同一个人添加到同一组时,就会发生这种情况。

如何防止这种情况发生? 我需要一个人和一个小组之间有一个单一的关系,而不是多个。

只要关系实体上的所有属性均相等,则在两个给定实体之间将仅创建一个关系。 您有一个时间戳记,这是罪魁祸首-SDN意识到这两个关系是不同的,因为它们的属性值不同,因此继续创建第二个关系。

目前,SDN没有配置允许您为关系实体指定合并还是创建。

您可能必须在应用程序级别管理一些同步。

我遇到了同样的问题,并且能够通过使用自定义密码查询来“解决”它。 既然您已经成功添加了Person和Group实体,则可以运行以下查询:

 @Query("MATCH (group:Group) " +
        "MATCH (person:Person) " +
        "WHERE person.uuid={0} AND group.uuid={1} "+
        "MERGE (person)-[r:MEMBER_OF]->(group) " +
        "SET r.uuid ={2} , r.date={3} " +
        "RETURN r")
GroupMembership isMemberOf(String personUuid,String groupUuid, String uuid, Date date);

通过这样调用:

personRepository.isMemberOf(personUuid,groupUuid,uuid,date);

但是 ,不要认为这是理所当然的。 我尚未进行大量测试以确保此方法是线程安全的。

答案由威廉·里昂对MERGE的原子执行可能是,你必须采取额外的步骤。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM