有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JavaSpring事务管理器和多线程

我正在使用可调用接口在serviceImpl中编写多线程程序。我正在使用spring事务管理器。在数据库中执行更新操作时,它将成功执行。但更新后的数据不会反映在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) 在我的例子中,为什么更新的数据没有反映在DB中 最佳替代方法是什么


共 (3) 个答案

  1. # 1 楼答案

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

  2. # 2 楼答案

    您可能希望在Spring中实现自己的TransactionSynchronizationManager并注入它。使用InmheritableThreadLocal之类的工具,而不是ThreadLocal

  3. # 3 楼答案

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

    为你效劳。doSomething(),它创建线程。对于每个线程,它都在执行与数据库相关的操作。是这样吗

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

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

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

    就我个人而言,我会尽量避免在不同的线程之间手动传递事务上下文。这完全破坏了声明式事务的整个概念