0%

redis事务

开启事务可以保证所有操作的原子性。

在SpringBoot中redis的事务开启有两种方式,

第一种

注意:默认RedisTemplate是没有开启事务支持的,所以我们先让开启事务支持。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SzjxApplication.class)
public class RedisTransaction {
@Autowired
private StringRedisTemplate stringRedisTemplate;

@Test
public void exec() {
// 开启事务支持,在同一个 Connection 中执行命令
stringRedisTemplate.setEnableTransactionSupport(true);
stringRedisTemplate.multi();
stringRedisTemplate.opsForValue().set("name", "spheign");
stringRedisTemplate.opsForValue().set("gender", "male");
stringRedisTemplate.opsForValue().set("age", "29");
System.out.println(stringRedisTemplate.exec());
}
}

stringRedisTemplate.setEnableTransactionSupport(true);这一句至关重要,也就是开启事务的方式。

但是还有一种更为常见的写法,也就是通过使用 SessionCallback,该接口保证其内部所有操作都是在同一个Session中,最后提交整个session的内容就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SzjxApplication.class)
public class RedisTransaction {

@Autowired
private StringRedisTemplate stringRedisTemplate;

@Test
public void exec() {
SessionCallback<Object> callback = new SessionCallback<Object>() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
operations.multi();
operations.opsForValue().set("name", "comrade");
operations.opsForValue().set("gender", "male");
operations.opsForValue().set("age", "29");
return operations.exec();
}
};
System.out.println(stringRedisTemplate.execute(callback));
}
}

第二种

还可以采用注解的方式自动添加事务。

首先开启redis配置,添加对事物的支持

1
2
3
4
5
6
7
8
9
10
11
@Configuration
@EnableConfigurationProperties({RedisProperties.class})
public class RedisConfig {
@Bean
public StringRedisTemplate customStringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
template.setEnableTransactionSupport(true);
return template;
}
}

使用也比较简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SzjxApplication.class)
public class RedisTransaction {

@Autowired
private StringRedisTemplate stringRedisTemplate;


@Test
@Transactional(rollbackFor = Exception.class)
public void trans(){
Map<String, String> map = new HashMap<>();
map.put("name", "spheign");
stringRedisTemplate.opsForValue().multiSet(map);
throw new RuntimeException("redis异常");
}
}