😎

Quick Start TypeORM

2024/01/11に公開

概要

https://typeorm.io/ を試します。

環境

  • TypeScript
  • MySQL(docker)

流れ

  • プロジェクト作成
  • DockerでMySQL起動
  • TypeORMでmigration
  • サンプルプログラム実行

実装

プロジェクト作成

mkdir 20240111_typeorm
cd 20240111_typeorm
npm install typeorm reflect-metadata mysql2 --save

npx typeorm init --database mysql

Project created inside current directory.
Please wait, installing dependencies...
Done! Start playing with a new project!

こんな感じの構成になります。

tree -I node_modules
.
├── README.md
├── package-lock.json
├── package.json
├── src
│   ├── data-source.ts
│   ├── entity
│   │   └── User.ts
│   ├── index.ts
│   └── migration
└── tsconfig.json

DockerでMySQL起動

# docker-compose.yml
version: '3.8'
services:
  mysql:
    image: mysql:8.2
    environment:
      MYSQL_DATABASE: 'sampledb'
      MYSQL_USER: 'example_user'
      MYSQL_PASSWORD: '<example_user_password>'
      MYSQL_ROOT_PASSWORD: '<root_password>'
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql
volumes:
  mysql_data:

起動

# 起動
docker-compose up -d

# 確認
docker-compose ps
NAME                       IMAGE               COMMAND                  SERVICE             CREATED             STATUS              PORTS
20240111_typeorm-mysql-1   mysql:8.2           "docker-entrypoint.s…"   mysql               5 seconds ago       Up 4 seconds        0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp

# 接続確認
mysql -h 127.0.0.1 -u example_user -p sampledb
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 8.2.0 MySQL Community Server - GPL

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

TypeORMのdata-source.ts修正

# data-source.ts
import "reflect-metadata"
import { DataSource } from "typeorm"
import { User } from "./entity/User"

export const AppDataSource = new DataSource({
    type: "mysql",
    host: "127.0.01",
    port: 3306,
    username: "example_user",
    password: "<example_user_password>",
    database: "sampledb",
    synchronize: true,
    logging: false,
    entities: [User],
    migrations: ["src/migration/*.ts"],  // ※1
    subscribers: [],
})

※1 最初ここを空欄にして実行してたのでうまくいきませんでした・・・

Migrationファイル生成

# 生成
npx typeorm-ts-node-commonjs migration:generate -d src/data-source.ts ./src/migration/CreateUsers
Migration /home/tsaeki/Develop/20240111_typeorm/src/migration/1704971255992-CreateUsers.ts has been generated successfully.

src/migration/{TIMESTAMP}-CreateUsers.ts が生成されます

# src/migration/{TIMESTAMP}-CreateUsers.ts
import { MigrationInterface, QueryRunner } from "typeorm";

export class CreateUsers1704971255992 implements MigrationInterface {
    name = 'CreateUsers1704971255992'
    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`CREATE TABLE \`user\` (\`id\` int NOT NULL AUTO_INCREMENT, \`firstName\` varchar(255) NOT NULL, \`lastName\` varchar(255) NOT NULL, \`age\` int NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`);
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`DROP TABLE \`user\``);
    }
}

Migration実行

# 実行
npx typeorm-ts-node-commonjs migration:run -d src/data-source.ts

query: SELECT VERSION() AS `version`
query: SELECT * FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = 'sampledb' AND `TABLE_NAME` = 'migrations'
query: CREATE TABLE `migrations` (`id` int NOT NULL AUTO_INCREMENT, `timestamp` bigint NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB
query: SELECT * FROM `sampledb`.`migrations` `migrations` ORDER BY `id` DESC
0 migrations are already loaded in the database.
1 migrations were found in the source code.
1 migrations are new migrations must be executed.
query: START TRANSACTION
query: CREATE TABLE `user` (`id` int NOT NULL AUTO_INCREMENT, `firstName` varchar(255) NOT NULL, `lastName` varchar(255) NOT NULL, `age` int NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB
query: INSERT INTO `sampledb`.`migrations`(`timestamp`, `name`) VALUES (?, ?) -- PARAMETERS: [1704971255992,"CreateUsers1704971255992"]
Migration CreateUsers1704971255992 has been  executed successfully.
query: COMMIT

userテーブルが作成されてることを確認します。

mysql -h 127.0.0.1 -u example_user -p sampledb -e 'desc user'
Enter password:
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int          | NO   | PRI | NULL    | auto_increment |
| firstName | varchar(255) | NO   |     | NULL    |                |
| lastName  | varchar(255) | NO   |     | NULL    |                |
| age       | int          | NO   |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+

サンプルスクリプトを実行

src/index.ts を実行してみます。
firstName: Timber、lastName: Saw、が登録されます

ts-node src/index.ts

Inserting a new user into the database...
Saved a new user with id: 1
Loading users from the database...
Loaded users:  [ User { id: 1, firstName: 'Timber', lastName: 'Saw', age: 25 } ]
Here you can setup and run express / fastify / any other framework.

実際にテーブルを確認します。

mysql -h 127.0.0.1 -u example_user -p sampledb -e 'select * from user'
Enter password:
+----+-----------+----------+-----+
| id | firstName | lastName | age |
+----+-----------+----------+-----+
|  1 | Timber    | Saw      |  25 |
+----+-----------+----------+-----+

参考

Discussion