【问题标题】:Can't get Spring transaction to rollback (java+mysql)无法让 Spring 事务回滚(java+mysql)
【发布时间】:2011-09-19 02:15:23
【问题描述】:

上周我终于开始让我的应用使用交易。我正在使用 Spring 声明性事务,并且我知道事务本身正在工作,因为它使具有数千个插入的东西在一个事务中从 5-10 分钟缩短到 5-10 秒。数据库是 MySQL,所有的表都是 InnoDB。所以我想让这个功能在它不起作用时回滚。基本上,它是导入一个 xml 文件并从 xml 构建数据库表。因此,如果出现故障,我不希望部分上传,否则会不一致。我一直在严格遵循 Spring 文档,并且由于我确实让事务运行,我猜一般配置是正确的。

这是 .xml 文件的相关部分:

<tx:advice id="txAdvice" transaction-manager="txManager">
  <tx:attributes>
    <tx:method name="get*" read-only="true"/>
    <tx:method name="uploadModelToProject" rollback-for="Throwable"/>
    <tx:method name="*"/>
  </tx:attributes>
</tx:advice>

这是服务的相关部分:

public interface ModelService {
    // interface to upload an LSI XML file of the  model into a project
    public Model uploadModelToProject(Project proj, String xmlFile);
}

uploadModelToProject 调用 SAX Parser 实现中的一个方法,然后实现解析

public Model importModelToProject(Project proj, String xmlInputFileName) throws SAXException, IOException, ParserConfigurationException, ImportException {

    //get a factory
    SAXParserFactory spf = SAXParserFactory.newInstance();
    try {

        //get a new instance of parser 
        SAXParser sp = spf.newSAXParser();          

        //parse the file and also register this object for callbacks
        sp.parse(xmlInputFileName, this);                               

    } finally {
        newModel = null;
    }

    return newModel;

}

我尝试过使用 rollback-for="Throwable"、rollback-for="Exception"、rollback-for="ImportException"(我自己的异常)。然后我在代码中手动抛出了一个异常,它没有工作。我不知道我是否需要一些传播参数或其他设置。似乎我没有遗漏任何明显的东西。有人有什么建议吗?所发生的一切都是抛出一个异常,一切仍然进入数据库。我错过了一个明显的步骤吗?

感谢您的帮助。

【问题讨论】:

  • 我意识到我从实际运行的代码中修改了这段代码以删除一些专有的东西,所以 finally 语句是不正确的,但它确实有效。

标签: java mysql spring transactions


【解决方案1】:

我没有得到任何建议,但我终于想通了,所以我想我会发布答案,以防其他人试图找出回滚的东西。我打开了 commons/log4j 日志的调试级别,所以我可以看到 Spring 框架中发生的一切。丰富的输出,但很有用。

原来我缺少的是了解 Spring 框架在哪里拦截和捕获配置中的异常,以便启动回滚。

我的第一组代码,在我处理事务之前,我正在从 XML 解析中捕获异常,并返回一个空指针供调用者处理。我没有考虑 Spring 将在哪里处理异常,所以我没有想到如果我捕获异常并且不重新抛出,那么 Spring 不知道。我的下一个尝试是传递所有异常但没有在任何地方处理它,错误地认为 Spring 是神奇的。好消息是事务被回滚,坏消息是向用户返回了错误页面。

所以我的“啊哈!”那一刻我意识到配置中指定的方法(即服务中的方法)必须是引发异常的方法。是的,在意识到这一点之后,这似乎很明显,但我经历了这个才弄清楚。因此,在我的示例中,“uploadModelToProject”方法需要在获得异常后重新抛出异常,而服务中该方法的调用者需要处理异常,这将在 Spring 拦截它并执行回滚之后立即发生。

另外,我没有让我的 XML 导入器中的低级函数抛出所有这些不同类型的异常,而是创建了自己的“ImportException”,捕获了异常,然后向上抛出 ImportException。

希望这对某人有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 2016-09-19
    • 2017-03-03
    • 2012-03-10
    相关资源
    最近更新 更多