Skip to content

TypeORMでDBアクセス#

TypeORMはTypeScriptを使ってデータベースに情報を保存するためのライブラリです。

ここでは、これまでに作ったアプリケーションに、アンケートをデータベースに保存する機能を追加します。

前提条件#

アプリケーションの作成 を行ってください。 データベースはDockerというアプリケーションを使って起動します。Dockerをインストールしてください。

TypeORMのインストール#

以下のコマンドをnpmプロジェクトのルートで実行してください。

npm install typeorm

今回はデータベースはPostgreSQLというデータベースを使用します。PostgreSQLにつなぐためのコネクタをインストールします。

npm install pg

tsconfig.jsonをTypeORM用に設定します。

{
  "include": [
    "src/backend/**/*"
  ],
  "compilerOptions": {
//  "target": "es5",//行の先頭に//を入れて無効化。
    "target": "es6",// この行を追加
    "emitDecoratorMetadata": true,// この行を追加
    "experimentalDecorators": true,// この行を追加
    "module": "commonjs",
    "outDir": "./dist",
    "rootDir": "./src/backend",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

これでTypeORMの設定が完了しました。

DockerでPostgreSQLを起動#

Dockerとは、コンテナと呼ばれる仮想環境上でアプリケーションを動作させるアプリケーションです。 手元のマシンに直接アプリケーションをインストールすると、インストールしたものが他に悪さをするときがあるのですが、Dockerであればすぐに消せるので、お手軽にいろいろなアプリケーションを動作させることができます。

DockerでPostgreSQLを起動します。 ターミナルを新しく立ち上げて、以下のコマンドを実行してください。

docker run --name postgres -e POSTGRES_PASSWORD=postgres -d -p 5432:5432 postgres:10-alpine

これでPostgreSQLが起動しました。

TypeORMでDB接続を行う。#

前回アンケートをとる画面を作りました。 ここでは、入力してもらったアンケートをデータベースに保存します。

まずはデータベースに保存するためのアンケートの構造を定義します。定義はTypeScriptで行います。

定義のファイルをおくディレクトリを作成します。

mkdir src/backend/models

src/backend/models/Enquete.ts を作成します。内容は以下です。

import { Entity, PrimaryGeneratedColumn, Column, BaseEntity } from 'typeorm'

@Entity()
export default class Enquete extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id: number = 0

  @Column()
  public point: number = 0

  @Column()
  public message: string = ""

  @Column()
  public mail: string = ""
}

続けて、データベースへの保存処理と取得処理を作成します。 今回はWebAPIとして、データベースの保存、一覧取得を作成します。

src/backend/controllers/enquete.ts を作成し、内容は以下にしてください。

import express, { Router } from 'express'
import { getRepository } from 'typeorm'
import Enquete from '../models/Enquete'

var router: Router = express.Router();

router.post('/', function (req, res) {
    const enquete = req.body;
    const EnqueteRepository = getRepository(Enquete);
    EnqueteRepository.save(enquete);
    res.send(enquete);
});
export default router;

続いて、サーバ起動時にデータベースに接続するようにします。 src/backend/index.ts を以下のように修正してください。

import express from 'express'
import messageController from './controllers/message'
import enqueteController from './controllers/enquete'//この行を追加
import {createConnection} from 'typeorm'//この行を追加

import Enquete from './models/Enquete'//この行を追加

const app: express.Express = express()

app.use(express.json())
app.use(express.urlencoded({ extended: true }))

app.use("/messages", messageController)
app.use("/api/enquetes", enqueteController)//この行を追加
app.use("/", express.static(__dirname + "/public"))

/* ここから */
!async function initialize(){
    await createConnection({
        type: "postgres",
        url: process.env.DATABASE_URL || "postgres://postgres:postgres@127.0.0.1:5432/postgres",
        synchronize: true,
        entities: [
            Enquete,
        ],
        extra: {
            ssl: (!!process.env.DATABASE_SSL) ? {
                rejectUnauthorized: false,
            } : false,
        }
    });
/* ここまで追加 */
    // 3000番ポートでAPIサーバ起動
    app.listen(3000, () => {
        console.log('ポート3000番で起動しましたよ!')
    })
}()//この行を追加

app.listenでWebサーバが起動するのですが、その前にデータベースに接続を行っています。

ここまでできたら、Vueからサーバに通信してAPIを呼んでみます。

Vueからサーバに通信を行う。#

Vueアプリからサーバに通信を行うためにはAxiosというライブラリを利用します。

Axiosをインストールします。ターミナルで、npmプロジェクトのルートで以下のコマンドを実行してください。

npm install axios

続いて、src/front/components/PostEnquete.vue を更新します。 2行、script タグの中に追加します。

<template>
  <div>
    <h1>{{title}}</h1>
      <p>{{description}}</p>
    <div v-if="!posted"><!-- 入力エリア ここから -->
      <div>
        <input type="radio" id="5" value="5" v-model="enquete.point"><label for="5">5点</label>
        <input type="radio" id="4" value="4" v-model="enquete.point"><label for="4">4点</label>
        <input type="radio" id="3" value="3" v-model="enquete.point"><label for="3">3点</label>
        <input type="radio" id="2" value="2" v-model="enquete.point"><label for="2">2点</label>
        <input type="radio" id="1" value="1" v-model="enquete.point"><label for="1">1点</label>
      </div>
      <div>
        <p>ご意見・ご要望</p>
        <textarea v-model="enquete.message"></textarea>
      </div>
      <div>
        <p>メールアドレス</p>
        <input type="mail" v-model="enquete.mail" />
      </div>
      <div>
        <button @click="sendMessage()">アンケート送信</button>
      </div>
    </div><!-- 入力エリア ここまで-->
    <div v-else><!-- 結果エリア ここから -->
      <div>
        点数{{enquete.point}}      </div>
      <div>
        <p>ご意見・ご要望</p>
        <p>{{enquete.message}}</p>
      </div>
      <div>
        <p>メールアドレス</p>
        <p>{{enquete.mail}}</p>
      </div>
    </div><!-- 結果エリア ここまで -->
  </div>
</template>
<script lang="ts">
import Vue from "vue";
import axios from "axios";//この行を追加

export default Vue.extend({
  data() {
    return {
      title: "アンケート",
      description: "良かったですか?5点(高い) から 1点(低い) で点数をつけてください。",
      enquete: {},
      posted: false
    };
  },
  methods: {
      sendMessage(){
        this.description = "アンケート送信をありがとうございました。";
        axios.post("/api/enquetes/", this.enquete);//この行を追加
        this.posted = true;
      }
  }
});
</script>

これで、アンケートをデータベースに保存できるようになりました! では確認してみます。

ブラウザで http://localhost:3000にアクセスしてください。 アンケートを入力します。 アンケート入力 アンケート送信ボタンを押してください。 アンケート送信完了

これで、アンケートが登録されました。

データベースの中をみて、アンケート内容を確認してみましょう。

ターミナルで以下のコマンドを実行します。

docker exec -it postgres psql -U postgres

これでPostgreSQLにログインしています。 続いて、同じターミナルでselect文を実行します。

select * from enquete;

すると、以下のような表示がされます。

 id | point |     message      |        mail
----+-------+------------------+--------------------
  1 |     5 | とても最高です | ukiuni@example.com
(1 row)

アンケート内容が保存されていることを確認できますね! データベースの中を見るためには、SQLというコマンドを発行します。 ここでは、enqueteからすべてを出力する、ということをしています。

\q と打って、Enterキーを押せば、PostgreSQLから抜けることができます。

これで、アンケートを収集できるようになりました。

次は、アンケート結果を一覧で見れるように、アンケート入力画面とは別に、アンケート一覧表示画面を作れるようにします。