2017-03-21 5 views
0

のNode.js + ORACLEDB - 私はこのJSONを受けた最後の日付を挿入して、何度

{ 
    "TOTAL_RECORDS": 1029, 
    "REGISTROS": [ 
    { 
     "CODIGO": "1", 
     "ATENDIMENTO": "1", 
     "PAGAMENTO": "1", 
     "VENCIMENTO": "2016-12-17 00:00:00", 
     "PROCESSAMENTO": "2016-12-10 00:00:00", 
     "VALOR": "1800.00000", 
     "NOSSO_NUMERO": "xxxxxxx", 
     "NUMERO_DOCUMENTO": "xxxxx", 
     "CODIGO_BANCO": "123", 
     "LINHA_DIGITAVEL": "XXX70110000180000", 
     "CODIGO_BARRAS": "XXX90940" 
    }, 
    { 
     "CODIGO": "2", 
     "ATENDIMENTO": "2", 
     "PAGAMENTO": "2", 
     "VENCIMENTO": "2016-12-17 00:00:00", 
     "PROCESSAMENTO": "2016-12-10 00:00:00", 
     "VALOR": "2700.00000", 
     "NOSSO_NUMERO": "xxxxxxx", 
     "NUMERO_DOCUMENTO": "xxxxx", 
     "CODIGO_BANCO": "123", 
     "LINHA_DIGITAVEL": "XXX70110000180000", 
     "CODIGO_BARRAS": "XXX90940" 
    },... 

その後、私はこの情報をキャッチし、DBのOracleに保存する必要があるので、私はこれを実行します。

module.exports = function (object, callback) { 

    var oracledb = require('oracledb');  
    for(const prop in object['REGISTROS']){      

     codigo = object['REGISTROS'][prop]['CODIGO'];    

     atendimento = object['REGISTROS'][prop]['ATENDIMENTO']; 

     pagamento = object['REGISTROS'][prop]['PAGAMENTO']; 

     vencimento = object['REGISTROS'][prop]['VENCIMENTO']; 

     processamento = object['REGISTROS'][prop]['PROCESSAMENTO']; 

     valor = parseInt(object['REGISTROS'][prop]['VALOR']); 

     nossoNumero = object['REGISTROS'][prop]['NOSSO_NUMERO']; 

     numeroDocumento = object['REGISTROS'][prop]['NUMERO_DOCUMENTO']; 

     codigoBanco = object['REGISTROS'][prop]['CODIGO_BANCO']; 

     linhaDigitavel = object['REGISTROS'][prop]['LINHA_DIGITAVEL'];    

     codigoBarras = object['REGISTROS'][prop]['CODIGO_BARRAS']; 

     oracledb.getConnection({    
      user: "x", 
      password:"xxx", 
      connectString: "mycon/string" 
     }, 
     function(err, connection){ 
      if (err){ 
       console.error(err.message); 
       return; 
      } 

      connection.execute(
       "INSERT INTO USU_TBOLETO VALUES (:USU_CODIGO, :USU_ATEND, :USU_PAGAMENTO, " + 
       ":USU_VENCIMENTO, :USU_PROCESSA, :USU_VALOR, :USU_NOSSONUM, :NUMERODOC, :USU_CODBANCO, " + 
       ":USU_LINHADIG , :USU_CODBARRAS)", 

      [codigo, atendimento, pagamento, vencimento, processamento, valor, nossoNumero, 
      numeroDocumento, codigoBanco, linhaDigitavel, codigoBarras], 
      { autoCommit: true},    
      function(err, result){ 

       if (err){ 
        console.error(err.message);    
        doRelease(connection); 
        return; 
       } 
       console.log(codigo + ' - ' + atendimento + ' - ' + pagamento + ' - ' + vencimento); 
       ///console.log(result.metaData); 
       ///console.log(result.rows); 
       doRelease(connection); 
      });     
     }); 
    } 


    function doRelease(connection) {   
     connection.release( 
      function(err){ 
       if (err) { console.error(err.message); } 
      } 
     ); 
    } 
} 

そして、問題は、それが私のデータベースに合計レコードのようなちょうど最後のレコード、1029回、挿入されていますです。 なぜですか? 私はなぜそれが理解できません。 INSERTコードがFOR条件にあります。

肥満児までcodigo 1を出発して、1029倍に挿入される正しいです。 Diogo

+0

あなたのデシベルの挿入は非同期で、おそらくいくつかの時間がかかります。あなたの 'for'ループはほとんど直ちに実行されるので、挿入は最後の反復から値を受け取ります。 – abhishekkannojia

+0

これを見てくださいhttp://stackoverflow.com/questions/11488014/asynchronous-process-inside-a-javascript-for-loop – abhishekkannojia

答えて

1

あなたはコードとして実行するとあなたは現在それが構造化されている、それは多くのlibnvの作業キューへのync操作とJavaScriptコードの制御が失われます。私は(/ 7.6+ Node.jsの中で待つか、非同期)コントロールまたは約束チェーンを維持するためにasync module's eachSeries methodを使用してお勧めします。

また、ループの繰り返しごとに新しい接続を取得すると、処理が遅くなることがあります。この操作に必要な接続は1つだけです。あなたは接続を取得し、データを処理し、接続を閉じる必要があります。

もう1つのことは、autoCommit:trueの使用です。これを行ごとに行う場合は、各インサートを独自のトランザクションとして扱います。障害が途中で発生した場合は、何が間違っているかを把握して修正する(残りの行を挿入する)のは難しくマニュアルです。すべてを挿入した後に接続オブジェクトに対してcommitメソッドを使うことをお勧めします(または、ループの最後の繰り返しでautoCommit:trueを使用する)。

あなたがまたは3(一度に500のセットを行う場合)(一度にすべてを行うことによって)1029から1へのラウンドトリップの数を切断して、これをさらに最適化することができます:ここで

は一例です。これにより、パフォーマンスが大幅に向上します。バッチインサートを500グループ単位で実行する例を次に示します。

const oracledb = require('oracledb'); 
const config = require('./dbConfig.js'); 

module.exports = function(object, callback) { 
    let conn; 

    function insertRegistros(opts) { 
    if (opts.commit) { 
     console.log('Last iteration of the loop, committing with this one'); 
    } 

    return conn.execute(
    `declare 
     type varchar2_aat is table of varchar2(50) 
      index by pls_integer; 

     l_usu_codigo_vals varchar2_aat; 

     begin 

     l_usu_codigo_vals := :usu_codigo_vals; 

     forall x in 1 .. l_usu_codigo_vals.count 
     insert into usu_tboleto (
      usu_codigo, usu_atend, usu_pagamento, usu_vencimento, usu_processa, usu_valor, 
      usu_nossonum, numerodoc, usu_codbanco, usu_linhadig, usu_codbarras 
     ) values (
      :usu_codigo_vals(x), :usu_atend_vals(x), :usu_pagamento_vals(x), :usu_vencimento_vals(x), :usu_processa_vals(x), :usu_valor_vals(x), 
      :usu_nossonum_vals(x), :numerodoc_vals(x), :usu_codbanco_vals(x), :usu_linhadig_vals(x) , :usu_codbarras_vals(x) 
     ); 

     end;`, 
     { 
     usu_codigo_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.usu_codigo_vals}, 
     usu_atend_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.usu_atend_vals}, 
     usu_pagamento_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.usu_pagamento_vals}, 
     usu_vencimento_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.usu_vencimento_vals}, 
     usu_processa_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.usu_processa_vals}, 
     usu_valor_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.usu_valor_vals}, 
     usu_nossonum_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.usu_nossonum_vals}, 
     numerodoc_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.numerodoc_vals}, 
     usu_codbanco_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.usu_codbanco_vals}, 
     usu_linhadig_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.usu_linhadig_vals}, 
     usu_codbarras_vals: {type: oracledb.STRING, dir: oracledb.BIND_IN, val: opts.usu_codbarras_vals} 
     }, 
     { 
     autoCommit: opts.commit 
     } 
    ); 
    } 

    oracledb.getConnection(config) 
    .then(function(c) { 
     conn = c; 

     console.log('Got connection, starting loop'); 

     const batchRowCount = 500; 
     const loops = Math.ceil(object['REGISTROS'].length/batchRowCount); 

     let promiseChain = Promise.resolve(); 
     let registrosIdx = 0; 

     for (let outerIndex = 0; outerIndex < loops; outerIndex += 1) { 
     (function() { 
      const usu_codigo_vals = []; 
      const usu_atend_vals = []; 
      const usu_pagamento_vals = []; 
      const usu_vencimento_vals = []; 
      const usu_processa_vals = []; 
      const usu_valor_vals = []; 
      const usu_nossonum_vals = []; 
      const numerodoc_vals = []; 
      const usu_codbanco_vals = []; 
      const usu_linhadig_vals = []; 
      const usu_codbarras_vals = []; 

      for (let idx = 0; idx < batchRowCount; idx += 1) { 
      if (registrosIdx === object['REGISTROS'].length) { 
       break; 
      } 

      usu_codigo_vals.push(object['REGISTROS'][registrosIdx].CODIGO); 
      usu_atend_vals.push(object['REGISTROS'][registrosIdx].ATENDIMENTO); 
      usu_pagamento_vals.push(object['REGISTROS'][registrosIdx].PAGAMENTO); 
      usu_vencimento_vals.push(object['REGISTROS'][registrosIdx].VENCIMENTO); 
      usu_processa_vals.push(object['REGISTROS'][registrosIdx].PROCESSAMENTO); 
      usu_valor_vals.push(object['REGISTROS'][registrosIdx].VALOR); 
      usu_nossonum_vals.push(object['REGISTROS'][registrosIdx].NOSSO_NUMERO); 
      numerodoc_vals.push(object['REGISTROS'][registrosIdx].NUMERO_DOCUMENTO); 
      usu_codbanco_vals.push(object['REGISTROS'][registrosIdx].CODIGO_BANCO); 
      usu_linhadig_vals.push(object['REGISTROS'][registrosIdx].LINHA_DIGITAVEL); 
      usu_codbarras_vals.push(object['REGISTROS'][registrosIdx].CODIGO_BARRAS); 

      registrosIdx += 1; 
      } 

      promiseChain = promiseChain 
      .then(function() { 
       return insertRegistros({ 
       usu_codigo_vals: usu_codigo_vals, 
       usu_atend_vals: usu_atend_vals, 
       usu_pagamento_vals: usu_pagamento_vals, 
       usu_vencimento_vals: usu_vencimento_vals, 
       usu_processa_vals: usu_processa_vals, 
       usu_valor_vals: usu_valor_vals, 
       usu_nossonum_vals: usu_nossonum_vals, 
       numerodoc_vals: numerodoc_vals, 
       usu_codbanco_vals: usu_codbanco_vals, 
       usu_linhadig_vals: usu_linhadig_vals, 
       usu_codbarras_vals: usu_codbarras_vals, 
       commit: outerIndex + 1 === loops 
       }); 
      }); 
     })(); 
     } 

     return promiseChain; 
    }) 
    .catch(function(err) { 
     console.log(err); 
     console.log('Encountered error, rolling back transaction'); 

     return conn.rollback() 
     .then(function() { 
      console.log('Transaction rolled back'); 
     }) 
     .catch(function(err) { 
      console.log('Error rolling back', err); 
     }); 
    }) 
    .then(function() { 
     return conn.close(); 
    }) 
    .then(function() { 
     console.log('Connection closed'); 
    }) 
    .catch(function(err) { 
     console.log(err); 
    }); 
} 

