Я следую за учебником RetwisJ here. В этом я не думаю, что транзакции Redis реализованы. Например, в следующей функции, если какое-то исключение происходит между ними, данные будут оставлены в несогласованном состоянии. Я хочу знать, как функция как следующий может быть реализована в Spring Data Redis в качестве одной транзакции:Как реализовать транзакцию в Spring Data Redis в чистом виде?
public String addUser(String name, String password) {
String uid = String.valueOf(userIdCounter.incrementAndGet());
// save user as hash
// uid -> user
BoundHashOperations<String, String, String> userOps = template.boundHashOps(KeyUtils.uid(uid));
userOps.put("name", name);
userOps.put("pass", password);
valueOps.set(KeyUtils.user(name), uid);
users.addFirst(name);
return addAuth(name);
}
Здесь userIdCounter
, valueOps
и users
инициализируется в конструкторе. Я столкнулся с this в документации (раздел 4.8), но я не могу понять, как поместить это в эту функцию, где некоторые переменные инициализируются вне функции (пожалуйста, не говорите, что я должен инициализировать эти переменные в каждом и каждая функция, где мне нужны транзакции!).
PS: Есть еще @Transaction
для Spring Data Redis?
ОБНОВЛЕНИЕ: Я пробовал использовать MULTI
, EXEC
. Код, который я написал для другого проекта, но когда его применительно к этой задаче будет выглядеть следующим образом:
public String addMyUser(String name, String password) {
String uid = String.valueOf(userIdCounter.incrementAndGet());
template.execute(new SessionCallback<Object>() {
@Override
public <K, V> Object execute(RedisOperations<K, V> operations)
throws DataAccessException {
operations.multi();
getUserOps(operations, KeyUtils.uid(uid)).put("name", name);
getUserOps(operations, KeyUtils.uid(uid)).put("pass", password);
getValueOps(operations).set(KeyUtils.user(name), uid);
getUserList(operations, KeyUtils.users()).leftPush(name);
operations.exec();
return null;
}
});
return addAuth(name);
}
private ValueOperations<String, String> getValueOps(RedisOperations operations) {
return operations.opsForValue();
}
private BoundHashOperations<String, String, String> getUserOps(RedisOperations operations, String key) {
return operations.boundHashOps(key);
}
private BoundListOperations<String, String> getUserList(RedisOperations operations, String key) {
return operations.boundListOps(key);
}
Сообщать этот способ использования MULTI
, EXEC
рекомендуется ли или нет.
Привет, прошло много времени с тех пор, как это было задано. И поскольку никто не ответил, я понял, как это сделать (обновляется в вопросе). Но я не знаю, рекомендуется ли это для этого. Является ли TransactionSynchronisationManager способом перехода? Требуется ли какая-либо дополнительная конфигурация, кроме этого? Преимущество, которое я нашел в написанном мной коде, если мне нужно прочитать данные из Redis, я могу использовать «шаблон», и поэтому он не будет частью транзакции. – sinu
Использование «SessionCallback» отлично (см. [ссылка] (http://docs.spring.io/spring-data/data-redis/docs/current/reference/html/redis.html#tx)), поскольку это связывает используемое соединение за время, которое команды выполняют для выполнить и освободить его впоследствии. «TransactionSynchronisationManager» или в следующей версии 1.3 «template.setEnableTransactionSupport (true)» скорее предназначен для обработки нескольких вызовов redis, которые потенциально не находятся близко друг к другу, пока активна внешняя транзакция активна.Обычно не нужно напрямую взаимодействовать с TSM. –