Spring Boot 各种事务操作实战(自动回滚、手动回滚、部分回滚)

概念

事务定义

事务,就是一组操作数据库的动作集合。事务是现代数据库理论中的核心概念之一。如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务。当所有的步骤像一个操作一样被完整地执行,我们称该事务被提交。由于其中的一部分或多步执行失败,导致没有步骤被提交,则事务必须回滚到最初的系统状态。

事务特点
  • 原子性:一个事务中所有对数据库的操作是一个不可分割的操作序列,要么全做要么全不做
  • 一致性:数据不会因为事务的执行而遭到破坏
  • 隔离性:一个事务的执行,不受其他事务的干扰,即并发执行的事务之间互不干扰
  • 持久性:一个事务一旦提交,它对数据库的改变就是永久的。

事务实现机制

Spring为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式声明式的两种方式。

  • 编程式事务管理: 编程式事务管理使用TransactionTemplate或者直接使用底层的 PlatformTransactionManager。对于编程式事务管理,spring 推荐使用 TransactionTemplate。
  • 声明式事务管理: 建立在 AOP 之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
  • 声明式事务管理不需要入侵代码,更快捷而且简单,推荐使用。

声明式事务有两种方式:

  • 一种是在配置文件(xml)中做相关的事务规则声明(因为很少用本文不讲解)
  • 另一种是基于**@Transactional**注解的方式。注释配置是目前流行的使用方式,推荐使用。

在应用系统调用声明了 @Transactional 的目标方法时,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,根据 @Transactional 的属性配置信息,这个代理对象决定该声明 @Transactional 的目标方法是否由拦截器 TransactionInterceptor 来使用拦截,在 TransactionInterceptor 拦截时,会在目标方法开始执行之前创建并加入事务,并执行目标方法的逻辑,最后根据执行情况是否出现异常,利用抽象事务管理器 AbstractPlatformTransactionManager 操作数据源 DataSource 提交或回滚事务。

Spring AOP 代理有 CglibAopProxy 和 JdkDynamicAopProxy 两种,以 CglibAopProxy 为例,对于 CglibAopProxy,需要调用其内部类的 DynamicAdvisedInterceptor 的 intercept 方法。对于 JdkDynamicAopProxy,需要调用其 invoke 方法。

开启事务

注解 @Transactional 的使用
注解 @Transactional 常用配置

参 数 名 称

功 能 描 述

readOnly

用于设置当前事务是否为只读事务,设置为 true 表示只读,false 则表示可读写,默认值为 false。例如:@Transactional(readOnly=true)

rollbackFor

用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:指定单一异常类:@Transactional(rollbackFor=RuntimeException.class);指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})

transactionManager / value

多个事务管理器托管在 Spring 容器中时,指定事务管理器的 bean 名称

rollbackForClassName

用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如:指定单一异常类名称 @Transactional(rollbackForClassName=”RuntimeException”) 指定多个异常类名称:@Transactional(rollbackForClassName={“RuntimeException”,”Exception”})

noRollbackFor

用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class) 指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})

noRollbackForClassName

用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。例如:指定单一异常类名称:@Transactional(noRollbackForClassName=”RuntimeException”) 指定多个异常类名称:@Transactional(noRollbackForClassName={“RuntimeException”, ”Exception”})

propagation

用于设置事务的传播行为。例如:@Transactional(propagation=Propagation.NOT_SUPPORTED, readOnly=true)

isolation

用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置

timeout

该属性用于设置事务的超时秒数,默认值为 - 1 表示永不超时
事物超时设置:@Transactional(timeout=30) ,设置为 30 秒

Propagation 的属性(事务的传播行为)

例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)

Propagation 属性

含义

REQUIRED

默认值 在有 transaction 状态下执行;如当前没有 transaction,则创建新的 transaction;

SUPPORTS

如当前有 transaction,则在 transaction 状态下执行;如果当前没有 transaction,在无 transaction 状态下执行;

MANDATORY

必须在有 transaction 状态下执行,如果当前没有 transaction,则抛出异常 IllegalTransactionStateException;

REQUIRES_NEW

创建新的 transaction 并执行;如果当前已有 transaction,则将当前 transaction 挂起;

NOT_SUPPORTED

在无 transaction 状态下执行;如果当前已有 transaction,则将当前 transaction 挂起;

