sequelizejs 对事务的控制,请问有什么好的封装建议

发布于 2022-09-07 20:31:48 字数 2580 浏览 9 评论 0

使用sequelizejs对mysql的事务进行控制,在跨方法,跨service时,请问怎样封装或者设计,能平滑的传递事务

应用的框架是express + sequelizejs,在service层中,常常会出现在一个方法中调用其他service的方法,但是又要求在同一个事务中,所以只能获取开启事务后,将事务传递到其他service中,一旦service发生变动,需要更改的地方就非常多了

例如在保存一边文章的时候,需要将其包含的标签的关系存放到另一张表中,保存标签与文章关系的操作在两一个service中,这就需要将事务传递

// 这是保存文章的操作
async saveOrUpdateArticle(article: Article){
    if(!article.tags && article.tags.length < 1){
        throw new BusinessException('文章的所属标签不能为空')
    }
    const result = await db.transaction().then(async (t) => {
        try {
            // 修改
            if(article.id){
                article.updateAt = Date.now();
                let originArticel = await this.getArticleById(article.id, t);
                originArticel = await originArticel.update(article, {transaction: t});
                //更新articleTag
            }else{
                // 新增
                const newArticle = await ArticleModel.create(article, {transaction: t});
                //throw 'abort the transaction';
                const articleTags = [];
                article.tags.forEach((tagId) => {
                    const articleTag: ArticleTag = {
                        articelId: newArticle.id,
                        tagId: tagId
                    };
                    articleTags.push(articleTag);
                });
                // 新增articleTag
                await this.services.articleTagService.saveOrUpdateArticleTags(articleTags, t);
            }
            await t.commit();
            return true;
        } catch (e) {
            await t.rollback()
            logger.error(e);
            return false;
        }   
    })
    return result;             
}

// 这是保存文章与标签关系的操作,需要预留事务参数的传递    

async saveOrUpdateArticleTags(articleTags: ArticleTag[], t){
    const promiseList = [];
    articleTags.forEach((articleTag) => {
        promiseList.push(this.saveOrUpdateArticleTag(articleTag, t));
    });
    return await Promise.all(promiseList);
}

async saveOrUpdateArticleTag(articleTag: ArticleTag, t){
    //修改
    if(articleTag.id){
        articleTag.updateAt = Date.now();
        const originArticleTag = await this.getTagById(articleTag.id);
        if(!originArticleTag){
            throw new BusinessException(`id为'${articleTag.id}'的articleTag不存在`);
        }
        articleTag = await originArticleTag.update(articleTag);
    }else{
        articleTag = await ArticleTagModel.create(articleTag, {transaction: t})
    }
    return articleTag;
}

在进行事务操作的时候,能否不通过参数的方式进行事务的传递,各位大佬有什么好的建议?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

南街九尾狐 2022-09-14 20:31:48
let transactionServer = new Server(t);
let server = new Server();

transactionServer.doSomething();

我也想知道有什么好办法,我们目前是这样做的。

横笛休吹塞上声 2022-09-14 20:31:48

不进行参数传递的话,就可以理解为是有一个“全局变量”在起作用。

  1. 每个req触发一次docker重建,设置global.transaction。不过肯定不适合已有项目,用serverless还有可能实现
  2. 设置 req.transaction 变量,在各项操作中,保证 req 变量可用。这样的话,相当于用req伪装了全局变量
心在旅行 2022-09-14 20:31:48

建议不使用数据库本身的事务

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文