Как пометить пользовательский запрос шифрования Spring Data Neo4j 5.0.3 только для чтения
В настоящее время я работаю над приложением REST API Spring Data Neo4j 5.0.3, которое взаимодействует с причинным кластером Neo4j 3.3.1, состоящим из 3 основных узлов (1 лидер и 2 последователя). К лучшему или к худшему, мы также отправляем множество пользовательских шифров в базу данных, используя session.query
а-ля SQL подготовленные заявления. Когда мы делаем это, мы замечаем, что практически ни один из наших пользовательских Cypher не был представлен через 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.
Учитывая эти наблюдения, есть ли какие-нибудь простые способы сделать мои запросы доступными только для чтения?
1 ответ
Первая часть, касающаяся Spring: из-за ограничений Spring AOP невозможно иметь несколько изолированных транзакций в одном классе. Лучшим решением было бы отделить вызывающий код от транзакционных методов в разных классах. Тогда @Transactional(readOnly = true)
буду работать.
Вторая часть, касающаяся OGM session.query
звонки: если ваша единица работы участвует в существующей READ_WRITE
транзакция, например, это происходит из-за @Transactional
Проблема АОП выше, нет способа установить тип READ_ONLY
, По умолчанию OGM всегда создает READ_WRITE
транзакция, если не указан явный тип.
ТЛ; др;
Есть два решения проблемы в целом:
- Извлечь
@Transactional
методы в другой класс и оставить код вызывающей стороны в существующем. - Создать
Session
объект вручную, вводяSessionFactory
и создать транзакцию сREAD_ONLY
тип. (и удалите@Transactional
аннотация)
(как ответил в Neo4j пользователь slack)