环境信息

  • JDK 版本信息
<properties><java.version>1.8</java.version>
</properties>

  • SpringBoot 版本、依赖信息
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.2.RELEASE</version><relativePath/>
</parent>

我们在 SpringBoot 中使用 Redis 时,会引入如下的 redis starter

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

这个 starter 引入了 jedis 和 spring-data-redis 两个与 redis 核心的包。

Redis 事务相关的命令参考

  • 事务

Redis 事务在 SpringBoot 中的应用

说明:下面以测试用例的形式说明 Redis 事务在 SpringBoot 中正确与错误的用法。首先,看一看当前测试用例的主体代码:

package com.imooc.ad.service;import com.imooc.ad.Application;
import org.junit.Test;
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.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;/*** <h1>Redis 事务测试</h1>* Created by Qinyi.*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class RedisTransTest {/** 注入 StringRedisTemplate, 使用默认配置 */@Autowiredprivate StringRedisTemplate stringRedisTemplate;

  • 错误的用法
/*** <h2>没有开启事务支持: 事务执行会失败</h2>* */
@Test
public void testMultiFailure() {stringRedisTemplate.multi();stringRedisTemplate.opsForValue().set("name", "qinyi");stringRedisTemplate.opsForValue().set("gender", "male");stringRedisTemplate.opsForValue().set("age", "19");System.out.println(stringRedisTemplate.exec());
}

执行以上测试用例,会抛出如下的异常信息:

Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR EXEC without MULTI

这里给出的错误信息显示:在执行 EXEC 命令之前,没有执行 MULTI 命令。这很奇怪,我们明明在测试方法的第一句就执行了 MULTI。通过追踪 multi、exec 等方法,我们可以看到如下的执行源码(spring-data-redis):

public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");Assert.notNull(action, "Callback object must not be null");RedisConnectionFactory factory = getRequiredConnectionFactory();RedisConnection conn = null;try {// RedisTemplate 的 enableTransactionSupport 属性标识是否开启了事务支持,默认是 falseif (enableTransactionSupport) {// only bind resources in case of potential transaction synchronizationconn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);} else {conn = RedisConnectionUtils.getConnection(factory);}boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);

源码中已经给出了答案:由于 enableTransactionSupport 属性的默认值是 false,导致了每一个 RedisConnection 都是重新获取的。所以,我们刚刚执行的 MULTI 和 EXEC 这两个命令不在同一个 Connection 中。

  • 设置 enableTransactionSupport 开启事务支持

解决上述示例的问题,最简单的办法就是让 RedisTemplate 开启事务支持,即设置 enableTransactionSupport 为 true 就可以了。测试代码如下:

/*** <h2>开启事务支持: 成功执行事务</h2>* */
@Test
public void testMultiSuccess() {// 开启事务支持,在同一个 Connection 中执行命令stringRedisTemplate.setEnableTransactionSupport(true);stringRedisTemplate.multi();stringRedisTemplate.opsForValue().set("name", "qinyi");stringRedisTemplate.opsForValue().set("gender", "male");stringRedisTemplate.opsForValue().set("age", "19");System.out.println(stringRedisTemplate.exec());     // [true, true, true]
}

  • 通过 SessionCallback,保证所有的操作都在同一个 Session 中完成

更常见的写法仍是采用 RedisTemplate 的默认配置,即不开启事务支持。但是,我们可以通过使用 SessionCallback,该接口保证其内部所有操作都是在同一个Session中。测试代码如下:

/*** <h2>使用 SessionCallback, 在同一个 Redis Connection 中执行事务: 成功执行事务</h2>* */
@Test
@SuppressWarnings("all")
public void testSessionCallback() {SessionCallback<Object> callback = new SessionCallback<Object>() {@Overridepublic Object execute(RedisOperations operations) throws DataAccessException {operations.multi();operations.opsForValue().set("name", "qinyi");operations.opsForValue().set("gender", "male");operations.opsForValue().set("age", "19");return operations.exec();}};// [true, true, true]System.out.println(stringRedisTemplate.execute(callback));
}

总结:我们在 SpringBoot 中操作 Redis 时,使用 RedisTemplate 的默认配置已经能够满足大部分的场景了。如果要执行事务操作,使用 SessionCallback 是比较好,也是比较常用的选择。

