ベースSpringBoot 2.Xの
多くの場合、リレーショナルデータベースの開発に使用される業務は、実際には、このようRedisのような非リレーショナルデータベースは、また、トランザクションのサポートを持って、どのように使用Redisの取引に紙で説明をしてSpringBoot。
関連するプレゼンテーションが参照できる事項:
0、起因
事故に並んで、我々は大きな値を用いるのRedisの存在を探し、データの量が最大限界ダボを超え、この緊急ラージ・オブジェクトは、単一の文字列値に値を分割します。
データベースを維持し、データベースの更新にダブル同じRedisのを書き込み、削除、挿入、キーを指定のRedisから削除するために。
すべてが従来の動作をRedisのが、鉱山は、データベースの更新方法に埋もれて、開いているトランザクション@Transactional削除につながったこの方法は、キー操作は、トランザクションに参加したのRedis。
後のライン上のエラー:
エラーは、クラスタモデルをRedisのは、トランザクションをサポートしていない、ということを明らかにしました。その理由は、クラスタは、テキストを参照することができ、トランザクションをサポートしていません:?ですがどんなRedisのクライアント(Javaが好ま)Redisのクラスタオンをサポートする取引である
この質問に基づいて、この記事をまとめたもので
1、トランザクション内の春
エラーが発生したときに、すべてのデータアクセステクノロジは、トランザクションのメカニズムを持って、これらの技術は、トランザクションを開くためのAPIを提供し、トランザクションは完全な運用データやロールバックデータに取り組んでいます。
春は異なるデータアクセス技術の問題に対処するためのメカニズムを統一し、春には、トランザクションの提供PlatformTransactionManager
、使用インタフェースへのインタフェース、異なるデータアクセス技術を。
データアクセステクノロジ | 実現 |
---|---|
JDBC | DataSourceTransactionManager |
JPA | JPATransactionManager |
休止状態 | HibernateTransactionManager |
JDO | JDOTransactionManager |
分散トランザクション | JtaTransactionManager |
SpringBootトランザクションで開くには、単にメソッドやクラスにコメントする@Transactionalを使用し、非常に簡単です。
春の公式文書も@EnableTransactionManagementオープントランザクションを必要としますが、SpringBootは自動的に構成することによって行うために私たちを助けている、そうSpringBootはコメントに書いていない
@Transactionalいくつかの共通の属性の下にここにいくつかのメモを強調しました
伝搬
伝播メカニズムの問題、主に以下の、デフォルトが必要です:
- REQUIRED - 同じトランザクションを使用して、新しいトランザクション、Bは方法Aに呼び出し、存在しない場合に異常が方法Bのロールバックが発生した場合、方法Aは、トランザクションを呼び出し、全体のトランザクションがロールバックされます。
REQUIRES_NEW - Bは、データAのロールバックの異常な方法発生しないように、メソッドAがメソッドBを呼び出し、関係なく、問題があるかどうかの、新しいトランザクションを開きます。
- 類似したとREQUIRES_NEWが、唯一のJDBCは、HibernateやJPAをサポートしていませんサポートしています - NESTED
- サポート - トランザクションメソッド呼び出しを使用するトランザクションがあり、何のトランザクションが業務を持っていないではないでしょう
- NOT_SUPPORTED - メソッド呼び出しの最初の段階でのトランザクションが保留中のトランザクションを終了する場合は強制方法は、トランザクション内で実行されていません。
- NEVER - トランザクションが例外をスローする場合は、トランザクションを持っていることを強制することはできません
MANDATORY - トランザクションが例外をスローしない場合は、取引を余儀なくされていなければなりません
rollbackFor
デフォルトでは、ロールバックを引き起こす可能性が例外を指定することはThrowableのサブクラスであります
noRollbackFor
何がデフォルトのThrowableの実行のサブクラスで、異常なトランザクションのロールバックを使用できない原因
2、トランザクションの障害が発生した場合@トランザクション
- 只对public方法生效。默认的protected和private方法上写上@Transactional不会报错,但该方法上的事务不生效,官方原文:Method visibility and @Transactional;
- 默认情况(只写@Transactional不填写rollbackFor参数)下此注解会对unchecked异常进行回滚,对checked异常不回滚;
- 类内部未开启事务的方法调用开启事务的方法
前两条很好理解,针对3,引用丁雪丰的《Spring全家桶》视频中的解释:
Spring的声明式事务本质上是通过AOP来增强了类的功能
Spring的AOP本质上就是为类做了一个代理看似在调用自己写的类,实际用的是增强后的代理类
下图描述了方法被事务代理时的流程,来源:Spring AOP
3、SpringBoot整合Redis事务实践
下面我们搭建一个最简单的SpringBoot整合redis的工程用代码来验证redis事务
SpringBoot整合Redis
SpringBoot整合redis使用的是spring-boot-starter-data-redis
,redis事务依赖于jdbc的事务管理,所以还需要引入jdbc
pom相关引入:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
开启Redis事务
编写redis配置类,开启redis事务,配置事务管理
@Configuration
public class RedisConfig {
@Bean
public StringRedisTemplate StringRedisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
/**
* description 开启redis事务(仅支持单机,不支持cluster)
**/
template.setEnableTransactionSupport(true);
return template;
}
/**
* description 配置事务管理器
**/
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
代码验证
针对本文讨论,设计了四个验证方法,可自行验证
/**
* description 不带事务set
* return java.lang.String
* author 郑晓龙
* createTime 2019/12/12 16:36
**/
@GetMapping("put")
public void put(String key, String value) {
redisService.put(key, value);
}
/**
* description 带事务set
* return java.lang.String
* author 郑晓龙
* createTime 2019/12/12 16:36
**/
@GetMapping("putWithTx")
public void putWithTx(String key, String value) {
redisService.putWithTx(key, value);
}
/**
* description 调用带事务方法不生效的情况
* return java.lang.String
* author 郑晓龙
* createTime 2019/12/12 16:36
**/
@GetMapping("invokeWithPutTx")
public void invokeWithPutTx(String key, String value) {
redisService.invokePutWithTx(key, value);
}
/**
* description 调用带事务方法生效的情况
* return java.lang.String
* author 郑晓龙
* createTime 2019/12/12 16:36
**/
@GetMapping("invokeWithPutTx2")
public void invokeWithPutTx2(String key, String value) {
redisService.invokePutWithTx2(key, value);
}
4、总结:
- redis事务只支持单机,不支持cluster
- 需要开启事务时,只需要在对应的方法或类上使用@Transactional注解即可,SpringBoot自动开启了@EnableTransactionManagement
- 需要注意事务不生效的几种情况
- redis事务依赖于jdbc的事务管理
5、示例代码及参考:
- Transaction Management
- Transaction Propagation
- Transactional Support
- 《Spring全家桶》丁雪丰