请问怎么把mysql的事务多次查询给封装起来
发布于 6 年前 作者 DavidLuman 3408 次浏览 来自 问答

本来是下面这样封装的,但是这样子只能执行一次connection.query,有时要connection.query好几次,即对一次query完要处理再进行下一次query,那要怎么封装。 不应该是多次调用这个方法,因为每次都是new Promise,那就不属于同一次事务了。 var transactionQuery = function(sql, values,) { return new Promise((resolve, reject) => { pool.getConnection(function(err, connection) { if(err) { reject(err); } else { connection.beginTransaction(function(err) { if(err) { reject(err); } else { connection.query(sql, values, (err, result) => { if(err) { reject(err); } else { resolve(data); } }); } }); connection.release(); } }); }); }

13 回复

把query包装成promise?async await?

@heartAndRain 是的,因为需要用异步处理来获得数据

@DavidLuman promise包装为最小单元,不要想在一个promise把所有事情都做完。

来自酷炫的 CNodeMD

用同一个 connection 即可, 你写在里面还是外面, 没关系的.

mysql2欢迎你

async function xxx() {

    const { mysql } = this.app;


    const connection = await mysql.getConnection();

    try {
        await connection.beginTransaction(); // 开始事务
        const ret1 = await connection.query('xxx');
        if (!ret1) {
            await connection.rollback();
            return false;
        }
        //一些处理
        const ret2 = await connection.query('UPDATE xx');

        if (!ret2 || ret2.affectedRows <= 0) {
            await connection.rollback();
            return false;
        }


        await connection.commit();
        return true;

    } catch (e) {
        await connection.rollback();
        return false;
    } finally {
        connection.release();
    }
}


建个transaction类,把connect放到transaction中,将开启事务和提交,回滚事务分开。这样提交事务或回滚事务的时候释放连接,中间都可用把transaction当做参数进行传递。建议用sequelize

@AnzerWall 这样代码太长了,我就是因为代码长才想包装起来的

@ltfyxkfh sequelize的查询感觉好麻烦所以就没用,我现在是一次封装获得connection,然后再一个封装方法是传入connection来获得result

两个参数容易出bug,一个connection只能用一个事物,无法复用的。创建事物的时候先创建连接,然后创建事物,之后把连接当做属性保存在事物上,这样对用户来说连接是隐藏的,更干净好用

@ltfyxkfh 是这样么。这样遇到三个问题: 1.怎么把query的result返回,直接return的话外面得不到, 2.要怎么处理err,在调用的地方使用try/catch么。 3.这样每次外面还是得要pool.getConnection(),然后在里面创建类 class Transaction { constructor(connetcion) { this.connetcion = connetcion; } beginTransaction() { this.connetcion.beginTransaction(function(err) { if(err) throw err; }); } query(sql, value) { this.connetcion.query(sql, value, function(err, result) { if(err) throw err; return result }); } commit() { this.connetcion.commit(); this.connetcion.release(); } rollback() { this.connection.rollback(); this.connetcion.release(); } }

@DavidLuman 为啥说sequelize用起来很麻烦?我的项目里用的很顺手啊,很方便啊,功能也很强大,文档也丰富

来自酷炫的 CNodeMD

Promise是为此而设计的。

function foo () { return new Promise(function(resolve, rejection) { // 这里可以是任意复杂的异步逻辑 // 最终只需要根据不同情况调用resolve(…), 或者reject(…) 即可 }); }

调用代码

foo() .then(success, failure) .then(success, failure) .catch(error)

@DavidLuman

  1. 你可以用promise,这样可以通过then或者await获取结果
  2. try catch 只能在async await下得到promise的异常,无法得到callback形式throw的异常
  3. 可以封装一个getTransaction方法,方法里面是建立连接返回transaction
  4. sequelize真的很好用的,已经封装了getTransaction方法
回到顶部