簡體   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