鍍金池/ 問答/數(shù)據(jù)庫(kù)  HTML/ sequelizejs 對(duì)事務(wù)的控制,請(qǐng)問有什么好的封裝建議

sequelizejs 對(duì)事務(wù)的控制,請(qǐng)問有什么好的封裝建議

使用sequelizejs對(duì)mysql的事務(wù)進(jìn)行控制,在跨方法,跨service時(shí),請(qǐng)問怎樣封裝或者設(shè)計(jì),能平滑的傳遞事務(wù)

應(yīng)用的框架是express + sequelizejs,在service層中,常常會(huì)出現(xiàn)在一個(gè)方法中調(diào)用其他service的方法,但是又要求在同一個(gè)事務(wù)中,所以只能獲取開啟事務(wù)后,將事務(wù)傳遞到其他service中,一旦service發(fā)生變動(dòng),需要更改的地方就非常多了

例如在保存一邊文章的時(shí)候,需要將其包含的標(biāo)簽的關(guān)系存放到另一張表中,保存標(biāo)簽與文章關(guān)系的操作在兩一個(gè)service中,這就需要將事務(wù)傳遞

// 這是保存文章的操作
async saveOrUpdateArticle(article: Article){
    if(!article.tags && article.tags.length < 1){
        throw new BusinessException('文章的所屬標(biāo)簽不能為空')
    }
    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;             
}

// 這是保存文章與標(biāo)簽關(guān)系的操作,需要預(yù)留事務(wù)參數(shù)的傳遞    

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;
}

在進(jìn)行事務(wù)操作的時(shí)候,能否不通過(guò)參數(shù)的方式進(jìn)行事務(wù)的傳遞,各位大佬有什么好的建議?

回答
編輯回答
生性

不進(jìn)行參數(shù)傳遞的話,就可以理解為是有一個(gè)“全局變量”在起作用。

  1. 每個(gè)req觸發(fā)一次docker重建,設(shè)置global.transaction。不過(guò)肯定不適合已有項(xiàng)目,用serverless還有可能實(shí)現(xiàn)
  2. 設(shè)置 req.transaction 變量,在各項(xiàng)操作中,保證 req 變量可用。這樣的話,相當(dāng)于用req偽裝了全局變量
2017年12月13日 21:54
編輯回答
維他命

建議不使用數(shù)據(jù)庫(kù)本身的事務(wù)

2018年4月30日 18:21
編輯回答
莫小染
let transactionServer = new Server(t);
let server = new Server();

transactionServer.doSomething();

我也想知道有什么好辦法,我們目前是這樣做的。

2017年2月25日 11:16