NEVER

在无 transaction 状态下执行;如果当前已有 transaction,则抛出异常 IllegalTransactionStateException。

事务 5 种隔离级别

例如:@Transactional(isolation = Isolation.READ_COMMITTED)

隔离级别

含义

DEFAULT

这是一个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别另外四个与 JDBC 的隔离级别相对应;

READ_UNCOMMITTED

最低的隔离级别。事实上我们不应该称其为隔离级别,因为在事务完成前,其他事务可以看到该事务所修改的数据。而在其他事务提交前,该事务也可以看到其他事务所做的修改。可能导致脏,幻,不可重复读

READ_COMMITTED

大多数数据库的默认级别。在事务完成前,其他事务无法看到该事务所修改的数据。遗憾的是,在该事务提交后,你就可以查看其他事务插入或更新的数据。这意味着在事务的不同点上,如果其他事务修改了数据,你就会看到不同的数据。可防止脏读,但幻读和不可重复读仍可以发生。

REPEATABLE_READ

比 ISOLATION_READ_COMMITTED 更严格,该隔离级别确保如果在事务中查询了某个数据集,你至少还能再次查询到相同的数据集,即使其他事务修改了所查询的数据。然而如果其他事务插入了新数据,你就可以查询到该新插入的数据。可防止脏读,不可重复读,但幻读仍可能发生。

SERIALIZABLE

完全服从 ACID 的隔离级别,确保不发生脏读、不可重复读和幻影读。这在所有隔离级别中也是最慢的,因为它通常是通过完全锁定当前事务所涉及的数据表来完成的。代价最大、可靠性最高的隔离级别,所有的事务都是按顺序一个接一个地执行。避免所有不安全读取。

使用注意事项(防止事务失效)
  • 在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。

  • **@Transactional 注解应该只被应用在 public 修饰的方法上。**如果你在 protected、private 或者 package-visible 的方法上使用 该注解,它也不会报错(IDEA 会有提示), 但事务并没有生效。

  • 被外部调用的公共方法 A 有两个进行了数据操作的子方法 B 和子方法 C 的事务注解说明:

    • 被外部调用的公共方法 A 未声明事务 @Transactional,子方法 B 和 C 若是其他类的方法且各自声明事务,则事务由子方法 B 和 C 各自控制

    • 被外部调用的公共方法 A 未声明事务 @Transactional,子方法 B 和 C 若是本类的方法,则无论子方法 B 和 C 是否声明事务,事务均不会生效

    • 被外部调用的公共方法 A 声明事务 @Transactional,无论子方法 B 和 C 是不是本类的方法,无论子方法 B 和 C 是否声明事务,事务均由公共方法 A 控制

    • 被外部调用的公共方法 A 声明事务 @Transactional,子方法运行异常,但运行异常被子方法自己try-catch处理了,则事务回滚是不会生效的!

      如果想要事务回滚生效,需要将子方法的事务控制交给调用的方法来处理:

      • 方案 1:子方法中不用try-catch处理运行异常
      • 方案 2:子方法的 catch 里面将运行异常抛出【throw new RuntimeException();】
  • 默认情况下,Spring 会对 unchecked 异常进行事务回滚,也就是默认对 RuntimeException() 异常或是其子类进行事务回滚。

    如果是 checked 异常则不回滚,例如空指针异常、算数异常等会被回滚;文件读写、网络问题 Spring 就没法回滚。

    若想对所有异常(包括自定义异常)都起作用,注解上面需配置异常类型:@Transactional(rollbackFor = Exception.class

  • 数据库要支持事务,如果是 mysql,要使用 innodb 引擎,myisam 不支持事务

  • 事务 @Transactional 由 spring 控制时,它会在抛出异常的时候进行回滚。如果自己使用 try-catch 捕获处理了,是不生效的。如果想事务生效可以进行手动回滚或者在 catch 里面将异常抛出【throw new RuntimeException();】

    • 方案一:手动抛出运行时异常(缺陷是不能在 catch 代码块自定义返回值)

      try{....  }catch(Exception e){logger.error("",e);throw new RuntimeException(e);}
      
    • 方案二:手动进行回滚【 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 】

      try{...}catch(Exception e){log.error("fail",e);TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();return false;}
      
  • @Transactional 可以放在 Controller 下面直接起作用,看到网上好多同学说要放到 @Component 下面或者 @Service 下面,经过试验,可以不用放在这两个下面也起作用。

  • @Transactional 引入包问题,它有两个包:

    import javax.transaction.Transactional; 
    // 和
    import org.springframework.transaction.annotation.Transactional;         // 推荐
    

    这两个都可以用,对比了一下他们两个的方法和属性,发现后面的比前面的强大。建议使用后面的。

使用场景
自动回滚

直接抛出,不 try/catch

@Override
@Transactional(rollbackFor = Exception.class)
public Object submitOrder() throws Exception {  success();  //假如exception这个操作数据库的方法会抛出异常,方法success()对数据库的操作会回滚。 exception(); return ApiReturnUtil.success();
}
手动回滚

进行 try/catch,回滚并抛出

@Override
@Transactional(rollbackFor = Exception.class)
public Object submitOrder (){  success();  try {  exception(); } catch (Exception e) {  e.printStackTrace();     // 手动回滚事务TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();return ApiReturnUtil.error();}  return ApiReturnUtil.success();
}
回滚部分异常

使用【Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint(); 】设置回滚点。

使用【TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);】回滚到 savePoint。

@Override
@Transactional(rollbackFor = Exception.class)
public Object submitOrder (){  success();  //只回滚以下异常,Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();try {  exception(); } catch (Exception e) {  e.printStackTrace();     // 手工回滚事务TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);return ApiReturnUtil.error();}  return ApiReturnUtil.success();
}
手动创建、提交、回滚事务

PlatformTransactionManager 这个接口中定义了三个方法 getTransaction 创建事务,commit 提交事务,rollback 回滚事务。它的实现类是 AbstractPlatformTransactionManager。

@Autowired
priDataSourceTransactionManager dataSourceTransactionManager;
@Autowired
TransactionDefinition transactionDefinition;// 手动创建事务
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);// 手动提交事务
dataSourceTransactionManager.commit(transactionStatus);// 手动回滚事务。(最好是放在catch 里面,防止程序异常而事务一直卡在哪里未提交)
dataSourceTransactionManager.rollback(transactionStatus);
PlatformTransactionManager 手动提交事务,设置隔离级别
@Autowired
private PlatformTransactionManager transactionManager;public void test() {DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);try {// 数据库操作 //提交事务transactionManager.commit(transactionStatus);} catch (Exception e) {log.error("xxxx", e);//回滚事务transactionManager.rollback(transactionStatus);}
}

