Spring事务超时到底是怎么回事?( 二 )

执行结果:
耗时:3024毫秒14:14:38.257 [main] DEBUG o.s.jdbc.core.JdbcTemplate - Executing SQL statement [select 1]Exception in thread "main" org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was Wed Oct 11 14:14:37 CST 2023at org.springframework.transaction.support.ResourceHolderSupport.checkTransactionTimeout(ResourceHolderSupport.java:155)第一个数据库操作,没有抛出异常,直到第二个执行时抛出了异常 。
总结:      事务方法开始执行时就开始计时,在执行到数据库操作时判断当前的执行时间点是否已经超过了设置的超时时间 , 如果是则抛出Timeout异常 。
4. 事务超时原理在开始一个事务时会在DataSourceTransactionManager#doBegin方法中设置超时时间
protected void doBegin(Object transaction, TransactionDefinition definition) {int timeout = determ.NETimeout(definition);if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {// 如果注解@Transactional中设置了timeout,则设置超时时间txObject.getConnectionHolder().setTimeoutInSeconds(timeout);}}protected int determineTimeout(TransactionDefinition definition) {if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) {return definition.getTimeout();}return getDefaultTimeout();}当通过JdbcTemplate操作数据库时,还会执行如下操作
public class JdbcTemplate {private <T> T execute(StatementCallback<T> action, boolean closeResources) {Statement stmt = null;try {stmt = con.createStatement();// 配置Statement对象,这其中会设置超时时间applyStatementSettings(stmt);// ...return result;}}protected void applyStatementSettings(Statement stmt) throws SQLException {// ...// getQueryTimeout方法返回的是当前JdbcTemplate对象中设置d饿超时时间DataSourceUtils.applyTimeout(stmt, getDataSource(), getQueryTimeout());}}DataSourceUtils工具类
public abstract class DataSourceUtils {public static void applyTimeout(Statement stmt, @Nullable DataSource dataSource, int timeout) throws SQLException {ConnectionHolder holder = null;if (dataSource != null) {holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);}// 如果当前事务执行配置了超时时间if (holder != null && holder.hasTimeout()) {// 剩余事务超时将覆盖指定的值 。stmt.setQueryTimeout(holder.getTimeToLiveInSeconds());}else if (timeout >= 0) {// No current transaction timeout -> apply specified value.stmt.setQueryTimeout(timeout);}}}ResourceHolderSupport类
public abstract class ResourceHolderSupport implements ResourceHolder {public int getTimeToLiveInSeconds() {double diff = ((double) getTimeToLiveInMillis()) / 1000;int secs = (int) Math.ceil(diff);// 检查超时时间checkTransactionTimeout(secs <= 0);return secs;}private void checkTransactionTimeout(boolean deadlineReached) throws TransactionTimedOutException {if (deadlineReached) {// 设置事务回滚setRollbackOnly();// 抛出异常throw new TransactionTimedOutException("Transaction timed out: deadline was " + this.deadline);}}}
【Spring事务超时到底是怎么回事?】


推荐阅读