0

私は明らかに非常に一般的な問題に行き詰まり、ここで何が間違っているのか疑問に思っていました.

「アカウント」タイプの 2 つのノードがあり、それらの間に「友達」関係を追加したいと考えています。ただし、相手のアカウントがフレンドシップ リクエストを承認または拒否できるようになる前に、単純に関係を追加することはしません (通常の流れ)。それで「友情」という豊かな関係を築きました。

私のユニットテストは、リクエストがイニシエーターのアカウントではなく、カウンターパートのアカウントに追加されることを示しています。

これまでに使用したコードの抜粋を次に示します。

   @Fetch
   @RelatedToVia(type =  "FRIEND", direction = Direction.BOTH)
   private Set<Friendship> friends;
   ...
   ... 
   public void addFriendshipRequest(Friendship friendship) {
      this.friends.add(friendship);
   }

   public Set<Friendship> getConfirmedFriends() {
    Set<Friendship> friendships = new HashSet<Friendship>();
    for(Friendship f : this.friends) {
        if(f.getState() == Friendship.State.CONFIRMED) {
            friendships.add(f);
        }
    }
    return friendships;
}

public Set<Friendship> getFriendships() {
    return this.friends;
}

public Set<Friendship> getFriendRequests() {
    Set<Friendship> requests = new HashSet<Friendship>();
    for(Friendship f : this.friends) {
        if(f.getState() == Friendship.State.REQUESTED) {
            requests.add(f);
        }
    }
    return requests;
} 
...
...
}

今、私の「友情」関係エンティティ

import org.springframework.data.neo4j.annotation.EndNode;
import org.springframework.data.neo4j.annotation.GraphId;
import org.springframework.data.neo4j.annotation.RelationshipEntity;
import org.springframework.data.neo4j.annotation.StartNode;
import java.io.Serializable;
import java.util.Date;

@RelationshipEntity(type = "FRIEND")
public class Friendship implements Serializable {

public enum State { REQUESTED, CONFIRMED }

@GraphId
private Long id;

@StartNode
private Account requester;

@EndNode
private Account confirmer;

private State state;

private Date dateOfRequest;

private Date dateOfConfirmation;

public Friendship(Account requester, Account target) {
    this.state = State.REQUESTED;
    this.confirmer = target;
    this.requester = requester;
    this.dateOfRequest = new Date();
}

public Friendship() { }

... getter/setter and stuff ommitted


}

対応するサービス

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

import static org.springframework.util.Assert.notNull;

@Service("friendshipService")
@Transactional
@SuppressWarnings("SpringJavaAutowiringInspection")
public class FriendshipServiceImpl implements FriendshipService {

@Autowired
private Neo4jTemplate template;

/**
 * request a friendship with another account
 *
 * @param requester
 * @param target
 */
@Override
public void requestFriendship(Account requester, Account target) {
    notNull(target);
    if(!target.hasFriendshipWith(requester.getId())) {
        target.addFriendshipRequest(new Friendship(requester, target));
        template.save(target);
    }
}

/**
 * change pending state of friendship request to CONFIRMED
 *
 * @param confirmer
 * @param requester
 */
@Override
public void acceptFriendshipRequest(Account confirmer, Account requester) {
    notNull(confirmer);
    for(Friendship f : confirmer.getFriendRequests()) {
        if (f.getRequester().equals(requester)) {
            f.setState(Friendship.State.CONFIRMED);
            f.setDateOfConfirmation(new Date());
        }
    }
    template.save(confirmer);
}

/**
 * declines friendship request by removing it
 *
 * @param confirmer
 * @param requester
 */
@Override
public void declineFriendshipRequest(Account confirmer, Account requester) {
    notNull(confirmer);
    for(Friendship f : confirmer.getFriendRequests()) {
        if (f.getRequester().equals(requester)) {
            confirmer.getFriendships().remove(f);
        }
    }
    template.save(confirmer);
}

}

そして、すべてがスムーズに進むかどうかを確認するための私の簡単な単体テスト...

@ContextConfiguration({"classpath:/test-applicationContext.xml"})
@SuppressWarnings("SpringJavaAutowiringInspection")
@RunWith(SpringJUnit4ClassRunner.class)
public class TestFriendships {

@Autowired
Neo4jTemplate template;

@Autowired
private AccountDetailsService accountDetailsService;

@Autowired
private FriendshipService friendshipService;

private Account myself;
private Account friendlyHans;
private Account unfriendlyPeter;


@Rollback(false)
@BeforeTransaction
public void cleanUpGraph() {
    Neo4jHelper.cleanDb(template);
}

@Before
public void prepareTests() {
    myself = accountDetailsService.createAccount(new Account("itsme"));
    friendlyHans = accountDetailsService.createAccount(new Account("butterflyhans"));
    unfriendlyPeter = accountDetailsService.createAccount(new Account("evilmindedpeter"));
}

@Test
@Transactional
public void testSendFriendshipRequest() throws Exception {
    friendshipService.requestFriendship(myself, friendlyHans);
    assertThat(friendlyHans.getFriendRequests().size(), is(1));
    assertThat(myself.getFriendships().size(), is(1));
    assertThat(friendlyHans.getFriendRequests().iterator().next().getRequester(), is(myself));
    assertThat(friendlyHans.getFriendRequests().iterator().next().getConfirmer(), is(friendlyHans));
    assertThat(friendlyHans.getFriendRequests().iterator().next().getState(), is(Friendship.State.REQUESTED));
}

だから、今、friendshipService.requestFriendship(myself, friendlyHans) を呼び出すと、両方のアカウント間の関係が確立されると仮定し、BOTH への方向を示したので、さらに、相手の友情リストを確認すると、最初のアカウントとの関係にもなります。残念ながら、これ (assertThat(myself.getFriendships().size(), is(1));) はセットが空であるため失敗します。

ここで私が間違っていることを指摘できますか? ここ数日間試してみましたが、残念ながら成功しませんでした。おそらくそれはほんの小さなことです。しかし、私はそれを見つけることができません。

ああ、私が使っているバージョン番号は

  • 春のデータ Neo4j 2.1.0.RELEASE
  • スプリングコア 3.2.0.RELEASE
  • Neo4j 1.8.1

よろしくお願いします。

4

1 に答える 1

0

リレーションシップ フィールドを更新するには、データベースから自分自身のオブジェクトを読み戻す必要があります。そうしないと、新しいリレーションシップを作成する前に、読み込んだオブジェクトを使用することになります。

于 2013-07-09T13:32:17.013 に答える