如何将自定义Spring Data Neo4j 5.0.3 cypher查询标记为只读

时间:2018-02-13 18:42:44

标签: java neo4j spring-data-neo4j spring-data-neo4j-5

我目前正在开发一个Spring Data Neo4j 5.0.3 REST API应用程序,该应用程序与Neo4j 3.3.1因果集群连接,该集群包含3个核心节点(1个领导者和2个粉丝)。无论好坏,我们还使用session.query一个SQL预处理语句向数据库提交了大量自定义cypher查询。当我们这样做时,我们注意到几乎所有通过session.query提交的自定义Cypher都没有被发送给任何只读关注者。

我已经破解了代码并注意到Neo4jSession内的query方法总是会创建一个类型为READ_WRITE的事务。有没有办法解决这个问题,以便我们的查询能够正确分布在我们的集群中?

我也尝试用@Transactional(readOnly = true)标记适当的方法,但它似乎不起作用。当我进入Neo4jTransactionManager时,我在第218行看到以下内容:

private Transaction.Type getTransactionType(TransactionDefinition definition, Neo4jTransactionObject txObject) {
    Transaction.Type type;
    if (definition.isReadOnly() && txObject.isNewSessionHolder()) {
        type = Transaction.Type.READ_ONLY;
    } else if (txObject.transactionData != null) {
        type = txObject.transactionData.type();
    } else {
        type = Transaction.Type.READ_WRITE;
    }
    return type;
}

第一个分支中的第二个条件isNewSessionHolder是什么意思?在单个HTTP API调用的上下文中,我们至少调用数据库2次,因此在第二个查询中,我相信这个条件总是返回false。

鉴于这些观察结果,是否有任何简单的方法可以使我的查询被视为只读?

1 个答案:

答案 0 :(得分:1)

关于Spring的第一部分:由于Spring AOP的限制,在一个类中不可能有多个孤立的事务。 最好的解决方案是将调用代码与不同类中的事务方法分开。然后@Transactional(readOnly = true)将起作用。

关于OGM的session.query来电的第二部分:如果您的工作单元参与现有的READ_WRITE交易,例如这是因为上面的@Transactional AOP问题,无法将类型设置为READ_ONLY。默认情况下,如果未设置显式类型,OGM将始终创建READ_WRITE事务。

TL;博士;

一般来说,这个问题有两种解决方案:

  1. @Transactional方法解压缩到另一个类中,并将调用者代码保留在现有类中。
  2. 通过注入Session手动创建SessionFactory对象,并创建一个READ_ONLY类型的事务。 (并删除@Transactional注释)
  3. (在Neo4j用户松弛中回答)