我目前正在处理弹簧数据NEO4J 5.0.3 REST API应用程序,该应用程序与Neo4J 3.3.1的REST API应用程序连接,由3个核心节点(1个领导者和2个关注者(组成。无论好坏,我们还使用 session.query
a la sql准备的语句向数据库提交了许多自定义的密码查询。当我们这样做时,我们注意到通过session.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。
鉴于这些观察,是否有任何简单的方法可以使我的查询被尊重为只读?
关于弹簧的第一部分:由于弹簧AOP的局限性,不可能在一个类中具有多个隔离事务。最好的解决方案是将调用代码与不同类别的交易方法分开。然后@Transactional(readOnly = true)
将起作用。
有关OGM session.query
调用的第二部分:如果您的工作单位参与现有的READ_WRITE
事务,例如由于上面的@Transactional
AOP问题而发生这种情况,因此无法将类型设置为READ_ONLY
。如果未设置明确的类型,则默认的OGM将始终创建READ_WRITE
交易。
tl; dr;
通常有两种解决方案:
- 将
@Transactional
方法提取到另一个类中,然后将呼叫者代码留在现有的代码中。 - 通过注入
SessionFactory
并使用READ_ONLY
类型创建事务来创建Session
对象。(并删除@Transactional
注释(
(如neo4j用户休息中的回答(