springboot mybatis-plus数据库超时配置

这篇具有很好参考价值的文章主要介绍了springboot mybatis-plus数据库超时配置。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

mybatis-plus全局控制

mybatis-plus:
  configuration:
    # 单个SQL执行超时时间(含insert,delete,select),一般应用不宜过长,单位秒
    default-statement-timeout: 30

  • 超时异常
### Cause: com.mysql.cj.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client request
; Statement cancelled due to timeout or client request; nested exception is com.mysql.cj.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client request
	at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:76)
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
	at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:91)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:441)
	at com.sun.proxy.$Proxy133.selectList(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224)

mybatis单个SQL控制

  • 写XML 写法,单位秒

<insert  
  id="insert"  
  parameterType="com.test.abc.Person"  
  ...

  timeout="30">
...
</insert>
  • Mapper类写法,单位秒
@Mapper
public interface DemoMapper extends BaseMapper<Demo> {

    @Select("SELECT * FROM DEMO")
    @Options(timeout = 30) // 设置超时时间为 30 秒
    List<Demo> select();
}

  • 超时异常
同上(略)

spring事务超时控制

  • 整个事务的超时时间,单位是秒。
  • 它的原理大致是事务启动时,事务上下文会计算一个到期时间deadLine(当前时间+超时时间),当mybatis -> prepareStatement时,会调用 SpringManagedTransaction 的getTimeOut,该方法会计算事务剩余时间timeToLiveInSeconds(deadLine-System.currentTimeMillis()),如果timeToLiveInSeconds小于0则报错TransactionTimedOutException,大于0根据情况设置为statement 的queryTimeOut (参照下文的源码分析)

情况1:事务剩余时间 timeToLiveInSeconds小于 statement 本身的 queryTimeOut,则 statement 的 setQueryTimeout 设置为 timeToLiveInSeconds

情况2: 事务剩余时间 timeToLiveInSeconds大于 statement 本身的 queryTimeOut,则 statement 的 setQueryTimeout 设置为 queryTimeOut

@Transactional(timeout = 15)
public int test(){
	demoMapper.select();

	demoMapper.insert(...);
	
	// 其他数据库操作
}

根据它的原理及测试,可能会出现以下两种异常。

  • 事务超时异常: TransactionTimedOutException
org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was Thu Dec 14 16:06:47 CST 2023
	at org.springframework.transaction.support.ResourceHolderSupport.checkTransactionTimeout(ResourceHolderSupport.java:155)
	at org.springframework.transaction.support.ResourceHolderSupport.getTimeToLiveInMillis(ResourceHolderSupport.java:144)
	at org.springframework.transaction.support.ResourceHolderSupport.getTimeToLiveInSeconds(ResourceHolderSupport.java:128)
	at org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout(SpringManagedTransaction.java:125)
	at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:87)
	at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:62)

  • statement执行超时异常: MySQLTimeoutException
com.mysql.cj.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client request
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:113)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:955)
	at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:372)
	at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59)
	at com.sun.proxy.$Proxy197.execute(Unknown Source)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:64)

JDBC也可以配置socket超时时间

  • 配置socketTimeout 单位毫秒,一般不推荐配这个
jdbc:mysql://localhost:3066/testdb?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
&socketTimeout=60000

总结

mybatis 执行SQL超时,底层也是用了 Jdbc 的 Statment 的 setQueryTimeout

mybatis设置超时源码(spring5.2.15+mybatis3.5.9)

BaseStatementHandler.java

public abstract class BaseStatementHandler implements StatementHandler {
  protected void setStatementTimeout(Statement stmt, Integer transactionTimeout) throws SQLException {
    Integer queryTimeout = null;
    if (mappedStatement.getTimeout() != null) {
      queryTimeout = mappedStatement.getTimeout();
    } else if (configuration.getDefaultStatementTimeout() != null) {
      queryTimeout = configuration.getDefaultStatementTimeout();
    }
    if (queryTimeout != null) {
      stmt.setQueryTimeout(queryTimeout);
    }
    StatementUtil.applyTransactionTimeout(stmt, queryTimeout, transactionTimeout);
  }

StatementUtil.java文章来源地址https://www.toymoban.com/news/detail-773333.html

public class StatementUtil {

  private StatementUtil() {
    // NOP
  }

