5

我目前正在开发一个 Spring Data Neo4j 5.0.3 REST API 应用程序,该应用程序与由 3 个核心节点(1 个领导者和 2 个追随者)组成的 Neo4j 3.3.1 因果集群接口。无论好坏,我们还使用session.queryla SQL 准备语句向数据库提交了许多自定义密码查询。当我们这样做时,我们注意到几乎没有我们通过提交的自定义 Cyphersession.query被发送给任何只读追随者。

我已经破解了代码并注意到在 内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。

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

4

1 回答 1

1

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

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

tl;博士;

对于这个问题,一般有两种解决方案:

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

(正如 Neo4j 用户松弛中的回答)

于 2018-02-13T20:37:43.620 回答