这篇日志有三个目的
1.回顾编程式事务
2.回顾mybatis
3.测试事务的超时时间设置是否能起到作用
首先祭上pom.xml,里面所有的依赖都是必须的,所有用不到的依赖我都干掉了
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wangx.demo</groupId> <artifactId>mybatis-transaction</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>mybatis-transaction</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.3.9.RELEASE</spring.version> </properties> <dependencies> <!-- ojdbc --> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc7</artifactId> <version>12.1.0.2</version> </dependency> <!-- 线程池 --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <!-- logback需要的一套依赖 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.3</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.2</version> </dependency> <!-- spring基本支持 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- spring-jdbc,对事务等东东提供了支持 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5</version> <configuration> <!-- 指定source和target的版本 --> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
只需要一个类就搞定,显然我没有在事务里做任何操作,因为这个不是重点。重点是我sleep了50秒,而我TransactionTemplate 的超时时间明明设置的是5秒,为毛没有超时呢
package com.demo.transaction.program; import java.util.concurrent.TimeUnit; import org.apache.commons.dbcp.BasicDataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.AbstractPlatformTransactionManager; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; public class Main { private static Logger logger = LoggerFactory.getLogger(Main.class); public static void main(String[] args) { new Main().writeSysparam(); } public void writeSysparam() { logger.debug("进入writeSysparam()方法"); TransactionTemplate template = new TransactionTemplate(); template.setTransactionManager(getTrasationManager()); template.setTimeout(5); template.execute(new TransactionCallback<Object>() { @Override public Object doInTransaction(TransactionStatus status) { try { TimeUnit.SECONDS.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } return null; } }); } public AbstractPlatformTransactionManager getTrasationManager() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("oracle.jdbc.OracleDriver"); dataSource.setUrl("jdbc:oracle:thin:@localhost:1521/OPENBANKCOREDB"); dataSource.setUsername("coredb"); dataSource.setPassword("coredb"); DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSource); return transactionManager; } }
关于对于事务超时时间的解释,有一片文章写得很好:http://jinnianshilongnian.iteye.com/blog/1986023
然后我们自己来梳理一下:
TransactionTemplate类继承自DefaultTransactionDefinition
template.setTimeout(5) 往里看是 this.timeout = 5;
那么这个timeout在哪里会用到呢,根据上面那篇博文的指引,是在
template.execute(...
---> this.transactionManager.getTransaction(this) (TransactionTemplate类)
---> doBegin(transaction, definition); (抽象类AbstractPlatformTransactionManager或者说DataSourceTransactionManager类的实例)
在DataSourceTransactionManager中doBegin的实现中,有如下一段代码
int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); }
其中determineTimeout(definition)就是从definition中取出timeout