Как пометить пользовательский запрос шифрования 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 транзакция, если не указан явный тип.

ТЛ; др;

Есть два решения проблемы в целом:

  1. Извлечь @Transactional методы в другой класс и оставить код вызывающей стороны в существующем.
  2. Создать Session объект вручную, вводя SessionFactory и создать транзакцию с READ_ONLY тип. (и удалите @Transactional аннотация)

(как ответил в Neo4j пользователь slack)

Другие вопросы по тегам