NodeJS Mysql事务无法与innodb表一起正常工作

时间:2018-10-01 06:26:20

标签: mysql node.js transactions

我的数据访问层如下所示:

Connection.ts

let mysql = require('mysql');
const config = require('../../dbConfig/dbconfig');
let connectionpool = mysql.createPool({
  host: config.connection.host,
  user: config.connection.user,
  password: config.connection.password,
  database: config.connection.database,
  connectionLimit: 1000,
  connectTimeout: 60 * 60 * 1000,
  aquireTimeout: 60 * 60 * 1000,
  timeout: 60 * 60 * 1000,
});

exports.getConnection = function (callback) {
  connectionpool.getConnection(callback);
};

DBfactory.ts

const _dbConnection =  require('./Connection');
/**
 * Factory abstraction for creating database connection
 */
class DbFactory {
  static create(callback) {
    let st;
    const sqltranscation = require('./SqlTransaction');
    _dbConnection.getConnection((err, connection) => {
          if (err) {
            console.log('ERROR: getConnection failed: err = ' + err);
          }
          st = new sqltranscation(connection);
          return callback(st);
        });
  }
}
export const databaseFactory = DbFactory;

SQLtransaction.ts

class SqlTransaction {
  connection;
  constructor(connection) {
    this.connection = connection;
  }

  query(query, params, callback) { // command
    this.connection.beginTransaction((err) => {
      this.connection.query(query, params, (error, result) => {
        if (error) {
           this.connection.rollback();
           console.log(error);
           return callback(null, error);
        }
        // console.log(result);
        return callback(result, null);
      });
    });
  }

  complete() {
    this.connection.commit((err) => {
      if (err) {
        console.log(err);
      }
      this.connection.release();
      return err;
    });
  }
}

module.exports = SqlTransaction;

AddData.ts

