我目前正在开发一个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。
鉴于这些观察结果,是否有任何简单的方法可以使我的查询被视为只读?
答案 0 :(得分:1)
关于Spring的第一部分:由于Spring AOP的限制,在一个类中不可能有多个孤立的事务。
最好的解决方案是将调用代码与不同类中的事务方法分开。然后@Transactional(readOnly = true)
将起作用。
关于OGM的session.query
来电的第二部分:如果您的工作单元参与现有的READ_WRITE
交易,例如这是因为上面的@Transactional
AOP问题,无法将类型设置为READ_ONLY
。默认情况下,如果未设置显式类型,OGM将始终创建READ_WRITE
事务。
TL;博士;
一般来说,这个问题有两种解决方案:
@Transactional
方法解压缩到另一个类中,并将调用者代码保留在现有类中。Session
手动创建SessionFactory
对象,并创建一个READ_ONLY
类型的事务。 (并删除@Transactional
注释)(在Neo4j用户松弛中回答)