Spring Data Neo4j 4返回缓存的结果吗? [英] Spring Data Neo4j 4returning cached results?

查看:65
本文介绍了Spring Data Neo4j 4返回缓存的结果吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定这是Neo4j问题还是Spring Data问题.我是Neo4j的新手,所以我只想确保自己做对了.我正在使用带有neo4j-community-2.3.1数据库实例的spring-data-neo4j:4.0.0.RELEASE.

I'm not sure if this is a Neo4j question or a Spring Data question. I'm fairly new to Neo4j, so I just want to make sure I'm doing things right. I'm using spring-data-neo4j:4.0.0.RELEASE with a neo4j-community-2.3.1 DB instance.

这种情况是,我从数据库查询中得到了更多的期望节点.如果我创建一个由3种不同类型的节点组成的图:

The situation is that I am getting more nodes that I'm expecting back from DB queries. If I create a graph consisting of 3 different types of nodes:

(NodeA)-[:NodeAIncludesNodeB]->(NodeB)-[:NodeBIncludesNodeC]->(NodeC)

,然后运行查询以获取单个NodeA节点,我在查询结果中接收到从NodeA到NodeC的整个图形.

and then I run a query to get a single NodeA node I receive the entire graph from NodeA to NodeC in the query results.

好像我正在从数据库中获取缓存结果,而不是实时结果.我之所以这样说是因为,如果在创建图之后调用session.context.clear(),查询将不再返回包括NodeC在内的整个图,但仍会返回单个NodeA及其所有NodeB.

It seems as though I'm getting cached results instead of live results from the DB. The reason I say this is because if I call session.context.clear() after the creation of the graph, the query no longer returns the entire graph including the NodeC's, but it does still return the single NodeA along with all of its NodeB's.

