在开始这个看似很长的段落之前,我想对我可能收到的任何建议/建议表示感谢。——朱约翰
我开发了一个简单的测试来帮助我理解 Spring 的声明式 (@Transactional) 事务管理框架如何与 Spring 的 RESTful Web 服务一起工作。
为此,我开发了以下 RESTful 控制器:
@RequestMapping(value="register", method=RequestMethod.POST, produces="application/json", consumes="application/json")
public void accountFacade () {
tester.accountTest();
}
其中“tester”是以下服务类的 bean,并自动装配到此控制器中。类中唯一的方法是事务性的:
@Transactional
public class TransactionTest extends ActivityStatus {
@Autowired
private ObjectManager objectManager;
@Autowired
private GenericDB gdb;
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("META-INF/test- context.xml");
TransactionTest tester = (TransactionTest) ac.getBean("tester");
tester.accountTest();
}
@Transactional(readOnly=false, propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED,
rollbackFor=RuntimeException.class)
public void accountTest () {
try {
String sql = "insert into account set account_id=0, ....";
gdb.jdbcTemplateInsert(sql);
sql = "insert into login set account_id=....";
gdb.jdbcTemplateInsert(sql, values);
} catch (DataAccessException dae) {
System.out.println("Catching DataAccessException (dae)");
throw new RuntimeException (dae);
}
}
在上面,GenericDB 是一个提供自定义 jdbcTemplate 的类。
测试运行是从浏览器调用 accountFacade。我故意设置数据,以便第一个 SQL 成功,第二个 SQL 失败,以触发回滚。
问题:最终结果是一条记录被插入到帐户中,并且仍然存在,即使第二次插入也按预期失败。
几点注意事项:
如果我向两个 SQL 提供正确的数据,测试运行就会成功。
如果我只是将 TransactionTest 作为 Eclipse 中的独立 java 应用程序(请参阅类 defn 中的 main(...) )针对本地数据库运行,则似乎会发生回滚。
执行确实捕获了一个 AccessDataException(请参阅我在“catch”块中的打印语句)。因此,我得出结论,抛出了“new RuntimeException()”。
由于插入失败而导致的错误消息(调用堆栈)确实显示了以下内容:
在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) [spring-tx-3.1.1.RELEASE.jar:3.1.1.RELEASE]
这表明 Spring 的事务拦截器正确地“包装”了方法“accountTest”。这似乎意味着我的配置(见下文)是有效的。
applicationContext.xml 中的相关行:
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="tester" class="org.SandRiver.Controllers.TransactionTest">
</bean>
关于我的执行环境的几句话:我在 OpenShift 的环境中运行了应用程序,其中包括
- 老板6.1
- mysql 5.x(我不知道“x”)。
- 我正在使用 Maven 与 Spring 版本保持同步。