2016-06-25 8 views
1

私はSpring-Data-Neo4J(4.0.0.RELEASE)を使ってアプリケーションを構築しています。アプリケーションには、PersonエンティティとGroupエンティティの2つのエンティティがあります。また、関係エンティティMember_Ofもあります。これは、ある人がグループのメンバーであることを示します。エンティティは以下のようになりますNeo4Jの2ノード間の多重関係を防止

メンバーをグループに追加する方法があります。このメソッドに@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が返された場合、つまり関係が存在しない場合、グループに追加されます。

問題は、同じ人物が同じグループに複数回追加されることがあることがあります。これは、2人のユーザーがアプリケーションを実行しているときに、同じユーザーを同じグループに追加しようとするときに発生します。

これを防ぐにはどうすればよいですか?私は人とグループとの間に単一の関係を持つ必要があり、複数のものではありません。

答えて

1

リレーションエンティティのすべてのプロパティが等しい場合、指定された2つのエンティティ間に作成されるリレーションは1つだけです。 SDNはタイムスタンプを持っています。SDNは、プロパティの値が異なり、先に進んで2番目の関係を作成するため、2つの関係が異なることを認識しています。

現時点では、SDNにはリレーションシップエンティティのマージと作成を指定できる設定がありません。

おそらくアプリケーションレベルでいくつかの同期を管理する必要があります。

+0

タイムスタンプは、メンバーのグループへの参加時間を記録するために必要です。重複した関係を避けるために小切手を保管しています。私は、既存の関係があるかどうかを確認しています。そうでない場合は、メンバーを追加するだけです。私は全体の方法を同期さえしました。しかし、依然として同時リクエストを送信すると、重複した関係になります。どうすれば問題を解決できますか? – Soumya

+0

javaエンティティのhashtagとequalsメソッドの実装は、Neo4Jに格納されているか、またはNeo4Jから取得された方法に(もしあれば)影響を与えますか? equalsメソッドが適切に実装されていないか、部分的にしか実装されていない場合、Neo4jで豊富な関係を更新する際に問題があることがわかりました。実際、後者の場合、関係は失われつつあります。 – Soumya

1

私は同じ問題を抱え、カスタムサイファークエリを使用して解決できました。このようにそれを呼び出すことによって

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

しかしを、それを取ることはありません。私は、このアプローチがスレッドセーフであることを保証するために広範なテストを行っていません。

This MERGEのアトミック実行に関するWilliam Lyonの回答は、あなたが取る必要がある余分なステップかもしれません。

+0

私はこれを(ユニーク制約なしで)試しましたが、重複した関係も作成します。私たちは広範囲にSDNを使用しており、関係を作成しながらサイファーを使用することは推奨されていません。「http://stackoverflow.com/questions/33461927/creating-relationships-in-neo4j-using-spring-data」 – Soumya

関連する問題