vueを使ってTypeORM(RDB)をChromeとChomeHeadlessとCorodva(ios)で動かしたときのメモと実行サンプル色々()

## 初めに

Corodva開発をするにあたって、とにかくギリギリまでbrowser開発で粘りたかったので、その辺をいい感じに吸収してくれるプロダクトを探したところTypeORMに当たりました。
本当に素晴らしいプロダクトだと思っています。
※0.2.0以降のTypeORMからWebSQLのサポートが外れました。。。


## vuejsに取込む

強引にglobal mixinしました

```javascript
import { createConnection, Connection, getConnection } from "typeorm"
const merge = require('webpack-merge')

let option = merge(process.env.DB_CONECT, {
      logger: new this.constructor.dbLogger(),
      entities: [...(省略)]
    }
let connection = await createConnection(option)

Vue.mixin({
  data() {
    return {
      connection: connection
    }
  },
})
```


## ChromeとCorodvaの切り替え

envファイルに持ちました
synchronizeはアプリケーションでタイミングを計りたかったので、自動実行させません。

* chrome+chromeheadless

```javascript
module.exports = merge(devEnv, {
  DB_CONECT: {
    type: '"websql"',
    database: '"..."',
    location: '"default"',
    logging: false,
    synchronize: false
  }
})
```
* cordova

```javascript
  DB_CONECT: {
    type: '"cordova"',
    database: '"..."',
    location: '"default"',
    logging: true,
    synchronize: false
  },
```


## 使い方色々

* entity  

テーブルと1:1

```javascript
import {BaseEntity, Entity, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, Column} from "typeorm";

@Entity('${テーブル名}')
export class ${テーブル名} extends BaseEntity {
    @PrimaryGeneratedColumn()
    id = undefined;

    @Column({
      type: "varchar",
      length: 6,
      nullable: false,
    })
    ${フィールド名} = new String();

    //...テーブルのフィールドを定義

    // 共通項目は自動で登録
    // 登録日時
    @CreateDateColumn()
    regist_datetime = new Date();


    // 更新日時
    @UpdateDateColumn()
    upd_datetime = new Date();
}

```


* select
    * 1件(findOne)  
    classオブジェクトが返却される  

    ```javascript
      let selectObj = await ${エンティティクラス}.findOne({
        ${フィールド名}: "検索条件"
      });
    ```

    * 複数件(find)  
    classオブジェクトのArrayが返却される  

    ```javascript
      let ${エンティティクラス} = await ${エンティティクラス}.find({
        ${フィールド名}: "検索条件"
      });
    ```

    * 検索オプション
 
    ```javascript
      const ${エンティティクラスのArray} = await ${エンティティクラス}.find({
        where: {
        ${フィールド名}: "検索条件"
          )
        },
        order: {
          ${フィールド名}: "ASC"
        }
      });

      // import無しでもgetRepositoryでエンティティは取れる
      const ${エンティティクラス} = this.connection.getRepository('${エンティティクラス}')
       ${エンティティクラス}.findOne({
          select: ['id'],
          where: {id: 1},
          order: {
            id: "ASC"
          }
      })
    ```
    * findオプション

    ```javascript
    select
    where
    relations(entity定義にリレーション定義を書くと使えます)
    join(entity定義にリレーション定義を書くと使えます)
    order
    cache
    ```

* insert+update  
entityクラスの`save`でinsert or updateとなる

    * insert

    ```javascript
      let ${エンティティクラス} = new ${エンティティクラス}()
      ${エンティティクラス}.xxx_cd = '001'
      // newしたrecordのsaveはinsert扱い
      ${エンティティクラス}.save()
    ```


    * update

    ```javascript
      let ${エンティティクラス} = await ${エンティティクラス}.findOne({
        xxx_cd: 001
      })
      ${エンティティクラス}.xxx_cd = '002'
      // selectしたrecordのsaveはupdate扱い
      ${エンティティクラス}.save()
    ```

* delete

    ```javascript
      let ${エンティティクラス} = await ${エンティティクラス}.findOne({
        xxx_cd: 001
      })
      // selectしたrecordにremoveでdeleteとなる
      ${エンティティクラス}.remove()
    ```

* transaction制御

    ```javascript
    const vm = this
    const transactionFunction = async (manager) => {
      let ${エンティティクラス} = await ${エンティティクラス}.findOne({
        xxx_cd: 001
      })
      ${エンティティクラス}.xxx_cd = '002'
      ${エンティティクラス}.save()

      let ${エンティティクラス} = await ${エンティティクラス}.findOne({
        xxx_cd: 002
      })
      ${エンティティクラス}.remove()

    }
    this.connection.transaction(transactionFunction).catch(error => {throw error} )
    ```

* bulk

    ```javascript
        await this.connection.createQueryBuilder()
          .insert()
          .into(${table_name})
          .values(parameters)
          .execute();
    ```

* join
  本当はEntityクラスにリレーション定義するんですけど・・・

    ```javascript
          let items = await Items.createQueryBuilder("${エンティティ名}")
            .innerJoin(
              ${joinしたいエンティティ名},
              "${別名}",
              "Items.item_cd = ${joinしたいエンティティ名}.item_cd AND ${joinしたいエンティティ名}.pos_dept_key_typ = :${条件のシンボル}",
              {
                ${条件のシンボル}: ${条件の変数}              }
            )
            .where("Items.start_date <= :nowDate", {
              nowDate: this.formatYmd(new Date())
            })
            .andWhere("Items.end_date >= :nowDate", {
              nowDate: this.formatYmd(new Date())
            })
            .getRawMany();
    ```


* query

    ```javascript
      this.connection
        .createQueryRunner()
        .query(`
            SELECT
              NAME AS NAME
            FROM
              SQLITE_MASTER
        `)
        .then(resolve => {
          vm.queryResult = JSON.stringify(resolve, null, "  ");
        })
        .catch(reject => {
          vm.queryResult = reject.stack
            ? reject.stack
            : JSON.stringify(reject, null, "  ");
        });

    ```

ここまで
これでブラウザで開発出来てそのままCorodvaで動くので便利感ただ事ではないです。