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

sim*_*onl 5 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.queryla SQL预处理语句向数据库提交了大量自定义cypher查询.当我们这样做时,我们注意到我们提交的自定义Cypher几乎都没有session.query被发送给任何只读的关注者.

我已经破解了代码并注意到,在Neo4jSessionquery方法中,该方法总是创建一个带有类型的事务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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

mei*_*ier 1

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

关于 OGMsession.query调用的第二部分:如果您的工作单元参与现有READ_WRITE事务,例如由于@Transactional上述 AOP 问题而发生这种情况,则无法将类型设置为READ_ONLY。默认情况下,READ_WRITE如果未设置显式类型,OGM 将始终创建交易。

太长;博士;

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

  1. 将方法提取@Transactional到另一个类中,并将调用者代码保留在现有类中。
  2. Session通过注入手动创建对象SessionFactory并创建带有类型的事务READ_ONLY。(并删除@Transactional注释)

(如 Neo4j 用户 slack 中的回答)