事务失效不回滚的原因及解决方案

异常被捕获导致事务失效

在 spring boot 中,使用事务非常简单,直接在方法上面加入 @Transactional 就可以实现。

@GetMapping("delete")
@ResponseBody
@Transactional    
public void delete(@RequestParam("id") int id) {       try {          //delete countrythis.repository.delete(id);         if(id == 1){              throw Exception("测试事务");}           //delete citythis.repository.deleteByCountryId(id);}catch (Exception e){logger.error("delete false:" + e.getMessage());        }
}

发现事务不回滚,即 this.repository.delete(id);成功把数据删除了。

原因:

默认 spring 事务只在发生未被捕获的 RuntimeException 时才回滚。

spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样 aop 代理才能捕获到方法的异常,才能进行回滚,默认情况下 aop 只捕获 RuntimeException 的异常,但可以通过配置来捕获特定的异常并回滚。

换句话说在 service 的方法中不使用 try catch 或者在 catch 中最后加上 throw new RuntimeExcetpion() 抛出运行异常,这样程序异常时才能被 aop 捕获进而回滚。

解决方案:

<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>4.3.2.RELEASE</version></dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.9</version>
</dependency><plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.9</version>
<configuration><showWeaveInfo>true</showWeaveInfo><aspectLibraries><aspectLibrary><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId></aspectLibrary></aspectLibraries>
</configuration><executions>
<execution><goals><goal>compile</goal><goal>test-compile</goal></goals>
</execution>
</executions>
</plugin>
解决方案

方案 1、在类上(或者最外层的公共方法)加事务

@Service
@Slf4j
public class MyTransactional {// 最外层公共方法。自动回滚事务方式,insertOrder()方法报错后事务回滚,且线程中止,后续逻辑无法执行@Transactionalpublic void test1() {this.insertOrder();System.out.println("11111111111111111");}// 最外层公共方法。手动回滚事务方式,insertOrder()方法报错后事务回滚,可以继续执行后续逻辑@Transactionalpublic void test2() {try {  insertOrder();} catch (Exception e) {  log.error("faild to ...", e);// 手动回滚事务TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();// 其他操作}// 其他操作}// 进行数据库操作的方法(private 或 public 均可)private void insertOrder() {//insert log info//insertOrder//updateAccount}
}

方案 2、使用 AspectJ 取代 Spring AOP 代理

上面的两个问题 @Transactional 注解只应用到 public 方法和自调用问题,是由于使用 Spring AOP 代理造成的。为解决这两个问题,可以使用 AspectJ 取代 Spring AOP 代理。

需要将下面的 AspectJ 信息添加到 xml 配置信息中。

AspectJ 的 xml 配置信息

<tx:annotation-driven mode="aspectj" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property  />
</bean>
</bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect" factory-method="aspectOf"><property  />
</bean>

同时在 Maven 的 pom 文件中加入 spring-aspects 和 aspectjrt 的 dependency 以及 aspectj-maven-plugin。

AspectJ 的 pom 配置信息

其他

事务提交方式

默认情况下,数据库处于自动提交模式。每一条语句处于一个单独的事务中,在这条语句执行完毕时,如果执行成功则隐式的提交事务,如果执行失败则隐式的回滚事务。

对于正常的事务管理,是一组相关的操作处于一个事务之中,因此必须关闭数据库的自动提交模式。不过,这个我们不用担心,spring 会将底层连接的【自动提交特性】设置为 false 。也就是在使用 spring 进行事务管理的时候,spring 会将【是否自动提交】设置为 false,等价于 JDBC 中的 connection.setAutoCommit(false); ,在执行完之后在进行提交 connection.commit(); 。

事务回滚规则

指示 spring 事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。spring 事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。

默认配置下,spring 只有在抛出的异常为运行时 unchecked 异常时才回滚该事务,也就是抛出的异常为 RuntimeException 的子类 (Errors 也会导致事务回滚),而抛出 checked 异常则不会导致事务回滚。

可以明确的配置在抛出那些异常时回滚事务,包括 checked 异常。也可以明确定义那些异常抛出时不回滚事务。

事务并发会产生的问题

术语

含义

脏读

A 事务读取到了 B 事务还未提交的数据,如果 B 未提交的事务回滚了,那么 A 事务读取的数据就是无效的,这就是数据脏读

不可重复读

在同一个事务中,多次读取同一数据返回的结果不一致,这是由于读取事务在进行操作的过程中,如果出现更新事务,它必须等待更新事务执行成功提交完成后才能继续读取数据,这就导致读取事务在前后读取的数据不一致的状况出现

幻读

A 事务读取了几行记录后,B 事务插入了新数据,并且提交了插入操作,在后续操作中 A 事务就会多出几行原本不存在的数据,就像 A 事务出现幻觉,这就是幻读

第一类丢失更新

没有事务隔离的情况下,两个事务都同时更新一行数据,但是第二个事务却中途失败退出, 导致对数据的两个修改都失效了。

例如:

张三的工资为 5000,事务 A 中获取工资为 5000,事务 B 获取工资为 5000,汇入 100,并提交数据库,工资变为 5100;

与此同时,事务B正在读取张三的工资,读取到张三的工资为8000。随后,事务A发生异常,回滚了事务,张三的工资又回滚为5000。最后,事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读。
脏读

脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

例如:

张三的工资为 5000,事务 A 中把他的工资改为 8000,但事务 A 尚未提交。

与此同时,事务B正在读取张三的工资,读取到张三的工资为8000。随后,事务A发生异常,回滚了事务,张三的工资又回滚为5000。最后,事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读。
不可重复读

是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。

例如:

在事务 A 中,读取到张三的工资为 5000,操作没有完成,事务还没提交。
  与此同时,事务 B 把张三的工资改为 8000,并提交了事务。
  随后,在事务 A 中,再次读取张三的工资,此时工资变为 8000。在一个事务中前后两次读取的结果并不致,导致了不可重复读。

第二类丢失更新

不可重复读的特例。

有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成第一次写操作失效。

例如:

在事务 A 中,读取到张三的存款为 5000,操作没有完成,事务还没提交。
  与此同时,事务 B 存入 1000,把张三的存款改为 6000,并提交了事务。
  随后,在事务 A 中,存储 500,把张三的存款改为 5500,并提交了事务,这样事务 A 的更新覆盖了事务 B 的更新。

幻读

是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

例如:

目前工资为 5000 的员工有 10 人,事务 A 读取到所有的工资为 5000 的人数为 10 人。
  此时,事务 B 插入一条工资也为 5000 的记录。
  这时,事务 A 再次读取工资为 5000 的员工,记录为 11 人。此时产生了幻读。

不可重复读和幻读的区别

不可重复读的重点是修改,同样的条件,你读取过的数据,再次读取出来发现值不一样了

幻读的重点在于新增或者删除,同样的条件,第 1 次和第 2 次读出来的记录数不一样

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/66233.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学英语学压测:02jmeter组件-测试计划和线程组ramp-up参数的作用

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#xff1a;先看关键单词&#xff0c;再看英文&#xff0c;最后看中文总结&#xff0c;再回头看一遍英文原文&#xff0c;效果更佳&#xff01;&#xff01; 关键词 Functional Testing功能测试[ˈfʌŋkʃənəl ˈtɛstɪŋ]Sample样…

多线程访问FFmpegFrameGrabber.start方法阻塞问题

一、背景 项目集成网络摄像头实现直播功能需要用到ffmpeg处理rtmp视频流进行web端播放 通过网上资源找到大神的springboot项目实现了rtmp视频流转为http请求进行视频中转功能&#xff0c;其底层利用javacv的FFmpegFrameGrabber进行拉流、推流&#xff0c;进而实现了视频中转。 …

医学图像分析工具01:FreeSurfer || Recon -all 全流程MRI皮质表面重建

FreeSurfer是什么 FreeSurfer 是一个功能强大的神经影像学分析软件包&#xff0c;广泛用于处理和可视化大脑的横断面和纵向研究数据。该软件由马萨诸塞州总医院的Martinos生物医学成像中心的计算神经影像实验室开发&#xff0c;旨在为神经科学研究人员提供一个高效、精确的数据…

在Microsoft Windows上安装MySQL

MySQL仅适用于Microsoft Windows 64位操作系统&#xff0c;在Microsoft Windows上安装MySQL有不同的方法&#xff1a;MSI、包含您解压缩的所有必要文件的标准二进制版本&#xff08;打包为压缩文件&#xff09;以及自己编译MySQL源文件。 注意&#xff1a;MySQL8.4服务器需要在…

探索最新的编程技术趋势:AI 编程助手和未来的编程方式

随着技术的飞速发展&#xff0c;编程技术领域在近年来经历了深刻的变革。从人工智能到低代码开发工具&#xff0c;新的技术趋势不断涌现&#xff0c;不仅大幅提高了开发效率&#xff0c;也重新定义了开发者的角色和工作方式。本篇博客将探讨几项当前最值得关注的编程技术&#…

k8s集群,CRI-Docker部署条件及方法

CRI-Docker部署条件及方法 文章目录 CRI-Docker部署条件及方法CRI-Docker使用条件安装 cri-docker 的步骤&#xff1a; CRI-Docker使用条件 在 Kubernetes 1.20 及以上版本&#xff0c;kubeadm 默认使用 containerd 作为容器运行时&#xff08;Container Runtime Interface, C…

OKHttp调用第三方接口,响应转string报错okhttp3.internal.http.RealResponseBody@4a3d0218

原因分析 通过OkHttp请求网络&#xff0c;结果请求下来的数据一直无法解析并且报错&#xff0c;因解析时String res response.body().toString() 将toString改为string即可&#xff01;

oceanbase集群访问异常问题处理

1.报错现象 2.问题排查 检查obproxy状态发现为不可用状态 重启obproxy 依次重启Obproxy集群 观察任务状态 重启完成 Obproxy状态正常 3.验证登录 登录成功

如何判断状态:停留还是移动。【计算加速度de方案】

跑步过程中 记录了一天时间的经纬度 时间&#xff0c;如何判断状态&#xff1a;停留还是移动。需要完整的解决方案。精准判断是停留还是移动 邓 要判断在跑步过程中是“停留”还是“移动”&#xff0c;需要根据GPS的经纬度数据以及时间来进行分析。你可以通过以下步骤实现准确…

ruckus R510升级到Unleashe后不能访问

ruckus R510 是IPQ4019&#xff0c;升级到Unleashe&#xff0c;它弹窗提示 但是这个IP没办法用&#xff0c;访问不了AP。 必应了一下&#xff0c;官方提示用advance ip scanner扫描。 扫描持续好久&#xff0c;发现IP竟然是从主路由获得。 9090的端口不用填&#xff0c;甚至不…

使用R语言绘制标准的中国地图和世界地图

在日常的学习和生活中&#xff0c;有时我们常常需要制作带有国界线的地图。这个时候绘制标准的国家地图就显得很重要。目前国家标准地图服务系统向全社会公布的标准中国地图数据&#xff0c;是最权威的地图数据。 今天介绍的R包“ggmapcn”&#xff0c;就是基于最新公布的地图…

影刀RPA高级操作实战(二):数据抓取与数据库写入

在数字化转型的浪潮中&#xff0c;影刀RPA凭借其强大的自动化能力&#xff0c;成为企业提升效率、降低成本的重要工具。掌握影刀RPA的高级操作&#xff0c;能够帮助我们应对更加复杂的业务场景&#xff0c;实现高效的数据处理与系统集成。本文将详细讲解影刀RPA在数据抓取与数据…

【精读电影】至暗时刻

Order! Order! 肃静&#xff01; Mr. Speaker&#xff01; Mr. Speaker! 议长先生&#xff01; 议长先生&#xff01; The leader of the Opposition, Clement Attle. 请工党领袖 克莱门特艾德礼 发言。 Mr. Speaker&#xff01; 议长先生&#xff01; It seem that I have not…

linux上安装MySQL教程

1.准备好MySQL压缩包&#xff0c;并进行解压 tar -xvf mysql-5.7.28-1.el7.x86_64.rpm-bundle.tar -C /usr/local 2.检查是否有mariadb数据库 rpm -aq|grep mariadb 关于mariadb:是MySQL的一个分支&#xff0c;主要由开源社区在维护&#xff0c;采用GPL授权许可 MariaDB的目…

Qt仿音乐播放器:客户端唯一化

一、铺垫 1.我们采用共享内存来进行客户端的唯一化&#xff1b; 2.我刚看到的时候&#xff0c;就感觉&#xff0c;这是人想出来的吗&#xff1f;太绝了 二、实例 int main(int argc, char *argv[]) {QApplication a(argc, argv);QSharedMemory shareMemory("Widget&qu…

Linux系统自动化sh脚本

Linux系统自动化sh脚本 前言功能优点步骤示例 前言 Linux系统中&#xff0c;可以编写自动化sh脚本&#xff0c;并在终端中自动加载。可用来简化复杂命令或创建专属命令&#xff0c;提升工作效率。 功能 init_workspace&#xff1a;可以识别Host和Docker&#xff0c;初始化工…

计算机网络基础(7)中科大郑铨老师笔记

应用层 目标&#xff1a;  网络应用的 原理&#xff1a;网络应用协议的概念和实现方面 传输层的服务模型 客户-服务器模式 对等模式(peerto-peer) 内容分发网络  网络应用的 实例&#xff1a;互联网流行的应用层协 议  HTTP  FTP  SMTP / POP3 / IMAP  DNS…

Spring源码分析之事件机制——观察者模式(二)

目录 获取监听器的入口方法 实际检索监听器的核心方法 监听器类型检查方法 监听器的注册过程 监听器的存储结构 过程总结 Spring源码分析之事件机制——观察者模式&#xff08;一&#xff09;-CSDN博客 Spring源码分析之事件机制——观察者模式&#xff08;二&#xff…

CSS——4. 行内样式和内部样式(即CSS引入方式)

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>方法1&#xff1a;行内样式</title></head><body><!--css引入方式&#xff1a;--><!--css的引入的第一种方法叫&#xff1a;行内样式将css代码写…

python之移动端测试---appium

Appium Appium介绍环境准备新版本appium的用法介绍元素定位函数被封装&#xff0c;统一使用By.xxx(定位方式)&#xff1a;通过文本定位的写法 一个简单的请求示例APP操作api基础apk安装卸载发送&#xff0c;拉取文件uiautomatorviewer工具使用获取页面元素及属性模拟事件操作模…