CNode

请问怎么把mysql的事务多次查询给封装起来

问答
DDavidLuman发布于8 年前最后回复8 年前13 回复4384 浏览0 收藏

本来是下面这样封装的,但是这样子只能执行一次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)

H
heartAndRain#1·8 年前

把query包装成promise?async await?

D
DavidLuman#2·8 年前
引用 heartAndRain把query包装成promise?async await?

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

Z
zy445566#3·8 年前
引用 DavidLuman@heartAndRain 是的,因为需要用异步处理来获得数据

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

来自酷炫的 CNodeMD

D
dlyt#4·8 年前

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

A
AnzerWall#5·8 年前

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


L
ltfyxkfh#6·8 年前

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

D
DavidLuman#7·8 年前
引用 AnzerWallmysql2欢迎你

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

D
DavidLuman#8·8 年前
引用 ltfyxkfh建个transaction类,把connect放到transaction中,将开启事务和提交,回滚事务分开。这样提交事务或回滚事务的时候释放连接,中间都可用把transaction当做参数进行...

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

L
ltfyxkfh#9·8 年前

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

D
DavidLuman#10·8 年前
引用 ltfyxkfh两个参数容易出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(); } }

Z
zhangmingfeng#11·8 年前
引用 DavidLuman@ltfyxkfh sequelize的查询感觉好麻烦所以就没用,我现在是一次封装获得connection,然后再一个封装方法是传入connection来获得result

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

来自酷炫的 CNodeMD

F
flamingtop#12·8 年前

Promise是为此而设计的。

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

调用代码

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

L
ltfyxkfh#13·8 年前

@DavidLuman

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