【问题标题】:Spring managed transaction does not commit some statementsSpring托管事务不提交某些语句
【发布时间】:2014-03-13 14:31:34
【问题描述】:

原则上我或多或少有以下代码

@Component
public class SomeService {
  @Autowired
  private SettingsService settingsService;

  @Autowired
  private OtherService otherService;

  @Transactional
  public void storeData(Data d) {
    settingsService.set("setting1", d.getSetting1());
    settingsService.set("setting2", d.getSetting2());
    settingsService.set("setting3", d.getSetting3()); // no effect

    // do something with otherService
  }

  @Transactional
  public void storeData2(Data d) {
    settingsService.set("setting1", d.getSetting1());
    settingsService.set("setting3", d.getSetting3());
    settingsService.set("setting2", d.getSetting2()); // no effect

    // do something with otherService
  }

  @Transactional
  public void storeData3(Data d) {
    settingsService.set("setting1", d.getSetting1());
    settingsService.set("setting2", d.getSetting2()); // no effect
    // settingsService.set("setting3", d.getSetting3());

    // do something with otherService
  }

  @Transactional
  public void storeData4(Data d) {
    settingsService.set("setting1", d.getSetting1());
    settingsService.set("setting2", d.getSetting2());
    settingsService.set("setting3", d.getSetting3());
    settingsService.set("setting3", "doesn't matter"); // works but hacky

    // do something with otherService
  }

  // @Transactional
  public void storeData5(Data d) {
    settingsService.set("setting1", d.getSetting1());
    settingsService.set("setting2", d.getSetting2());
    settingsService.set("setting3", d.getSetting3()); // works but no TX :(

    // calls to otherService go boom because there is no TX
  }
}

在主配置中通过简单的@EnableTransactionManagement 启用事务管理。

SettingsServiceOtherService 都将一些内容存储在同一个关系数据库中。

现在,当我调用一些 storeData 方法时,始终是对 settingsService 的最后一次调用没有效果,即更改不会保留在数据库中(请参阅 storeDatastoreData2storeData3)。如果我执行最后一行两次(或尝试保留一些虚假数据),一切正常,但这显然是一个 hack (storeData4)。

奇怪的是,在所有情况下,对OtherService 的调用都可以正常保存所有内容。

SettingServiceset方法可以用@Transactional注解,也可以不注解;所描述的错误行为不会改变。只有当我从SomeServicestoreData 方法中删除@Transactional 时,所有对settingsService 的调用才会生效(storeData5)。但是我真的很想要那个交易(我需要它来处理otherService)。

所以上面的行为表明服务调用原则上工作,但不是同时工作。我调试了所有东西,所有变量都设置为正确的值。我不知道这种行为的原因可能是什么以及如何进一步调试它。

【问题讨论】:

    标签: java spring transactions spring-transactions


    【解决方案1】:

    在我意识到运行时发现的 @Transactional 注释的作用域之前,我有类似的事务损失(尽管不相同)。

    长话短说:将@Transactional 注释推广给您的呼叫客户。这可以防止发生在我们的测试环境中导致随机混乱的多个事务。

    所以在你的情况下,无论调用你的服务方法,添加@Transactional 到它。不保证它会解决您的特定问题,但它确实对我们有用。

    【讨论】:

    • 如果您认为SomeServiceSettingsService 的调用客户端怎么办? SomeService 可以说是在服务层的“外边缘”。我无法合理地将声明的交易移到更远的地方。
    • 服务参与交易。它们不会开始或结束它们。开始和结束事务的责任是控制器(也称为交互器)的责任。控制器调用服务(这可能反过来根据需要调用服务)并通过调用它们的方法来改变对象。数据从数据库中提取,更改,然后写回。事务从控制器开始,在控制器完成,而不是在服务内。
    • These Answers 和其他人似乎不同意。无论如何,交易必须有效,无论我从哪里开始交易。我不想避免这个问题(我已经有一个解决方法),我想解决它。也许这只是其他问题的症状。我只是不知道它可能是什么。
    猜你喜欢
    • 2014-09-20
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-28
    • 2017-03-26
    相关资源
    最近更新 更多