当前位置: 首页 > news >正文

Node生态中最优雅的数据库事务处理机制

Vona ORM 对数据库事务提供了完整的支持,提供了直观、优雅、强大的特性:

  1. 使用装饰器启用事务
  2. 事务传播机制
  3. 事务补偿机制
  4. 确保数据库与缓存数据一致性

使用装饰器启用事务

import { Database } from 'vona-module-a-orm';class ServicePost {@Database.transaction()async transaction() {// insertconst post = await this.scope.model.post.insert({title: 'Post001',});// updateawait this.scope.model.post.update({id: post.id,title: 'Post001-Update',});}
}  

手工启用事务

1. 使用当前数据源

class ServicePost {async transactionManually() {const db = this.bean.database.current;await db.transaction.begin(async () => {await this.scope.model.post.update({ id: 1, title: 'Post001_Update' });});}
}

2. 使用指定数据源

class ServicePost {async transactionManually() {const db = this.bean.database.getDb({ clientName: 'default' });await db.transaction.begin(async () => {const modelPost = this.scope.model.post.newInstance(db);await modelPost.update({ id: 1, title: 'Post001_Update' });});}
}

事务参数

class ServicePost {@Database.transaction({
+   isolationLevel: 'READ_COMMITTED',
+   propagation: 'REQUIRED'})async transaction() {...}
}  
class ServicePost {async transactionManually() {const db = this.bean.database.getDb({ clientName: 'default' });await db.transaction.begin(async () => {...},{
+       isolationLevel: 'READ_COMMITTED',
+       propagation: 'REQUIRED',});}
}  

事务参数:isolationLevel

名称 说明
DEFAULT 数据库相关的缺省isolationLevel
READ_UNCOMMITTED
READ_COMMITTED
REPEATABLE_READ
SERIALIZABLE
SNAPSHOT

事务参数:propagation

Vona ORM 支持数据库事务传播机制

名称 说明
REQUIRED 默认的事务传播级别。如果当前存在事务, 则加入该事务。如果当前没有事务, 则创建一个新的事务
SUPPORTS 如果当前存在事务,则加入该事务. 如果当前没有事务, 则以非事务的方式继续运行
MANDATORY 强制性。如果当前存在事务, 则加入该事务。如果当前没有事务,则抛出异常
REQUIRES_NEW 创建一个新的事务。如果当前存在事务, 则把当前事务挂起。也就是说不管外部方法是否开启事务,总是开启新的事务, 且开启的事务相互独立, 互不干扰
NOT_SUPPORTED 以非事务方式运行。如果当前存在事务,则把当前事务挂起(不用)
NEVER 以非事务方式运行。如果当前存在事务,则抛出异常

事务补偿机制

当事务成功或者失败时执行一些逻辑

1. 成功补偿

this.bean.database.current.commit(async () => {// do something when success
});

2. 失败补偿

this.bean.database.current.compensate(async () => {// do something when failed
});

事务与Cache数据一致性

许多框架使用最简短的用例来证明是否高性能,而忽略了业务复杂性带来的性能挑战。随着业务的增长和变更,项目性能就会断崖式下降,各种优化补救方案让项目代码繁杂冗长。而 Vona 正视大型业务的复杂性,从框架核心引入缓存策略,并实现了二级缓存Query缓存Entity缓存等机制,轻松应对大型业务系统的开发,可以始终保持代码的优雅和直观

Vona 系统对数据库事务与缓存进行了适配,当数据库事务失败时会自动执行缓存的补偿操作,从而让数据库数据与缓存数据始终保持一致

针对这个场景,Vona 提供了内置的解决方案

1. 使用当前数据源

class ServicePost {@Database.transaction()async transaction() {// insertconst post = await this.scope.model.post.insert({title: 'Post001',});// cacheawait this.scope.cacheRedis.post.set(post, post.id);}
}  
  • 当新建数据后,将数据放入 redis 缓存中。如果这个事务出现异常,就会进行数据回滚,同时缓存数据也会回滚,从而让数据库数据与缓存数据保持一致

2. 使用指定数据源

class ServicePost {async transactionManually() {const db = this.bean.database.getDb({ clientName: 'default' });await db.transaction.begin(async () => {const modelPost = this.scope.model.post.newInstance(db);const post = await modelPost.insert({ title: 'Post001' });await this.scope.cacheRedis.post.set(post, post.id, { db });});}
}  
  • 如果对指定的数据库进行操作,那么就需要将数据库对象db传入缓存,从而让缓存针对数据库对象db执行相应的补偿操作。当数据库事务回滚时,让数据库数据与缓存数据保持一致
http://www.hskmm.com/?act=detail&tid=21261

相关文章:

  • 详细介绍:扒透 STL 底层!map/set 如何封装红黑树?迭代器逻辑 + 键值限制全手撕----《Hello C++ Wrold!》(23)--(C/C++)
  • 期货市场API对接完全指南:实时行情获取与实战应用
  • Tomcat使用redis管理session
  • NOC片上网络总线初探
  • AT_agc037_c [AGC037C] Numbers on a Circle
  • 记账本|基于SSM的家庭记账本小程序设计与实现(源码+数据库+文档) - 实践
  • redis数据连接写法
  • 缩放 div
  • 死锁的概念
  • 【2025-09-29】团队合作
  • 杂凑算法学习笔记
  • pg库支持扩展postgis
  • kuboard部署启用3个etcd(k8s单个master)
  • 数据库服务分布架构(MyCAT)
  • 题解:P14038 [PAIO 2025] Adventure Plan
  • 20231414_王仕琪_密码技术密码杂凑算法学习笔记
  • web3D、webGL、webGPU、webGIS、webXR、webCodecs的概念和对比 - 实践
  • Claude code的 thinking on/off差别有多少
  • Ubuntu 25的网络配置
  • 2025.9.26 测试
  • 贝叶斯学习笔记 - 详解
  • Ubuntu 24和25配置apt国内源
  • 实用指南:AWS实战:轻松创建弹性IP,实现固定公网IP地址
  • 完整教程:自然语言处理项目之情感分析(下)
  • 还在为安装PS发愁?这款网页版工具,打开浏览器就能用!
  • 委托相关
  • 清除“请允许观看视频”通知页面的完整指南
  • 千亿芯片公司被股东“抛弃” ,AI芯片第一股前景几何?
  • Java 与智慧港口:航运调度与物流枢纽数字化
  • DeepSeek-V3.2-Exp 发布,训练推理提效,API 同步降价