  /**
   * Apply a transaction timeout.
   * <p>
   * Update a query timeout to apply a transaction timeout.
   * </p>
   * @param statement a target statement
   * @param queryTimeout a query timeout
   * @param transactionTimeout a transaction timeout
   * @throws SQLException if a database access error occurs, this method is called on a closed <code>Statement</code>
   */
  public static void applyTransactionTimeout(Statement statement, Integer queryTimeout, Integer transactionTimeout) throws SQLException {
    if (transactionTimeout == null) {
      return;
    }
    // 事务剩余时间小于 statement自己的queryTimeout,就用事务的剩余时间,所以在事务里面statement的超时时间是动态的。
    if (queryTimeout == null || queryTimeout == 0 || transactionTimeout < queryTimeout) {
      statement.setQueryTimeout(transactionTimeout);
    }
  }

}

jdbc 测试代码


try (Connection connection = dataSource.getConnection()) {
            // 创建 Statement 对象
            Statement statement = connection.createStatement();

            // 设置查询超时时间为 10 秒
            int timeoutInSeconds = 10;
            statement.setQueryTimeout(timeoutInSeconds);

            // 执行查询
            String sqlQuery = "SELECT sleep(12)";
            ResultSet resultSet = statement.executeQuery(sqlQuery);

            // 处理结果集
            while (resultSet.next()) {
                // 处理每一行数据
            }

            resultSet.close();
            statement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

到了这里,关于springboot mybatis-plus数据库超时配置的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MyBatis-plus中的两种快捷操作数据库方式:1、mapper调用 2、ActiveRecord方式(简称AR) 二者的使用和区别介绍

            在使用MyBatis操作数据库时,需要频繁的写mapper层dao接口以及对应的配置文件和SQL语句,当功能方法繁杂,业务逻辑不复杂的时候,我们可以使用MyBatis的升级版MyBatis-Plus来代替我们写这些繁琐的配置文件和简单的SQL。 (1)书写或使用MP生成数据库表对应的实体类。

    2024年02月07日
    浏览(61)
  • Springboot 配置动态多数据源(Mybatis-plus)

    前言:在项目中需要用到动态切换多数据源,查阅Mybatis-plus文档得知可以通过@DS注解,但该方法主要针对不同内容的数据源,而目前场景是相同内容的数据库需要在运行时根据请求头动态切换,因此文档方法不适用。 注意,不要使用dynamic-datasource-spring-boot-starter依赖包。 应用

    2024年02月12日
    浏览(40)
  • grpc + springboot + mybatis-plus 动态配置数据源

    前言 这是我在这个网站整理的笔记,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 1.1 项目初始化 项目初始化的时候会调用com.baomidou.dynamic.datasource.DynamicRoutingDataSource对象的addDataSource方法添加数据源,数据源存进dataSourceMap中。 1.2 接口请求时候 进行数据操作时,

    2024年02月09日
    浏览(39)
  • SpringBoot整合Mybatis-Plus+Druid实现多数据源

    🌺本文主要讲解 springboot +mybatisplus + druid 实现多数据源配置功能 🌺 主页传送门:📀 传送 Spring Boot:    Spring Boot是一个基于Spring框架的开源Java开发框架,旨在简化Spring应用程序的开发、配置和部署。它提供了一种快速、敏捷的方式来构建独立的、生产级别的Spring应用程

    2024年02月09日
    浏览(102)
  • SpringBoot整合Mybatis-Plus、Druid配置多数据源

    目录 1.初始化项目 1.1.初始化工程 1.2.添加依赖 1.3.配置yml文件 1.4.Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹 1.5.配置使用数据源 1.5.1.注解方式 1.5.2.基于AOP手动实现多数据源原生的方式 2.结果展示 Mybatis-Plus:简介 | MyBatis-Plus (baomidou.com) 在正式开始之前,先初始

    2024年02月11日
    浏览(45)
  • 【SpringBoot 3.x】整合Mybatis-Plus多数据源、Druid

    开发依赖 版本 Spring Boot 3.0.6 Mybatis-Plus 3.5.3.1 dynamic-datasource-spring-boot-starter 3.6.1 JDK 20 SpringBoot启动类修改 由于排除了DruidDataSourceAutoConfigure类的自动装载,就需要手工指定装配以下几个类 查看DruidDataSourceAutoConfigure这个类的源码可以看出,需要把@Import带进来的几个类进行自动装

    2024年02月04日
    浏览(47)
  • springBoot + mybatis-plus 实现监听 mysql的数据增删改的监听

    在Spring Boot + MyBatis-Plus中实现MySQL数据增删改的监听,可以通过以下步骤: 1. 添加MyBatis-Plus依赖,在pom.xml文件中添加以下依赖:   2. 配置MyBatis-Plus,通常在application.yml文件中进行配置: 3. 创建监听器类,实现com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor接口。  4. 在My

    2024年02月15日
    浏览(114)
  • SpringBoot+MyBatis-Plus多数据源@DS注解失效的解决方法

    引入 dynamic-datasource: application.yml 数据源配置: 详细使用请看 MyBatis-Plus官网 这种场景还是比较常见,比如在一个为master数据源的调用slave数据源就会失效 slave数据源Service方法 mater数据源Service方法调用slave数据源Service方法 这里会出现没有走slave_1,依然还是master数据源 需要在

    2024年01月18日
    浏览(50)
  • Springboot+mybatis-plus+dynamic-datasource+Druid 多数据源 分布式事务

    背景 处理多数据源事务一直是一个复杂而棘手的问题,通常我们有两种主流的解决方法。 第一种是通过Atomikos手动创建多数据源事务,这种方法更适合数据源数量较少,参数配置不复杂,对性能要求不高的项目。然而,这种方法的最大困难在于需要手动配置大量设置,这可能

    2024年02月11日
    浏览(36)
  • MyBatis Plus 数据库字段加密处理

    当项目开发到一半,可能突然客户会要求对数据库里面比如手机号、身份证号的字段进行加密; 在保证开发最快、影响范围最小的情况下,我们需要选择一种介于数据库和代码之间的工具来帮我们实现自动加解密; 这里我们选用AES对称加密算法,因为它是可逆算法。 AES加密

    2024年02月07日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包