【发布时间】:2017-01-20 16:20:58
【问题描述】:
我正在尝试设置使用 Spring 和 MyBatis 的网络应用程序。
这里是重要的sn-ps代码。
pom.xml 中的 Maven 依赖项:
...
<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>
...
以及Spring bean的配置:
@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注解,那很可能是一个错误。如果在这种情况下抛出异常迫使我修复我的代码而不是静默创建一些事务,那会很好。
请问有办法实现吗?
感谢您的帮助。
【问题讨论】:
-
你的数据库支持事务吗?如您所知,
MYISAM引擎没有。 -
@Forward 是的,我使用的是 Postgres 9.6。
标签: spring mybatis spring-mybatis