我正在嘗試設置使用Spring和MyBatis的Web應用程序。用Spring和MyBatis丟失@Transactional的異常
以下是重要的代碼片段。
Maven依賴於pom.xml
:
...
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1212.jre7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
...
春豆及配置:
@Configuration
@EnableTransactionManagement
public class DatabaseConfiguration {
@Value("classpath:db/mybatis/mybatis-configuration.xml")
private Resource myBatisConfiguration;
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://127.0.0.1:5432/ehdb");
dataSource.setUsername(/*my username*/);
dataSource.setPassword(/*my password*/);
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
final DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource());
transactionManager.setValidateExistingTransaction(true);
return transactionManager;
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean() {
final SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
sqlSessionFactory.setDataSource(dataSource());
sqlSessionFactory.setConfigLocation(myBatisConfiguration);
return sqlSessionFactory;
}
@Bean
public SqlSession sqlSession() throws Exception {
return new SqlSessionTemplate(sqlSessionFactoryBean().getObject());
}
}
這裏是應該調用一些MyBatis的聲明在一個事務性方法的一個服務:
@Service
public class HelloManagerImpl implements HelloManager {
private final HelloDao helloDao;
public HelloManagerImpl(@Autowired final HelloDao helloDao) {
this.helloDao = helloDao;
}
@Override
@Transactional
public String doSomething() {
helloDao.insertRow(); // a row is inserted into DB table via MyBatis; bean sqlSession is autowired in HelloDao
throw new RuntimeException(); // transaction will be rolled back here
}
}
如果我打電話給方法doSomething
,它工作如預期的那樣。由於拋出RuntimeException
,事務回滾,數據庫表中沒有新行出現。
如果我註釋掉throw語句並重復實驗,數據庫表中會出現一個新行。這是預期的行爲。
現在,如果我另外註釋掉@Transactional
註釋並調用doSomething()
,則該方法成功並且將新行插入表中。如果沒有事務存在,似乎MyBatis會自動爲INSERT
語句創建一個事務。
我寧願在最後一種情況下失敗。如果我忘記編寫@Transactional
註釋,那可能是一個錯誤。如果在這種情況下拋出一個異常,迫使我修復我的代碼而不是靜靜地創建一些事務,那就沒問題了。
有沒有辦法實現這個請?
感謝您的幫助。
您的db支持事務嗎?如你所知,'MYISAM'引擎不會。 – Blank
@Forward是的,我使用的是Postgres 9.6。 – Cimlman