spring boot 事务_Redis 事务在 SpringBoot 中的应用相关推荐

  1. Spring Boot事务

    一.事务的四个特性 原子性(Atomicity,或称不可分割性) 一致性(Consistency) 隔离性(Isolation,又称独立性) 持久性(Durability) 二.事务的开启 默认设置下 ...

  2. Spring Boot 内置Tomcat——IntelliJ IDEA中配置模块目录设为文档根目录(DocumentRoot)解决方案

    源码分析 org.springframework.boot.web.servlet.server.DocumentRoot /*** Returns the absolute document roo ...

  3. 将Spring Boot应用程序部署到Tomcat中

    "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证. 部署应用 ...

  4. java servlet 部署到tomcat_如何把spring boot项目部署到tomcat容器中

    把spring-boot项目按照平常的web项目一样发布到tomcat容器下 一.修改打包形式 在pom.xml里设置 war 二.移除嵌入式tomcat插件 在pom.xml里找到spring-bo ...

  5. 第5章 Spring Boot事务支持

    开心一笑 [长得好看就出去走走,让其他人感受下外界的美好. 长得不好看就出去走走,让其他人感受下自己在外界的美好.] 新书购买 戳图购买 >>> 5.1 Spring事务介绍 5.1 ...

  6. 全局性事务控制如何在springboot中配置

    开发中,我们一般会利用AOP配置全局性的事务,对指定包下指定的方法(如add,update等)进行事务控制,在springboot中如何实现呢? @EnableTransactionManagemen ...

  7. Spring Boot 通过Restful API,在PostMan 中返回数据

    Spring Boot 通过Restful API,在PostMan 中返回数据 资源组 新增 POST/resource_group/ad 请求体:格式:from-data参数:groupName= ...

  8. Spring Boot 事务支持

    如何使用? Spring Boot 使用事务支持,非常简单,底层依然采用的是Spring本身提供的事务管理. 1.在启动类中添加 @EnableTransactionManagement 注解 2.在 ...

  9. Spring Boot事务管理详解

    什么是事务? 我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合.由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻辑并 ...

最新文章

  1. MIT Graph实践概述
  2. VisionSeed 腾讯优图实验室
  3. python 链表推导式 xx for xx in yy
  4. 《研磨设计模式》chap21 解释器模式Interpreter(1)模式介绍
  5. 网络钓鱼者钓到威胁情报公司的身上 黑客惨遭溯源
  6. C++ inline
  7. thymeleaf体验
  8. React开发(124):ant design学习指南之form中的属性isFieldTouched
  9. nginx学习文档之二 配置负载均衡-负载均衡发现的问题
  10. 【渝粤教育】国家开放大学2018年秋季 1301T病理生理学 参考试题
  11. 区块链在图书馆中应用
  12. 【Microsoft Azure 的1024种玩法】七.Azure云端搭建部署属于自己的维基百科
  13. 手机分辨率Android教程(十二)-- 使用DisplayMetrics获取手机分辨率
  14. Vue生成二维码组件封装
  15. html css jsp 数据库,html、css、js、jsp的区别是什么?
  16. 万字详解!Git 入门最佳实践 !
  17. 【英译中】如何拍好沙滩照2——2014年7月24日
  18. CString 和 LPCTSTR 之间的转换 及 LPSTR、LPWSTR、LPCSTR、LPCWSTR、LPTSTR、LPCTSTR的区分与转化
  19. Linux安装dos2unix的方法—绝对完全有用
  20. 幼儿园案例经验迁移_幼儿园教学案例分析

热门文章

  1. aws rds监控慢sql_使用AWS Lambda函数自动启动/停止AWS RDS SQL Server
  2. 【转】网络安全-------防止被抓包
  3. a超链接之返回顶部的两种实现方法
  4. (转) C# Async与Await的使用
  5. Hadoop 环境准备
  6. supervisor、pm2、forever坐下来聊聊
  7. 谈学习:合格的编程自学者必须知道的几点
  8. 设计模式中类的关系之泛化(Generalization)
  9. 后台创建窗体下拉列表
  10. 预培训个人项目(地铁线路规划)