class Data {
  transaction;
  constructor(st) {
    this.transaction = st;
  }
 addData(contract, callback) {

    try {

      const arr = [];

      // const keys = [];
      // for (const k in contract[0]) {
      //   keys.push(k);
      // }

      for (let i = 0; i < contract.length; i++) {
        let contractSignedDate = null;
        if (contract[i].contract_signed_date !== (null || '')) {
          contractSignedDate = '"' + this.dateFormat(contract[i].contract_signed_date) + '"';
        } else {
          contractSignedDate = null;
        }

        let contractExpiryDate = null;
        if (contract[i].contract_expiry_date !== (null || '')) {
          contractExpiryDate = '"' + this.dateFormat(contract[i].contract_expiry_date) + '"';
        } else {
          contractExpiryDate = null;
        }

        let contractImplementationDate = null;
        if (contract[i].contract_implementation_date !== (null || '')) {
          contractImplementationDate = '"' + this.dateFormat(contract[i].contract_implementation_date) + '"';
        } else {
          contractImplementationDate = null;
        }

        let contractTerminationDate = null;
        if (contract[i].contract_termination_date !== (null || '')) {
          contractTerminationDate = '"' + this.dateFormat(contract[i].contract_termination_date) + '"';
        } else {
          contractTerminationDate = null;
        }

        let notifyExpirationDays = null;
        if (isNumber(contract[i].notify_expiration_days)) {
          notifyExpirationDays = contract[i].voice_quota_tax;
        } else {
          notifyExpirationDays = null;
        }

        let etcApplicable;
        if (contract[i].etc_applicable === 'Yes') {
          etcApplicable = 1;
        } else {
          etcApplicable = 0;
        }

        const sqlQuery = '('
          + '(select id from contract_types where description  = "' + contract[i].contract_type + '")' + ', '
          + '"' + contract[i].contract_reference + '"' + ','
          + '"' + contract[i].contract_name + '"' + ','
          + contractSignedDate + ', '
          + contractExpiryDate + ', '
          + contractImplementationDate + ', '
          + contractTerminationDate + ', '
          + '"' + getString(contract[i].contract_termination_notes.split('"').join('\\"')) + '"' + ', '
          + notifyExpirationDays + ', '
          + etcApplicable + ', '
          + '"' + contract[i].etc_information + '"' + ', '
          + '"' + getString(contract[i].notes.split('"').join('\\"')) + '"' + ', '
          + '(select id from vendors where company  = "' + contract[i].vendor_company + '")'
          + ')';
        arr.push(sqlQuery);
        // console.log(sqlQuery);
      }

      const headers = '(contract_type_id, contract_reference, contract_name, contract_signed_date, contract_expiry_date, contract_implementation_date, contract_termination_date, contract_termination_notes ,' +
        ' notify_expiration_days, etc_applicable, etc_information, notes, vendor_id )';

      const query = `INSERT INTO dog_and_bone.contracts ` +
        headers +
        ` VALUES ` + arr.join(',');

      // console.log(query);

      const insertIds = [];
      this.transaction.query(query, [],
                             (result, error) => {

                               if (error) {
                                 return callback(null, error);
                               }
                               const length = result.affectedRows;
                               let insertId = result.insertId;
                               for (let i = 0; i < length; i++ ) {
                                 insertIds.push(insertId++);
                               }

                               const queryArrays = [];

                               const keys = [];
                               for (const k in contract[0]) {
                                 keys.push(k);
                               }

                               for (let i = 0; i < contract.length; i++) {
                                 for (let j = 0; j < keys.length; j++) {

                                   if (keys[j] === 'service_type_codes') {
                                     // console.log(contract[i][keys[j]]);
                                     const serviceCodes = contract[i][keys[j]].split(';');
                                     // console.log(serviceCodes);
                                     for (let k = 0; k < serviceCodes.length; k++) {

                                       const sqlQueryy = `INSERT INTO dog_and_bone.contract_service_types ` + '(contract_id, service_type_id )' + ' VALUES ' + '(' +
                                         insertIds[i] + ', ' + '(select id from service_types where code = "' + serviceCodes[k] + '")' + ')';
                                       queryArrays.push(sqlQueryy);

                                     }
                                   }

                                   if (keys[j] === 'internal_contact_ids') {
                                     // console.log(contract[i][keys[j]]);
                                     const internalContactIds = contract[i][keys[j]].split(';');

                                     for (let k = 0; k < internalContactIds.length; k++) {

                                       const sqlQueryy = `INSERT INTO dog_and_bone.contract_contacts ` + '(contract_id, contact_id, is_internal )' + ' VALUES ' + '(' +
                                         insertIds[i] + ', ' + internalContactIds[k] + ', ' + 1 + ')';
                                       queryArrays.push(sqlQueryy);

                                     }

                                   }
                                   if (keys[j] === 'external_contact_ids') {
                                     // console.log(contract[i][keys[j]]);

                                     const externalContactIds = contract[i][keys[j]].split(';');

                                     for (let k = 0; k < externalContactIds.length; k++) {

                                       const sqlQueryy = `INSERT INTO dog_and_bone.contract_contacts ` + '(contract_id, contact_id, is_internal )' + ' VALUES ' + '(' +
                                         insertIds[i]  + ', ' + externalContactIds[k] + ', ' + 0 + ')';
                                       queryArrays.push(sqlQueryy);

                                     }
                                   }
                                 }
                               }

                               // console.log(queryArrays);

                               let j = 0;

                               for (let i = 0; i < queryArrays.length; i++) {
                                 this.transaction.query(queryArrays[i], [],
                                   (res, err) => {
                                     if (err) {
                                       return callback(null, err);
                                     }
                                     j++;
                                     if (j === queryArrays.length) {
                                       return callback(res, err);
                                     }
                                   });
                               }
                               // return callback(result, error);
       });
    } catch (e) {
      return callback(null, e.message);
    }
  }
}

问题是我使用单个连接执行多个语句,但是后一个查询由于错误而失败时,将自动提交第一个查询。基本上,交易未按预期进行。我做错什么了吗?

0 个答案:

没有答案