在redis中的事务控制由watch,multi,exec来实现
public String testT() {
redisTemplate.opsForValue().set("one", "one");
List list =(List) redisTemplate.execute(new SessionCallback() {
@Override
public Object execute(RedisOperations oper) throws DataAccessException {
//设置监控key
oper.watch("one");
//开启事务,在exec执行前,全部都只是进入队列
oper.multi();
oper.opsForValue().set("two", "two");
//获取值为null,因为还在队列里面
Object two = oper.opsForValue().get("two");
if (two == null) {
System.out.println("插入还没执行");
}
return oper.exec();
}
});
System.out.println(list);
return "OK";
}
上面代码首先在redis中插入one,正常执行后redis中有2条记录one,two
其中注意点就是get的时候为null是因为在exec之前,所有的操作全在队列中,并获取不到该key的值
1.进行对应报错操作
redisTemplate.opsForValue().set("one", "one");
List list =(List) redisTemplate.execute(new SessionCallback() {
@Override
public Object execute(RedisOperations oper) throws DataAccessException {
//设置监控key
oper.watch("one");
//开启事务,在exec执行前,全部都只是进入队列
oper.multi();
oper.opsForValue().increment("one", 1);
oper.opsForValue().set("two", "two");
//获取值为null,因为还在队列里面
Object two = oper.opsForValue().get("two");
if (two == null) {
System.out.println("插入还没执行");
}
return oper.exec();
}
});
System.out.println(list);
return "OK";
由于one存的是字符串 oper.opsForValue().increment("one", 1);操作时会报错,但是结果还是插入2条,
2.进行修改值的操作
在oper.watch("one");后打断点把one的值进行修改,再运行,则不会进行插入第二条
总结:在redis中的事务中是对one的值进行监控,如果值发生了变化则放弃事务,即队列中的命令全部放弃
如果没有发生变化,并且是中间某条操作发生异常,会跳过这条命令继续执行。
@Transactional的注解可以实现整个方法的事务控制