我有一個連接到多個數據庫的應用程序。一切正常,直到我試圖將Spring Transaction Management添加到其中一個數據庫連接。Spring管理事務處理結果爲關閉連接
自從我向服務方法添加@Transactional註釋以來,數據庫連接將爲第一個託管事務正常工作。但是,在事務完成後,它看起來像實際的數據庫連接關閉,但邏輯連接對象認爲連接仍處於打開狀態。結果是使用該連接的任何後續數據庫調用都會失敗,並顯示「Closed Connection」錯誤。
換一種方式,這些場景的所有工作:
- 讀或寫操作的任何序列不@Transactional
- 的@Transactional流程,第一時間
- 完全相同的流程,除了刪除@Transactional屬性,重複任意次數
該問題僅在應用程序使用@Transactional批註運行方法後纔會出現。如果事務成功提交或回滾,則無關緊要。
請參閱下面的詳細類和日誌和東西。他們因爲SO而被匿名,所以任何錯別字都只是拼寫錯誤。
我第一次打到數據庫時,一切正常。這是我在日誌中看到:
DEBUG 26 Sep 2016 13:15:00,659() interceptor.RestServiceLoggingInterceptor preHandle 48 - Received request at path /service/trial/tmr/submit:
DEBUG 26 Sep 2016 13:15:01,259() datasource.DataSourceTransactionManager getTransaction 367 - Creating new transaction with name [com.example.service.shipping.createShipment]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; 'shippingTxManager',-java.lang.Exception
DEBUG 26 Sep 2016 13:15:01,260() datasource.DataSourceTransactionManager doBegin 206 - Acquired Connection [ConnectionHandle{url=jdbc:oracle:thin:@//example.com:1535/SCHEMA, user=user, debugHandle=null, lastResetAgoInSec=94, lastUsedAgoInSec=94, creationTimeAgoInSec=94}] for JDBC transaction
DEBUG 26 Sep 2016 13:15:01,265() datasource.DataSourceTransactionManager doBegin 223 - Switching JDBC Connection [ConnectionHandle{url=jdbc:oracle:thin:@//example.com:1535/SCHEMA, user=user, debugHandle=null, lastResetAgoInSec=94, lastUsedAgoInSec=94, creationTimeAgoInSec=94}] to manual commit
DEBUG 26 Sep 2016 13:15:01,268() transaction.SpringManagedTransaction openConnection 86 - JDBC Connection [ConnectionHandle{url=jdbc:oracle:thin:@//example.com:1535/SCHEMA, user=user, debugHandle=null, lastResetAgoInSec=94, lastUsedAgoInSec=94, creationTimeAgoInSec=94}] will be managed by Spring
<snip a bunch of select, insert, and update statements>
DEBUG 26 Sep 2016 13:15:02,223() datasource.DataSourceTransactionManager processCommit 759 - Initiating transaction commit
DEBUG 26 Sep 2016 13:15:02,223() datasource.DataSourceTransactionManager doCommit 269 - Committing JDBC transaction on Connection [ConnectionHandle{url=jdbc:oracle:thin:@//example.com:1535/SCHEMA, user=user, debugHandle=null, lastResetAgoInSec=95, lastUsedAgoInSec=95, creationTimeAgoInSec=95}]
DEBUG 26 Sep 2016 13:15:02,271() datasource.DataSourceTransactionManager doCleanupAfterCompletion 327 - Releasing JDBC Connection [ConnectionHandle{url=jdbc:oracle:thin:@//example.com:1535/SCHEMA, user=user, debugHandle=null, lastResetAgoInSec=95, lastUsedAgoInSec=95, creationTimeAgoInSec=95}] after transaction
DEBUG 26 Sep 2016 13:15:02,271() datasource.DataSourceUtils doReleaseConnection 327 - Returning JDBC Connection to DataSource
這是我在日誌中看到後續的嘗試:
DEBUG 26 Sep 2016 13:23:38,235() datasource.DataSourceTransactionManager getTransaction 367 - Creating new transaction with name [com.example.service.shipping.createShipment]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; 'shippingTxManager',-java.lang.Exception
DEBUG 26 Sep 2016 13:23:38,236() datasource.DataSourceTransactionManager doBegin 206 - Acquired Connection [ConnectionHandle{url=jdbc:oracle:thin:@//example.com:1535/SCHEMA, user=user, debugHandle=null, lastResetAgoInSec=1, lastUsedAgoInSec=602, creationTimeAgoInSec=612}] for JDBC transaction
DEBUG 26 Sep 2016 13:23:38,236() datasource.DataSourceTransactionManager doBegin 223 - Switching JDBC Connection [ConnectionHandle{url=jdbc:oracle:thin:@//example.com:1535/SCHEMA, user=user, debugHandle=null, lastResetAgoInSec=1, lastUsedAgoInSec=602, creationTimeAgoInSec=612}] to manual commit
DEBUG 26 Sep 2016 13:23:38,236() ShippingMapper.getShipmentInfo debug 142 - ==> Preparing: select * from shipments where shipment_id = ?
DEBUG 26 Sep 2016 13:23:38,271() datasource.DataSourceTransactionManager processRollback 851 - Initiating transaction rollback
DEBUG 26 Sep 2016 13:23:38,272() datasource.DataSourceTransactionManager doRollback 284 - Rolling back JDBC transaction on Connection [ConnectionHandle{url=jdbc:oracle:thin:@//example.com:1535/SCHEMA, user=user, debugHandle=null, lastResetAgoInSec=1, lastUsedAgoInSec=602, creationTimeAgoInSec=612}]
DEBUG 26 Sep 2016 13:23:38,316() datasource.DataSourceTransactionManager doCleanupAfterCompletion 327 - Releasing JDBC Connection [ConnectionHandle{url=jdbc:oracle:thin:@//example.com:1535/SCHEMA, user=user, debugHandle=null, lastResetAgoInSec=1, lastUsedAgoInSec=602, creationTimeAgoInSec=612}] after transaction
DEBUG 26 Sep 2016 13:23:38,317() datasource.DataSourceUtils doReleaseConnection 327 - Returning JDBC Connection to DataSource
ERROR 26 Sep 2016 13:23:38,318() impl.IntegrationServiceImpl submitTmr 235 - error:
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.sql.SQLException: Connection is closed!
以下是有關的類。我省略了一些東西,包括控制器,模型類,mybatis映射器和其他數據庫的配置。
配置
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean(name = "shippingDataSource")
public DataSource shippingDataSource() {
BoneCPDataSource dataSource = new BoneCPDataSource();
dataSource.setDriverClass("oracle.jdbc.OracleDriver");
dataSource.setJdbcUrl("jdbc:oracle:thin:@//example.com:1535/SCHEMA");
dataSource.setUsername("user");
dataSource.setPassword("pass");
return dataSource;
}
@Bean(name = "shippingTxManager")
public PlatformTransactionManager TxManager(){
return new DataSourceTransactionManager(shippingDataSource());
}
@Bean(name = "shippingSqlSessionFactoryBean")
public SqlSessionFactoryBean shippingSqlSessionFactoryBean() {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(shippingDataSource());
bean.setTypeAliasesPackage("com.example.shipping.model");
bean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
return bean;
}
@Bean(name = "shippingSqlSession")
public SqlSession shippingSqlSession() throws Exception {
return shippingSqlSessionFactoryBean().getObject().openSession();
}
}
服務層
@Service("shippingService")
// Remove the "Transactional" annotation and everything else works.
@Transactional(rollbackFor=ShippingException.class, transactionManager = "shippingTxManager")
public class ShippingService {
@Autowired
ShippingDao dao;
// If any packages are not inserted successfully, throw an exception
// and roll back the whole shipment.
public void CreateShipment(Shipment shipment){
try {
dao.insertShipment(shipment);
for(Package package : shipment.getPackages()) {
dao.insertPackage(package);
}
} catch (Exception e) {
throw new ShippingException(e);
}
}
}
數據層
@Repository
public class ShippingDao {
@Autowired
@Qualifier("shippingSqlSession")
private SqlSession session;
public int insertShipment(Shipment shipment){
return session.insert("insertShipment", shipment);
}
public int insertPackage(Package package){
return session.insert("insertPackage", package);
}
}
的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>
<artifactId>example</artifactId>
<groupId>com.example</groupId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.2.4.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp</artifactId>
<version>0.8.0.RELEASE</version>
</dependency>
</dependencies>
</project>
移除'shippingSqlSession' ..''SqlSessionFactoryBean'負責處理這個問題。您現在打開一個會話,在第一個事務後關閉。或者按照[文檔](http://www.mybatis.org/spring/sqlsession.html) –
中的說明使用'SqlSessionTemplate',這就是修復。如果你想發佈這個答案,我可以相信你。謝謝。 – aug