当前位置: 首页 > 知识库问答 >
问题:

spring boot xa事务数据源和jms

包和泰
2023-03-14

我制作了一个POC,其中包含Spring-boot-starter-data-jpa和Spring-boot-starter-active emq。当提交jpa事务时,我想在代理(activeMQ)上推送jms消息。

我的代码: UtilsateurService具有"主"事务:

@Service
public class UtilisateurService {

    @Autowired
    private UtilisateurRepository utilisateurRepository;

    @Autowired
    private SendMessage sendMessage;

    @Transactional(rollbackOn = java.lang.Exception.class)
    public Utilisateur create(Utilisateur utilisateur) throws Exception {
        final Utilisateur result = utilisateurRepository.save(utilisateur);
        sendMessage.send("creation utilisateur : " + result.getId());
        throw new Exception("rollback");
        //return result;
    }
}

“管理”Jms消息的SendMessage类:

@Component
public class SendMessage {

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Value("${jms.queue.destination}")
    private String destinationQueue;

    public void send(String msg) {
        this.jmsMessagingTemplate.convertAndSend(destinationQueue, msg);
    }

}

我的主要班级:

@SpringBootApplication
@EnableJms
@EnableTransactionManagement
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

在抛出异常之前,JMS消息被推送到activeMq代理上。所以我对经纪人没有“回滚”。

如何配置运行xa事务?

共有2个答案

赵高雅
2023-03-14

哈森给出了解决方案。因此,我将SendMessage类更改为:

@Component
public class SendMessage {

    private final JmsMessagingTemplate jmsMessagingTemplate;

    @Value("${jms.queue.destination}")
    private String destinationQueue;

    @Autowired
    public SendMessage(JmsMessagingTemplate jmsMessagingTemplate) {
        this.jmsMessagingTemplate = jmsMessagingTemplate;
        this.jmsMessagingTemplate.getJmsTemplate().setSessionTransacted(true);
    }

    public void send(String msg) {
        this.jmsMessagingTemplate.convertAndSend(destinationQueue, msg);
    }

}
臧曜瑞
2023-03-14

您的jmsTemplate是否已交易?

jmsTemplate.setSessionTransacted(true); 

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/support/JmsAccessor.html#setSessionTransacted-布尔值-

public void SetSessionTransact(布尔sessionTransact)

设置创建JMS会话时使用的事务模式。默认值为“false”。请注意,在JTA事务中,传递给create(Queue/Topic)Session(boolean transact,int-ackknowledgemode)方法的参数没有被考虑在内。根据JavaEE事务上下文,容器对这些值做出自己的决定。类似地,在本地管理的事务中也不考虑这些参数,因为在这种情况下,访问器操作现有的JMS会话。

将此标志设置为true将在托管事务之外运行时使用简短的本地JMS事务,在存在托管事务(XA事务除外)时使用同步的本地JMS事务。这具有本地JMS事务与主事务(可能是本地JDBC事务)一起管理的效果,JMS事务在主事务之后提交。

http://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with-and-without-xa.html

30.2.5交易管理

Spring提供了一个JmsTransactionManager,用于管理单个JMS连接工厂的事务。这允许JMS应用程序利用Spring的托管事务特性,如第17章“事务管理”中所述。JmsTransactionManager执行本地资源事务,将JMS连接/会话对从指定的ConnectionFactory绑定到线程。JmsTemplate自动检测此类事务性资源并相应地对其进行操作。

在JavaEE环境中,ConnectionFactory将汇集连接和会话,因此这些资源可以在事务之间高效地重用。在独立环境中,使用Spring的SingleConnectionFactory将导致共享JMS Connection,每个事务都有自己独立的会话。或者,考虑使用特定于提供程序的池适配器,如ActiveMQ的PooledConnectionFactory类。

JmsTemplate还可以与JtaTransactionManager和支持XA的JMS ConnectionFactory一起使用,以执行分布式事务。注意,这需要使用JTA事务管理器以及正确配置的XA连接工厂!(检查Java EE服务器/JMS提供程序的文档。)

在使用JMS API从连接创建会话时,跨托管和非托管事务环境重用代码可能会令人困惑。这是因为JMS API只有一个工厂方法来创建会话,并且它需要事务和确认模式的值。在托管环境中,设置这些值是环境的事务性架构体系的责任,因此供应商对JMS连接的包装器会忽略这些值。在非托管环境中使用JmsTemboard时,您可以通过使用SessionTransact和SessionAc知识模式属性来指定这些值。当使用带有JmsTemboard的PlatformTransactionManager时,模板将始终被赋予一个事务性JMS会话。

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/jms.html#jms-德克萨斯州

 类似资料:
  • 一、Attach数据库: ATTACH DATABASE语句添加另外一个数据库文件到当前的连接中,如果文件名为":memory:",我们可以将其视为内存数据库,内存数据库无法持久化到磁盘文件上。如果操作Attached数据库中的表,则需要在表名前加数据库名,如dbname.table_name。最后需要说明的是,如果一个事务包含多个Attached数据库操作,那么该事务仍然是原子的。见如下示例:

  • 我正在计划一个使用事件源的微服务模型。为了实现高可伸缩性和高吞吐量处理能力,我将使用Kafka作为微服务的消息代理。 在这一点上,我有问题的实现模型,以能够拥有Kafka主题和分区的好处。我的模型需要满足一些要求: 微服务必须从message broker获取数据(post/patch/put/delete) 数据一致性是强制性的,如果实体A需要实体B的先前存在,则必须只存在实体A的指向实体B的有

  • 在我的spring服务中,我调用了两个spring数据存储库方法 现在我的查询与事务管理相关。就我所了解和看到的代码而言,spring存储库使用@Transactional为其方法启用了事务。对于select操作,它的readonly=true。 我对事务的理解是,当执行选择操作时,会创建一个事务,然后为保存操作创建另一个事务,因为对于选择操作,事务只读=true。 我希望在单个事务中执行读写操作

  • 我有一个Spring mvc rest webservice,它带有一个保存数据源地图的数据源管理器bean。每个客户都有自己的数据库,因此也有自己的数据源。webservice以编程方式从DataSourceManager加载客户数据源,如果不存在,则创建一个新的。 通过这种实现,可以使用注释驱动的事务管理吗?我阅读的所有示例都在配置文件中声明了一个或多个数据源。

  • 1. 前言 一个项目中使用多个数据源的需求,我们在日常工作中时常会遇到。 以商城系统为例,有一个 MySQL 的数据库负责存储交易数据。公司还有一套 ERP 企业信息化管理系统,要求订单信息同步录入 ERP 数据库,便于公司统一管理,而该 ERP 系统采用的数据库为 SQL Server 。 此时,就可以在 Spring Boot 项目中配置多个数据源。另外,使用多数据源后,需要采用分布式事务来保

  • 本文向大家介绍SQLite教程(五):数据库和事务,包括了SQLite教程(五):数据库和事务的使用技巧和注意事项,需要的朋友参考一下 一、Attach数据库:      ATTACH DATABASE语句添加另外一个数据库文件到当前的连接中,如果文件名为":memory:",我们可以将其视为内存数据库,内存数据库无法持久化到磁盘文件上。如果操作Attached数据库中的表,则需要在表名前加数据库