我在Spring Data Neo4J文档( http://docs.spring.io/spring-data/neo4j/docs/current/reference/html/):

I found this quote in the Spring Data Neo4J documentation (http://docs.spring.io/spring-data/neo4j/docs/current/reference/html/):

但是请注意,会话永远不会返回缓存的对象,因此 不会有加载过时数据的风险;它总是命中 数据库.

Note, however, that the Session does not ever return cached objects so there’s no risk of getting stale data on load; it always hits the database.

我创建了一个小示例应用程序来说明:

I created a small example application to illustrate:

实体类:

@NodeEntity
public class NodeA extends BaseNode {

  private String name;
  @Relationship(type = "NodeAIncludesNodeB", direction = "OUTGOING")
  private Set<NodeB> bNodes;

  public NodeA() {}

  public NodeA(String name) {
    this.name = name;
  }
 //getters, setter, equals and hashcode omitted for brevity
}

@NodeEntity
public class NodeB extends BaseNode {

  private String name;
  @Relationship(type = "NodeBIncludesNodeC", direction = "OUTGOING")
  private Set<NodeC> cNodes;

  public NodeB() {}

  public NodeB(String name) {
    this.name = name;
  }
}

@NodeEntity
public class NodeC extends BaseNode {

  private String name;

  public NodeC() {}

  public NodeC(String name) {
    this.name = name;
  }  
}

存储库:

public interface NodeARepository extends GraphRepository<NodeA> {

  public NodeA findByName(String name);

  @Query("MATCH (n:NodeA) WHERE n.name = {nodeName} RETURN n")
  public NodeA findByNameQuery(@Param("nodeName") String name);

  @Query("MATCH (n:NodeA)-[r:NodeAIncludesNodeB]->() WHERE n.name = {nodeName} RETURN r")
  public NodeA findByNameWithBNodes(@Param("nodeName") String name);

  @Query("MATCH (n:NodeA)-[r1:NodeAIncludesNodeB]->()-[r2:NodeBIncludesNodeC]->() WHERE n.name = {nodeName} RETURN r1,r2")
  public NodeA findByNameWithBAndCNodes(@Param("nodeName") String name);
}

测试应用程序:

@SpringBootApplication
public class ScratchApp implements CommandLineRunner {

  @Autowired
  NodeARepository nodeARep;

  @Autowired
  Session session;

  @SuppressWarnings("unused")
  public static void main(String[] args) {
    ApplicationContext ctx = SpringApplication.run(ScratchApp.class, args);

  }

  @Override
  public void run(String...strings) {

    ObjectMapper mapper = new ObjectMapper();

    NodeA nodeA = new NodeA("NodeA 1");
    NodeB nodeB1 = new NodeB("NodeB 1");
    NodeC nodeC1 = new NodeC("NodeC 1");
    NodeC nodeC2 = new NodeC("NodeC 2");
    Set<NodeC> b1CNodes = new HashSet<NodeC>();
    b1CNodes.add(nodeC1);
    b1CNodes.add(nodeC2);
    nodeB1.setcNodes(b1CNodes);
    NodeB nodeB2 = new NodeB("NodeB 2");
    NodeC nodeC3 = new NodeC("NodeC 3");
    NodeC nodeC4 = new NodeC("NodeC 4");
    Set<NodeC> b2CNodes = new HashSet<NodeC>();
    b2CNodes.add(nodeC3);
    b2CNodes.add(nodeC4);
    nodeB2.setcNodes(b2CNodes);
    Set<NodeB> aBNodes = new HashSet<NodeB>();
    aBNodes.add(nodeB1);
    aBNodes.add(nodeB2);
    nodeA.setbNodes(aBNodes);
    nodeARep.save(nodeA);
//    ((Neo4jSession)session).context().clear();

    try {
      Iterable<NodeA> allNodeAs = nodeARep.findAll();
      System.out.println(mapper.writeValueAsString(allNodeAs));
//      ((Neo4jSession)session).context().clear();

      Iterable<NodeA> allNodeAs2 = nodeARep.findAll();
      System.out.println(mapper.writeValueAsString(allNodeAs2));

      NodeA oneNodeA = nodeARep.findByName("NodeA 1");
      System.out.println(mapper.writeValueAsString(oneNodeA));

      NodeA oneNodeA2 = nodeARep.findByNameQuery("NodeA 1");
      System.out.println(mapper.writeValueAsString(oneNodeA2));

      NodeA oneNodeA3 = session.load(NodeA.class, oneNodeA.getId());
      System.out.println(mapper.writeValueAsString(oneNodeA3));
//      ((Neo4jSession)session).context().clear();

      NodeA oneNodeA4 = nodeARep.findByNameWithBNodes("NodeA 1");
      System.out.println(mapper.writeValueAsString(oneNodeA4));

      NodeA oneNodeA5 = nodeARep.findByNameWithBAndCNodes("NodeA 1");
      System.out.println(mapper.writeValueAsString(oneNodeA5));

    } catch (JsonProcessingException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

  }
}

这是测试程序的结果:

[{"id":20154,"name":"NodeA 1","bNodes":[{"id":20160,"name":"NodeB 1","cNodes":[{"id":20155,"name":"NodeC 1"},{"id":20156,"name":"NodeC 2"}]},{"id":20157,"name":"NodeB 2","cNodes":[{"id":20158,"name":"NodeC 3"},{"id":20159,"name":"NodeC 4"}]}]}] 
[{"id":20154,"name":"NodeA 1","bNodes":[{"id":20160,"name":"NodeB 1","cNodes":[{"id":20155,"name":"NodeC 1"},{"id":20156,"name":"NodeC 2"}]},{"id":20157,"name":"NodeB 2","cNodes":[{"id":20158,"name":"NodeC 3"},{"id":20159,"name":"NodeC 4"}]}]}] 
{"id":20154,"name":"NodeA 1","bNodes":[{"id":20160,"name":"NodeB 1","cNodes":[{"id":20155,"name":"NodeC 1"},{"id":20156,"name":"NodeC 2"}]},{"id":20157,"name":"NodeB 2","cNodes":[{"id":20158,"name":"NodeC 3"},{"id":20159,"name":"NodeC 4"}]}]} 
{"id":20154,"name":"NodeA 1","bNodes":[{"id":20160,"name":"NodeB 1","cNodes":[{"id":20155,"name":"NodeC 1"},{"id":20156,"name":"NodeC 2"}]},{"id":20157,"name":"NodeB 2","cNodes":[{"id":20158,"name":"NodeC 3"},{"id":20159,"name":"NodeC 4"}]}]} 
{"id":20154,"name":"NodeA 1","bNodes":[{"id":20160,"name":"NodeB 1","cNodes":[{"id":20155,"name":"NodeC 1"},{"id":20156,"name":"NodeC 2"}]},{"id":20157,"name":"NodeB 2","cNodes":[{"id":20158,"name":"NodeC 3"},{"id":20159,"name":"NodeC 4"}]}]} 
{"id":20154,"name":"NodeA 1","bNodes":[{"id":20157,"name":"NodeB 2","cNodes":[{"id":20158,"name":"NodeC 3"},{"id":20159,"name":"NodeC 4"}]},{"id":20160,"name":"NodeB 1","cNodes":[{"id":20155,"name":"NodeC 1"},{"id":20156,"name":"NodeC 2"}]}]} 
{"id":20154,"name":"NodeA 1","bNodes":[{"id":20157,"name":"NodeB 2","cNodes":[{"id":20159,"name":"NodeC 4"},{"id":20158,"name":"NodeC 3"}]},{"id":20160,"name":"NodeB 1","cNodes":[{"id":20156,"name":"NodeC 2"},{"id":20155,"name":"NodeC 1"}]}]}

请注意,即使我仅请求除最后两个查询之外的所有查询中的单个节点,每个查询都返回相同的结果.

Note that every query returns the same result, even though I'm only requesting a single node in all but the last two queries.

如果我取消对session.context().clear()的注释,则结果如下:

If I uncomment the session.context().clear() calls here are the results:

[{"id":20161,"name":"NodeA 1","bNodes":[{"id":20164,"name":"NodeB 2","cNodes":null},{"id":20167,"name":"NodeB 1","cNodes":null}]}]
[{"id":20161,"name":"NodeA 1","bNodes":[{"id":20164,"name":"NodeB 2","cNodes":null},{"id":20167,"name":"NodeB 1","cNodes":null}]}] 
{"id":20161,"name":"NodeA 1","bNodes":[{"id":20164,"name":"NodeB 2","cNodes":null},{"id":20167,"name":"NodeB 1","cNodes":null}]} 
{"id":20161,"name":"NodeA 1","bNodes":[{"id":20164,"name":"NodeB 2","cNodes":null},{"id":20167,"name":"NodeB 1","cNodes":null}]}
{"id":20161,"name":"NodeA 1","bNodes":[{"id":20164,"name":"NodeB 2","cNodes":null},{"id":20167,"name":"NodeB 1","cNodes":null}]}
{"id":20161,"name":"NodeA 1","bNodes":[{"id":20164,"name":"NodeB 2","cNodes":null},{"id":20167,"name":"NodeB 1","cNodes":null}]}
{"id":20161,"name":"NodeA 1","bNodes":[{"id":20164,"name":"NodeB 2","cNodes":[{"id":20165,"name":"NodeC 3"},{"id":20166,"name":"NodeC 4"}]},{"id":20167,"name":"NodeB 1","cNodes":[{"id":20163,"name":"NodeC 2"},{"id":20162,"name":"NodeC 1"}]}]}

请注意,只有在我明确请求时才返回整个图,但是我仍然通过NodeA接收到NodeB.

Note that the entire graph is only returned when I request it explicitly, however I am still receiving the NodeB's with the NodeA.

我需要填充对REST调用的响应,而我不想删除多余的对象,这样它们就不会出现在REST响应中.每次访问数据库后,我是否都必须对session.context().clear()进行调用,以免收到缓存的"节点?有没有更好的方法可以使电话收到更细粒度的结果?我可以完全关闭缓存"吗?

I need to populate a response to a REST call and I'd rather not have to strip extraneous objects so they don't appear in the REST response. Will I have to make the call to session.context().clear() after every DB access so that I don't receive "cached" nodes? Is there a better way to make the call to receive a more fine-grained result? Can I turn off the "caching" altogether?

推荐答案

这是设计使然-查询确实会访问数据库以获取新数据,但是,如果实体在会话中已有相关节点,则这些是保留.请注意,某些测试方法的行为是不同的:

This is by design- the query does indeed hit the database to fetch fresh data, however, if the entity had related nodes already in the session, then those are retained. Note that the behaviour of some of your test methods is different:

Iterable<NodeA> allNodeAs = nodeARep.findAll();//默认深度为1,因此它将从图中加载相关节点,距离一跳

Iterable<NodeA> allNodeAs = nodeARep.findAll(); //Default depth 1, so it will load related nodes from the graph, one hop away

NodeA oneNodeA = nodeARep.findByName("NodeA 1");//派生的取景器,默认深度1,与上述行为相同

NodeA oneNodeA = nodeARep.findByName("NodeA 1"); //Derived finder, default depth 1, same behaviour as above

NodeA oneNodeA2 = nodeARep.findByNameQuery("NodeA 1");//自定义查询,它将仅返回查询要求的内容.

NodeA oneNodeA2 = nodeARep.findByNameQuery("NodeA 1"); //Custom query, it will only return what the query asks it to.

如果您使用的是findAll或find-by-id,则需要先执行session.clear(),然后进行深度为0的加载.在此处 https://jira.spring.io/browse/DATAGRAPH-642

You'll want to do a session.clear() followed by a load with depth 0 if you're using a findAll or find-by-id. A detailed explanation is available here https://jira.spring.io/browse/DATAGRAPH-642

这篇关于Spring Data Neo4j 4返回缓存的结果吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