【问题标题】:Spring transaction manager and multithreadingSpring事务管理器和多线程
【发布时间】:2013-05-26 00:24:35
【问题描述】:

我正在使用Callable接口在serviceImpl中编写多线程程序。我正在使用spring事务管理器。当在DB中执行更新操作时,它执行成功。但是更新的数据没有反映在DB中。但是当我在没有多线程的情况下运行程序,它会在 DB 中更新

这是我的配置

<tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="*" />
            <tx:method name="find*" propagation="NOT_SUPPORTED" />
            <tx:method name="get*" propagation="NOT_SUPPORTED" />
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="serviceOperation" expression="execution(* *..*ServiceImpl.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
    </aop:config>
    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

我可以转移到事务管理器的另一种方法。只是我想确认这种方法是否支持多线程。 所以我的问题是 spring事务管理器是否支持多线程(我的意思是通过声明注解或XML) 为什么在我的情况下更新的数据没有反映在数据库中? 最好的替代方法是什么?

【问题讨论】:

    标签: java spring spring-transactions


    【解决方案1】:

    您可能希望在 Spring 中实现自己的 TransactionSynchronizationManager 并将其注入。使用 InmheritableThreadLocal 之类的东西而不是 ThreadLocal。

    【讨论】:

      【解决方案2】:

      你还没有展示你是如何做多线程的,所以我只能猜测你做了什么:

      在 YourService.doSomething() 中,它创建线程。对于每个线程,它都在执行与 DB 相关的操作。对吗?

      正如另一个答案中所述,事务上下文以线程本地方式存储。因此,您在线程中的逻辑与任何事务都没有关联。您可以验证的一件事是,除了线程中的逻辑之外,在 doSomething() 中您还可以执行一些数据库操作。您会发现您在 doSomething() 中执行的数据库操作已提交,而线程中的操作会丢失。

      一个合理的解决方法是,通常我们有一层应用服务作为工作单元,因此我们在上面有事务边界(类似于你的服务)。您的线程应该调用服务提供的操作。当然,它们都会在不同的事务中。

      如果您希望它们全部在一个事务中,另一种方法是,不是让单个线程执行 DB 操作,而是线程现在执行繁重的工作并将结果发送回原始线程(例如,通过生产者-消费者队列)。起源线程负责收集结果并执行数据库操作。

      我个人会尽量避免在不同的线程中手动传递事务上下文。这简直是​​在破坏声明式事务的整个想法。

      【讨论】:

        【解决方案3】:

        Spring 使用的事务上下文存储在线程局部变量中。因此,如果您启动一个新线程,或使用可调用对象在另一个线程中执行代码,则此代码不会成为 Spring 事务方面启动的事务的一部分。这就是为什么您的数据没有出现在数据库中的原因。

        【讨论】:

        • 是否可以将活动事务传递给第二个线程?
        • 我对此表示怀疑。事务方面如何知道第二个线程是否完成了事务?如果方法在派生线程(或可调用线程)完成工作之前返回,谁会最终提交事务?
        • 如果我做这样的事情,我负责线程的正确同步。例如,在线程 A 中开始工作并在线程 B 中完成它可能很有用(因此在线程之间传递事务)。
        猜你喜欢
        • 2020-09-11
        • 2021-02-20
        • 1970-01-01
        • 1970-01-01
        • 2015-09-07
        • 2019-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多