JDBC- SQL执行超时时间

 java jdbc 的Statement 接口中定义了setQueryTimeout 方法,该方法API:

void setQueryTimeout(int seconds)
                     throws SQLException
将驱动程序等待 Statement 对象执行的秒数设置为给定秒数。如果超过该限制,则抛出 SQLException。
JDBC 驱动程序必须将此限制应用于  execute、executeQuery 和 executeUpdate 方法。
JDBC 驱动程序实现也可以将此限制应用于 ResultSet 方法
(有关详细信息,请参考驱动程序供应商文档)。
参数:
seconds - 以秒为单位的查询超时限制;0 表示没有任何限制
抛出:
SQLException - 如果发生数据库访问错误,在已关闭的 Statement 上调用此方法,或者不满足条件 seconds >= 0
另请参见:
getQueryTimeout()

  即如果数据库jdbc驱动支持情况下,可实现超时异常,这对于某些情况特别有用:

      1. sql执行时间特别长,导至执行线程长时间阻塞,减低请求处理的吞吐量。

      2. sql执行产生死锁,或等待另外的连接释放锁,而一直阻塞。

       

 MyBatis设置setQueryTimeout的方式:

   

  1.mybatis配置的xml中配置:

   

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!--设置SQL执行超时时间,超时抛出异常-->
        <setting name="defaultStatementTimeout" value="30"/>
    </settings>
</configuration>

  2.在sql配置的xml中配置timeout,优先级高于1

 

 <update id="updateName" timeout="20">
        update my_table set name=#{param1} where  id= #{param2}
    </update>

 

 MyBatis 在哪块调用Statement.setQueryTimeout方法??

  

public abstract class BaseStatementHandler implements StatementHandler {
 @Override
  public Statement prepare(Connection connection) throws SQLException {
    ErrorContext.instance().sql(boundSql.getSql());
    Statement statement = null;
    try {
      statement = instantiateStatement(connection);
      setStatementTimeout(statement);//设置sql执行超时时间
      setFetchSize(statement);
      return statement;
    } catch (SQLException e) {
      closeStatement(statement);
      throw e;
    } catch (Exception e) {
      closeStatement(statement);
      throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
    }
  }
   protected void setStatementTimeout(Statement stmt) throws SQLException {
    Integer timeout = mappedStatement.getTimeout();
    Integer defaultTimeout = configuration.getDefaultStatementTimeout();
    if (timeout != null) {
	// 如果配置的SQL中设置了timeout ?
	// 如:
	// <update id="updateName" timeout="20">
       //    update test_user set name=#{param1} where  id= #{param2}
       //  </update>
      //
      stmt.setQueryTimeout(timeout);
    } else if (defaultTimeout != null) {
	//如果设置了全局的超时时间
	//如在mybatis 的xml配置文件中Settings 下设置了:
       // <setting name="defaultStatementTimeout" value="20"/>
      stmt.setQueryTimeout(defaultTimeout);
    }
  }
  
}

 如果jdbc驱动支持,则超时会抛出异常。

  经测:PostgreSQL 9.5  支持。

  示例异常:

   

Caused by: org.postgresql.util.PSQLException: ERROR: canceling statement due to user request
  在位置:while updating tuple (0,12) in relation "my_table"
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:570)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:420)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:413)
	at com.alibaba.druid.pool.DruidPooledPreparedStatement.execute(DruidPooledPreparedStatement.java:493)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:45)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:73)
	at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49)
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:115)
	at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:75)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:170)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:386)

猜你喜欢

转载自java12345678.iteye.com/blog/2373592
今日推荐