我正在为未来的项目评估Mikro-Orm。有几个问题我要么在文档中找不到答案,要么没有完全理解它们。
让我描述一个最小复杂示例(NestJS):我有一个包含两个实体的订单处理系统:Orders和Invoices,以及顺序发票号的计数器表(法律要求)。值得一提的是,OrderService create方法并不总是由控制器调用,而是通过crobjob/queue系统调用的。我的问题是关于创建新订单的用例:
class OrderService {
async createNewOrder(orderDto) {
const order = new Order();
order.customer = orderDto.customer;
order.items = orderDto.items;
const invoice = await this.InvoiceService.createInvoice(orderDto.items);
order.invoice = invoice;
await order.persistAndFlush();
return order
}
}
class InvoiceService {
async create(items): Invoice {
const invoice = new Invoice();
invoice.number = await this.InvoiceNumberService.getNextInSequence();
// the next two lines are external apis, if they throw, the whole transaction should roll back
const pdf = await this.PdfCreator.createPdf(invoice);
const upload = await s3Api.uplpad(pdf);
return invoice;
}
}
class InvoiceNumberService {
async getNextInSequence(): number {
return await db.collection("counter").findOneAndUpdate({ type: "INVOICE" }, { $inc: { value: 1 } });
}
}创建带有所有后续服务调用的新订单的整个用例应该发生在一个Mikro事务中。因此,如果有任何东西抛入OrderService.createNewOrder()或随后调用的方法之一,则应该回滚整个事务。
发布于 2020-02-25 11:05:55
我将从坏消息开始,mongodb事务在MikroORM中还不受支持(虽然它们可能在几周内就会出现,但已经实现了PoC )。您可以在这里订阅更新:https://github.com/mikro-orm/mikro-orm/issues/34
但让我回答其余的问题,因为这样就适用了:
可以使用const collection = (em as EntityManager<MongoDriver>).getConnection().getCollection('counter');从内部mongo连接实例获取集合。您还可以使用orm.em.getTransactionContext()获取当前的trasaction上下文(目前只在sql驱动程序中实现,但在将来,这可能会返回mongo中的session对象)。
还请注意,在mongo驱动程序中,默认情况下不会启用隐式事务(虽然它是可配置的),因此您需要通过em.transactional(...)使用显式事务划分。
RequestContext助手自动工作。您只需将其注册为中间件(在nestjs orm适配器中自动完成),然后在共享上下文的域中运行请求处理程序(路由/端点/控制器方法)。由于这一点,DI中的所有服务都可以共享存储库的单例实例,但它们将自动从域中选择正确的上下文。
您基本上拥有这个自动请求上下文,然后您可以通过em.transactional(...)手动创建新的(嵌套的)上下文。
https://mikro-orm.io/docs/transactions/#approach-2-explicitly
https://stackoverflow.com/questions/60392238
复制相似问题