背景:redis
項目中遇到有一系列對Redis的操做,並須要保持事務處理。spring
環境:數據庫
Spring version 4.1.8.RELEASEspa
Redis Server 2.6.12 (64位)code
spring-data-redis version 1.6.1.RELEASEblog
jedis version 2.7.3索引
使用Spring的@Transactional對redis操做進行控制事務
Spring Redis的配置文件以下:ip
<description>Jedis配置</description> <!-- Redis 配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="maxTotal" value="${redis.maxActive}" /> <property name="maxWaitMillis" value="${redis.maxWait}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> </bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:hostName="${redis.host}" p:port="${redis.port}" p:usePool="true" p:timeout="${redis.timeout}" p:password="${redis.pass}" p:database="${redis.default.db}" p:poolConfig-ref="jedisPoolConfig" /> <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" /> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory" p:defaultSerializer-ref="stringRedisSerializer" p:enableTransactionSupport="false" /> <bean id="redisTemplateTransactional" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory" p:defaultSerializer-ref="stringRedisSerializer" p:enableTransactionSupport="true" />
其中的p:enableTransactionSupport 須要設置爲true,才能開啓Redis事務管理控制。
string
業務代碼以下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Autowired private RedisTemplate<String, String> redisTemplateTransactional; @Transactional public void transactionalForRedis() throws Exception { redisTemplateTransactional.boundValueOps("name").set("TEST_XXX");
redisTemplateTransactional.boundValueOps("age").set("11");
// 異常代碼 for (int i = 0; i < 5; i++) { if (i == 3) {
throw new RedisSystemException("dsd", new Exception("myself exception.....")); } } }
1.使用Spring的事務控制便可:@Transactional
2.其中會拋出異常處理,必須拋出RedisSystemException這個異常才能回滾,若是是本身封裝的異常類,不能回滾。
下面是結合數據庫操做與Redis,在同一個事務中進行控制的代碼樣例:
@Transactional public void test() throws Exception { //操做Redis redisTemplateTransactional.boundValueOps("name").set("TEST_YYYY"); redisTemplateTransactional.boundValueOps("age").set("80"); //操做數據庫: JPA保存操做 SimpleDemoEntity simpleDemoEntity = new SimpleDemoEntity(); simpleDemoEntity.setRemark("nima"); simpleDemoEntity.setWeixinId("1000"); simpleDemoDao.saveAndFlush(simpleDemoEntity); }
當遇到數據庫異常狀況,好比,主鍵衝突,惟一索引值等數據庫異常,Redis的操做也能夠正常回滾。
緣由:
使用@Transactional 事務控制後,Spring對數據庫層面進行了完美的事務控制,那麼當數據庫層拋出的全部異常均可以被事務控制管理。
而Redis或者使用Jedis自己的異常,或者業務異常類並無被Spring的事務控制管理。而Spring-redis,給了咱們一個能夠拋出業務異常的渠道,那就是RedisSystemException。