保持自信
redis也是有它的事務(wù)支持的,我們來看看在springboot中如何使用redis的事務(wù)特性吧
方法一
首先在redis的配置類中開啟事務(wù)支持
template.setEnableTransactionSupport(true);
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(jackson2JsonRedisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashKeySerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
//開啟事務(wù)支持
template.setEnableTransactionSupport(true);
return template;
}
驗(yàn)證如下
- redisTemplate.multi(); 開啟事務(wù)
- redisTemplate.exec(); 提交事務(wù)
- redisTemplate.discard(); 回滾事務(wù)
package com.springboot.study.demo1;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.*;
import org.springframework.test.context.junit4.SpringRunner;
/**
*@description: Test1
*@author: yinkai
*@create: 2020/3/7 21:15
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private ValueOperations<String, String> valueOperations;
@org.junit.Test
public void set() {
//收集命令然后在 exec()時(shí)執(zhí)行,不同于mysql這種關(guān)系型數(shù)據(jù)庫
try {
//開啟事務(wù)
redisTemplate.multi();
valueOperations.set("t1", "hello ");
int i = 1 / 0;
valueOperations.set("t2", "world ");
//提交事務(wù)
redisTemplate.exec();
}catch (Exception e){
//取消執(zhí)行事務(wù)
redisTemplate.discard();
}
}
}
執(zhí)行后可以發(fā)現(xiàn),因?yàn)槌霈F(xiàn)除0異常。redis并沒有插入數(shù)據(jù)。那redis事務(wù)的原理是什么呢?
只是把事務(wù)內(nèi)所有的redis操作收集起來,在redisTemplate.exec(); 提交事務(wù)時(shí)一起執(zhí)行而已,并不是像mysql這種關(guān)系型數(shù)據(jù)庫一樣把每條sql都執(zhí)行了只是沒有持久化
方法二
這種形式我開始以為是異步執(zhí)行的,就像 jQuery 的ajax請(qǐng)求一樣。其實(shí)只是寫法上的改變。redisTemplate.execute方法的返回值只是一個(gè)普通的List,并沒有什么異步獲取結(jié)果的功能。其實(shí)只是寫法上和方法一不同而已,也沒什么優(yōu)勢(shì)啊。不過使用這種方式就不需要在redis配置類中開啟事務(wù)配置了
package com.springboot.study.demo1;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.*;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
/**
*@description: Test1
*@author: yinkai
*@create: 2020/3/7 21:15
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private ValueOperations<String, String> valueOperations;
@org.junit.Test
public void set() {
//execute a transaction
List<Object> txResults = redisTemplate.execute(new SessionCallback<List<Object>>() {
public List<Object> execute(RedisOperations operations) throws DataAccessException {
operations.multi();
valueOperations.set("t1", "hello ");
// int i = 1 / 0;
valueOperations.set("t2", "world ");
return operations.exec();
}
});
System.out.println("Number of items added to set: " + txResults.get(0));
}
}
關(guān)于 redisTemplate.execute的返回值是個(gè)List,其實(shí)就是execute方法內(nèi)的所有redis操作語句的返回值集合。上面發(fā)出了2條語句。那么這個(gè)list就有2個(gè)元素了