node.js(TypeScript) でMySQL

node.js(TypeScript) でMySQL:

node.jsでMySqlのDBを操作する機会があったので備忘録としてまとめます。


まずTypeScriptのコンパイル環境をつくる

完全に好みが分かれると思いますが、TypeScriptで書きたくなりました。

npm i -g typescript 
npm i -g tsc 


下準備

DB操作は非同期処理になります。

TypeScriptで async/awaitが使えるようにしておきます。

tsconfig.json
{ 
  "compilerOptions": { 
  "lib": ["es2015"] 
} 
 


mysqljs

nodeでのMySQL操作はこちらを利用しました。
https://github.com/mysqljs/mysql

npm i --save mysql @types/mysql 


ハマりポイント


非同期処理

基本的なDB操作は公式のとおりなので割愛しますが、

複数の更新操作をする場合、前の更新が終わってから次の更新を行う必要があると思います。

先ほど下準備した async/awaitの出番、と思ってこう書きました。

index.ts
import * as mysql from 'mysql'; 
 
// DB接続情報を定義 
export interface DbConfig { 
    host: string; 
    user: string; 
    password: string; 
    database: string; 
} 
const dbConfig: DbConfig = { 
    host: 'HOST_NAME', 
    user:'USER_NAME', 
    password:'PW', 
    database:'DB' 
};  
// 接続 
const pool = mysql.createPool(dbConfig); 
 
/** INSERT用のasync関数 */ 
async function insertRecord(tableName: string, data: any) { 
    try { 
        const sql: string = mysql.format(`INSERT INTO ${tableName} SET ?`, data); 
        return await pool.query(sql) as any; 
    } catch (err) { 
        pool.end(); 
        throw new Error(err); 
    } 
} 
 
(async () => { 
  try{ 
  // 挿入するレコードを準備 
   const insertRecord: any = { 
   name: 'hoge' 
  }; 
 
 // 挿入処理 
  const result =  await insertRecord('TABLE_NAME', insertRecord); 
 
 // 挿入結果のレコードIDをコンソール出力 
  console.log(result.insertId); 
  pool.end(); 
 
 } catch (err) { 
   pool.end(); 
   throw  new Error(err);     
 } 
})(); 


でも結果は、レコードは挿入されますが、コンソール出力はされませんでした。



原因


mysqljsライブラリのpool.queryがPromiseを返してくれない

pool.query はPromiseを返してくれないので、非同期処理が終わっても待ち状態のままになります。

下の3行追加することで解決しました。

index.ts
import * as util from 'util'; 
 
const pool = mysql.createPool(dbConfig); 
 
// @ts-ignore 
pool.query = util.promisify(pool.query); 
 
pool.query = util.promisify(pool.query); とすることで、 Promise を返すように上書きしています。

※TypeScriptだとコンパイルのときに型のエラーがでたのでスルーしてもらうために @ts-ignore を1行上に追加しています。


そのほかのハマりポイント


TypeScriptのビルド

すごくしょうもないですが、 index.ts にいろいろ書いて、下記のようにファイル名を指定してビルドを実行するとtsconfig.jsonの内容が反映されません。

# ファイル指定はだめ 
tsc index.ts 
 
# OK 
tsc 
 


forEachはPromiseをみてくれない

forEachの中でasync functionをつかっても、Promiseのリターンを待たずにつぎにいってしまいます。

forEach自体にasyncとかつけても変わりません。

おとなしくfor文を使いました。


最後に

nodeでMySQLですが、挿入したレコードのidを取得して別のレコードのカラムを更新するのが楽にできて便利でした。

トランザクションロールバックの処理まで記事にしようと思いましたが、長くなったので書いたコードだけ上げておきます。

index.ts
/** 
 * INSERT,UPDATE,DELETEなど、 
 * エラー時のTransaction Rollbackを必要とするsqlの発行に使用 */ 
async function editRecordOfTransactionRollback(sql: string) { 
    console.log(sql); 
    return await new Promise((resolve => { 
        pool.getConnection((err, connection) => { 
            if (err) { 
                connection.release(); 
                pool.end(); 
                throw err; 
            } 
            connection.beginTransaction(err1 => { 
                if (err1) { 
                    connection.release(); 
                    pool.end(); 
                    throw err1; 
                } 
                connection.query(sql, (error, results) => { 
                    if (error) { 
                        connection.rollback(() => { 
                            connection.release(); 
                            pool.end(); 
                            throw error; 
                        }); 
                    } else { 
                        connection.commit((err2 => { 
                            if (err2) { 
                                connection.rollback(() => { 
                                    connection.release(); 
                                    pool.end(); 
                                    throw err2; 
                                }); 
                            } else { 
                                connection.release(); 
                                resolve(results); 
                            } 
                        })); 
                    } 
                }); 
            }); 
        }); 
    })) as Promise<any>; 
} 
 

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)