2013-07-09 66 views
0

我陷入了一个明显相当普遍的问题,并想知道我到底做错了什么。Spring Data Neo4j坚持丰富的关系

我有两个类型为“Account”的节点,并且想在它们之间添加一个“FRIEND”关系。但是我不会简单地在对应账户能够接受或拒绝友谊请求(通常流)之前添加关系。所以我创造了一个叫“友谊”的丰富关系。

我的单元测试显示请求将被添加到对应的帐户,但不是在启动器之一。

这里是我的代码的摘录我使用至今:

@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(我自己,friendlyHans)时,我认为这两个账户之间的关系将会建立,并且当我指出方向时,我进一步假设,当我检查同行友情列表中,也会有与第一个帐号的关系。不幸的是,这个(assertThat(myself.getFriendships()。size())是(1));)失败,因为该集合是空的。

你能指出我在这里做错了吗?我在过去的几天尝试过 - 不幸的是没有成功。也许这只是一件小事。但我找不到它。

哦,版本号,我使用的是

  • 春数据的Neo4j 2.1.0.RELEASE
  • 弹簧芯3.2.0.RELEASE
  • Neo4j的1.8.1

非常感谢提前。

回答

0

您必须从数据库中读回我自己的对象以更新关系字段,否则您只是在创建新关系之前使用您已阅读的对象。

+0

哦,我的...非常感谢!我认为这很容易......但那很简单?!哈哈......现在像一个迷人的作品。 –