redis、springboot事务

redis事务

参考:Redis之Redis事务

SpringBoot开启Redis事务错误: Cannot use Jedis when in Multi. Please use Transaction or reset jedis state.

watch key1 key2 ... : 监视一或多个key,如果在事务执行之前,
				被监视的key被其他命令改动,则事务被打断 ( 类似乐观锁 )
multi : 	标记一个事务块的开始( queued )
exec : 		执行所有事务块的命令 ( 一旦执行exec后,之前加的监控锁都会被取消掉 ) 
discard : 	取消事务,放弃事务块中的所有命令
unwatch :	取消watch对所有key的监控

watch指令类似于乐观锁,在事务提交时,如果watch监控的多个KEY中任何KEY的值已经被其他客户端更改,则使用EXEC执行事务时,事务队列将不会被执行,同时返回Nullmulti-bulk应答以通知调用者事务执行失败。

实战:

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

public Object execTransactionCorrect() {
        // watch该key,如果提交事物时有外界调整则设置失败
        String key = "redis";

        // 开始设置key为100
        stringRedisTemplate.opsForValue().set(key, "100");
        return stringRedisTemplate.execute(new SessionCallback<String>() {
            @Override
            public <K, V> String execute(RedisOperations<K, V> operations) throws DataAccessException {
                try {
                    operations.watch((K) key);
                    // 开启事务
                    operations.multi();
                    // 修改数据
                    operations.opsForValue().set((K)key, (V)"2");
                    // operations.opsForValue().increment((K) key);
                    // 模拟异常
                    Integer.parseInt("a");
                    // 提交事物 之前的redis操作,
                    operations.exec();
                } catch (Exception e) {
                    e.printStackTrace();
                    // 出现异常则需要取消redis事务(不用回滚,因为multi之后,相当于资料)
                    operations.discard();
                }
                return (String) operations.opsForValue().get(key);
            }
        });
    }

springboot手动开启事务

//1,注入bean

    @Autowired
    private PlatformTransactionManager platformTransactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

//2,结合try-catch使用
TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
try {
    dosomething....
    platformTransactionManager.commit(transactionStatus);
} catch (Exception e) {
  platformTransactionManager.rollback(transactionStatus);
}

    @Autowired
    DataSourceTransactionManager txm;

    @Override
    public void test() {
        TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        TransactionStatus status = txm.getTransaction(transactionDefinition);

        this.insert(new PeopleHouseInfoEntity().setRoom("123131"));
        int a = 10 / 0;
        // txm.rollback(status);
        txm.commit(status);
    }

全局切面配置,比注解中优先级高。

package com.yymt.common.config;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.*;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;


@Aspect
//切面
//表示该类相当于Spring的xml配置文件中的<Beans>
@Configuration
public class TransactionAdviceConfig {

    /**
     * 定义切点路径
     */
    private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.yymt.service..*.impl.*.*(..))";

    @Autowired
    private PlatformTransactionManager transactionManager;

    /**
     * @description 事务管理配置
     */
    @Bean
    public TransactionInterceptor TxAdvice() {
        // 事务管理规则,承载需要进行事务管理的方法名(模糊匹配)及设置的事务管理属性
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

        // 设置第一个事务管理的模式(适用于“增删改”)
        RuleBasedTransactionAttribute transactionAttribute1 = new RuleBasedTransactionAttribute();
        // 当抛出设置的对应异常后,进行事务回滚(此处设置为“Exception”级别)
        transactionAttribute1.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        // 设置隔离级别(存在事务则加入其中,不存在则新建事务)
        transactionAttribute1.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 设置传播行为(读已提交的数据)
        transactionAttribute1.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);

        // 设置第二个事务管理的模式(适用于“查”)
        RuleBasedTransactionAttribute transactionAttribute2 = new RuleBasedTransactionAttribute();
        // 当抛出设置的对应异常后,进行事务回滚(此处设置为“Exception”级别)
        transactionAttribute2.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        // 设置隔离级别(存在事务则挂起该事务,执行当前逻辑,结束后再恢复上下文事务) 。xl:挂起后会导致本次插入的数据查询不到()
        transactionAttribute2.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); 
        // transactionAttribute2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 设置传播行为(读已提交的数据)
        transactionAttribute2.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        // 设置事务是否“只读”(非必需,只是声明该事务中不会进行修改数据库的操作,可减轻由事务造成的数据库压力,属于性能优化的推荐配置)
        transactionAttribute2.setReadOnly(true);

        // 建立一个map,用来储存要需要进行事务管理的方法名(模糊匹配)
        Map<String, TransactionAttribute> txMap = new HashMap<>();
        txMap.put("insert*", transactionAttribute1);
        txMap.put("add*", transactionAttribute1);
        txMap.put("send*", transactionAttribute1);
        txMap.put("save*", transactionAttribute1);
        txMap.put("update*", transactionAttribute1);
        txMap.put("modify*", transactionAttribute1);
        txMap.put("change*", transactionAttribute1);
        txMap.put("delete*", transactionAttribute1);
        txMap.put("remove*", transactionAttribute1);
        txMap.put("check*", transactionAttribute1);
        txMap.put("upload*", transactionAttribute1);
        txMap.put("export*", transactionAttribute1);
        txMap.put("create*", transactionAttribute1);
        txMap.put("download*", transactionAttribute1);
        txMap.put("query*", transactionAttribute2);
        txMap.put("get*", transactionAttribute2);
        txMap.put("select*", transactionAttribute2);
        txMap.put("find*", transactionAttribute2);
        // 注入设置好的map
        source.setNameMap(txMap);
        // 实例化事务拦截器
        TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, source);
        return txAdvice;
    }

    /**
     * @description 利用AspectJExpressionPointcut设置切面
     */
    @Bean
    public Advisor txAdviceAdvisor() {
        // 声明切点要切入的面
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        // 设置需要被拦截的路径
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        // 设置切面和配置好的事务管理
        return new DefaultPointcutAdvisor(pointcut, TxAdvice());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值