【问题标题】:Spring @Transactional concurrencySpring @Transactional 并发
【发布时间】:2010-09-14 11:35:43
【问题描述】:


class MyService {

public void a() { synchronized(somekey) { b(); } }

@Transactional(propagation = Propagation.REQUIRES_NEW) public void b() { ...do DB works... } }

我的目标是

    1 - 获取密钥
    2 - 开始事务
    3 - 提交事务
    4 - 释放钥匙

当我从外部调用 a() 方法时,事务不起作用。

有什么建议吗?

谢谢。

【问题讨论】:

  • “不起作用”是什么样的?异常和错误消息会很有帮助。
  • 没有错误;只是事务没有启动,每个插入操作都直接进入数据库
  • 你是如何配置你的事务管理器的?

标签: java spring transactions concurrency synchronization


【解决方案1】:

除非您使用代码编织,否则这是行不通的。

Spring 处理事务的默认方式是通过AOP proxies。对事务方法的调用如下所示:

 caller --> ProxyClass.a() --> YourClass.a()

如果你在同一个对象上调用另一个方法,你不会通过代理,所以没有事务行为。

 caller --> ProxyClass.a() --> YourClass.a() --> YourClass.b()

如果不想使用AspectJ,可以使用AopContext.currentProxy()获取代理对象。

【讨论】:

    【解决方案2】:

    不是 100% 确定。我认为所有@Transactional 调用都必须在事务开始的同一线程上完成。我确定@Transactional 不能跨线程工作。 (我猜是设计使然)

    【讨论】:

      【解决方案3】:

      我很好奇钥匙的性质。为什么服务会生成它?替代设计不会将其放入数据库吗?

      如果没有错误消息,就很难准确判断出了什么问题。

      【讨论】:

      • 没有错误;只是事务没有启动,每个插入操作都直接进入数据库。
      • 另外数据库可能会根据位置(客户)而改变,所以我只想在Java端解决它。
      【解决方案4】:

      如果你想在a() 内部调用b(),并且你想让b() 具有事务性,你必须把它放到单独的类中。

      【讨论】:

        【解决方案5】:

        对 b() 的方法调用是内部调用,而不是 Henning 所说的事务代理。

        this 博文中解释了整个事情。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-12
          • 1970-01-01
          • 2023-03-07
          • 2018-07-05
          • 1970-01-01
          • 2010-12-07
          • 2010-11-09
          相关资源
          最近更新 更多