ご覧のとおり、コードはややこしいです。ただし、文字列や数値だけでなく、レコードのバインディング配列のサポートがドライバで追加された場合、これは将来的にはより簡単になります。

あなたはそれと私の周りの仕事についての詳細を読むことができるが、ここで私のブログに使用しています: https://jsao.io/2017/01/plsql-record-types-and-the-node-js-driver/

+0

Thks Dan!ご覧のとおり、私はJSで新しく、あなたの説明が私を大いに助けました! 私は非常に興味があります! –

+0

こんにちはDiogo、私は一括例で答えを更新しました。私はそれが助けて欲しい! –

0

forループはほぼ即時に実行されますが、データベース操作は非同期で低速です。 forループだったな、すまんすまんは、非同期操作にコールバックが実行されてしまった時点で完了し、したがって、それだけで、ループの最後の繰り返し中に値が表示されます。あなたはブロックが変数スコープが作成されますES6s constを使用して変数を宣言することができ、これを回避するために

。これにあなたのコードを変更し、それが動作するはずです:

module.exports = function(object, callback) { 

    var oracledb = require('oracledb'); 
    for (const prop in object['REGISTROS']) { 

     const codigo = object['REGISTROS'][prop]['CODIGO']; 

     const atendimento = object['REGISTROS'][prop]['ATENDIMENTO']; 

     const pagamento = object['REGISTROS'][prop]['PAGAMENTO']; 

     const vencimento = object['REGISTROS'][prop]['VENCIMENTO']; 

     const processamento = object['REGISTROS'][prop]['PROCESSAMENTO']; 

     const valor = parseInt(object['REGISTROS'][prop]['VALOR']); 

     const nossoNumero = object['REGISTROS'][prop]['NOSSO_NUMERO']; 

     const numeroDocumento = object['REGISTROS'][prop]['NUMERO_DOCUMENTO']; 

     const codigoBanco = object['REGISTROS'][prop]['CODIGO_BANCO']; 

     const linhaDigitavel = object['REGISTROS'][prop]['LINHA_DIGITAVEL']; 

     const codigoBarras = object['REGISTROS'][prop]['CODIGO_BARRAS']; 

     oracledb.getConnection({ 
       user: "x", 
       password: "xxx", 
       connectString: "mycon/string" 
      }, 
      function(err, connection) { 
       if (err) { 
        console.error(err.message); 
        return; 
       } 

       connection.execute(
        "INSERT INTO USU_TBOLETO VALUES (:USU_CODIGO, :USU_ATEND, :USU_PAGAMENTO, " + 
        ":USU_VENCIMENTO, :USU_PROCESSA, :USU_VALOR, :USU_NOSSONUM, :NUMERODOC, :USU_CODBANCO, " + 
        ":USU_LINHADIG , :USU_CODBARRAS)", 

        [codigo, atendimento, pagamento, vencimento, processamento, valor, nossoNumero, 
         numeroDocumento, codigoBanco, linhaDigitavel, codigoBarras 
        ], { 
         autoCommit: true 
        }, 
        function(err, result) { 

         if (err) { 
          console.error(err.message); 
          doRelease(connection); 
          return; 
         } 
         console.log(codigo + ' - ' + atendimento + ' - ' + pagamento + ' - ' + vencimento); 
         ///console.log(result.metaData); 
         ///console.log(result.rows); 
         doRelease(connection); 
        }); 
      }); 
    } 


    function doRelease(connection) { 
     connection.release(
      function(err) { 
       if (err) { 
        console.error(err.message); 
       } 
      } 
     ); 
    } 
} 

ループとクロージャの詳細を:

Javascript infamous Loop issue?

JavaScript closure inside loops – simple practical example

Asynchronous Process inside a javascript for loop

+0

あなたは@ abhishekkannoijaをロックします 私はあなたが私のために示したこのリンクを調査します。 –

関連する問題