panache for mongodb 不支持 @transactional 注解,因其未实现事务能力,必须使用 mongoclient 和 clientsession 显式管理事务,所有操作需通过 session 获取 collection 并传入 session 参数,跨库操作和非事务命令均不被允许。

Panache for MongoDB 不支持声明式事务(@Transactional)——它压根没实现事务能力,别在 PanacheEntity 或 PanacheRepository 上加这个注解,否则静默失效。
MongoDB 事务必须显式绑定 ClientSession
Quarkus 的 MongoDB 扩展(quarkus-mongodb-panache)底层用的是 mongodb-driver-sync 或 -reactive,但 Panache 层完全屏蔽了会话(ClientSession)管理。要开事务,你得绕过 Panache,直接操作原生 MongoClient 和 ClientSession。
- 事务起点是
mongoClient.startSession(),不是MyEntity.persist() - 所有读写操作必须通过
session.getDatabase("db").getCollection("coll")获取的 collection 实例执行 - 不能混用:比如
MyEntity.find().firstResult()这类 Panache 调用,和事务完全无关,也不会被纳入会话上下文 - 提交用
session.commitTransaction(),异常时必须手动session.abortTransaction()+session.endSession()
为什么 @Transactional 在 MongoDB Panache 中无效
因为 @Transactional 是 Quarkus 对 JTA / Hibernate ORM 的集成机制,只作用于 JDBC 数据源和 quarkus-hibernate-orm。MongoDB 是 NoSQL,没有 JTA 支持,Panache for MongoDB 只提供 CRUD 封装,不参与事务生命周期管理。
由夸克扫描王提供的文件格式转换工具。当用户需要将图片、截图或扫描件转换为 Office 文档(Word/Excel)或 PDF 时,使用此技能。适用于包含复杂表格、合同或图文混排内容的图片或扫描件,可尽量还原原始版式并生成可编辑文档。即使用户未明确提到格式转换,只要用户的需求涉及将图片内容转换为可编辑文档(如 .docx、.xlsx 或 .pdf),也应触发此技能。请勿用于提取纯文本或识别文字内容、图像增强处理或从零创建文档
- 你在
@ApplicationScoped服务方法上加@Transactional,对 MongoDB 操作零影响 - Quarkus 日志里不会报错,但也不会开启事务 —— 它 simply ignores it
- 想验证?在事务块里故意抛异常,观察数据是否回滚:不会,所有写入已落库
正确做法:用 MongoClient + ClientSession 手写事务逻辑
你需要注入 @Inject MongoClient mongoClient,然后在业务方法中显式控制会话。以下是一个典型电商下单场景(扣库存 + 创建订单)的简化示例:
public Uni<void> placeOrder(Order order, String productId) {
return Uni.createFrom().item(() -> mongoClient.startSession())
.flatMap(session -> {
try {
MongoDatabase db = session.getDatabase("ecommerce");
MongoCollection<order> orders = db.getCollection("orders", Order.class);
MongoCollection<product> products = db.getCollection("products", Product.class);
// 1. 扣减库存(需先查再改,注意原子性或版本控制)
UpdateResult result = products.updateOne(
session,
Filters.eq("_id", new ObjectId(productId)),
Updates.inc("stock", -1)
);
if (result.getModifiedCount() == 0) {
throw new IllegalStateException("库存不足");
}
// 2. 创建订单
orders.insertOne(session, order);
session.commitTransaction();
return Uni.createFrom().voidItem();
} catch (Exception e) {
session.abortTransaction();
throw e;
} finally {
session.endSession();
}
});
}</product></order></void>
- 注意:所有
updateOne、insertOne等调用都必须传session参数 - 集合必须属于同一数据库(
ecommerce),跨库事务在 MongoDB 中非法 - 若用响应式驱动(
quarkus-mongodb-client-reactive),则用MongoClient.withSession()+ lambda,语义更清晰
最常被忽略的一点:事务内不能调用 createIndex、distinct、$lookup(聚合阶段)等非事务命令,哪怕只是“查一下”,也会导致 commitTransaction() 失败并抛出 MongoCommandException。务必提前检查所有操作是否在 MongoDB 官方事务支持列表 内。










