iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 20
0
Modern Web

Nest.js framework 30天初探系列 第 20

Nestjs framework 30天初探:Day20 TypeORM(MSSQL)

TypeORM

Sequelize ORM方面已經做得很好了,不過現在有一個完全就是for TypeScript的ORM模組出現,就是TypeORMTypeORM支援MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, WebSQL,而且支援平台眾多,如:Browser, Ionic, Cordova and Electron。(想多瞭解可以看這篇中文翻譯http://www.cnblogs.com/brookshi/p/6446155.html)
這還蠻吸引筆者的目光,當然要來點開TypeORM技能,不用擔心這不好學,花不到一小時改一下Sequelize ORM的寫法,換成TypeORM的寫法,整個就搞定了XDDDD。

  1. 沿用Day19完成的專案,還沒開表的大大,可以用下方的SQL Script開表一下。
USE [IronManNest]
GO

/****** Object:  Table [dbo].[Users]    Script Date: 2017/12/20 下午 10:47:14 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Users](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Name] [nvarchar](50) NULL,
	[Age] [int] NULL,
 CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
  1. 裝一下本次要用到的模組。
    cmd 指令
npm install --save @nestjs/typeorm mssql typeorm
  1. 改寫一下users.entity.ts,改成TypeORM對於數據模型的定義。
    src/app/Users/users.entity.ts
'use strict';

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

@Entity()
export class Users {
    //主鍵,SQL Server識別種子
    @PrimaryGeneratedColumn()
    ID: number;

    @Column({ length: 50 })
    Name: string;

    @Column('int')
    Age: number;
}
  1. 修改一下databaseProviders。
    src/app/database.provider.ts
'use strict';

import { createConnection } from 'typeorm';

export const databaseProviders = [
    {
        provide: 'TypeORMInstance',
        useFactory: async () => await createConnection({
            type: 'mssql',
            host: 'localhost',
            port: 1433,
            username: 'sa',
            password: 'Aa123456',
            database: 'IronManNest',
            entities: [
                __dirname + '/Users/*.entity{.ts,.js}'
            ]
        })
    }
]

entities屬性可以直接load進整個目錄的entity.ts,這還蠻方便的。

  1. 修改一下,UsersProvider。
    src/app/Users/users.providers.ts
'use strict';

import { Users } from './users.entity';
import { Connection, Repository } from 'typeorm';
export const UsersProvider = {
    provide: 'UsersRepository',
    useFactory:(connection:Connection)=>connection.getRepository(Users),
    inject:['TypeORMInstance']
}
  1. 修改一下UsersServices,改一下constructor注入和換成TypeORM的CRUD方法,整體改動不大。
'use strict';

import { Component, Inject } from '@nestjs/common';
import { Users } from './users.entity';
import { IUsers, IUsersService } from './interfaces/index';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';

@Component()
export class UsersServices implements IUsersService {
    constructor(
        @InjectRepository(Users)
        private readonly usersRepository: Repository<Users>) { }

    public async findAll(): Promise<Array<Users>> {
        return await this.usersRepository.find();
    }

    //findOne()可以加入各種option,以下示範常見的where
    //注意findOne() 找到一筆就會立即return data,不會繼續往下找。
    public async findOne(options: Object): Promise<Users | null> {
        return await this.usersRepository.findOne(options);
    }

    //restful API很常用。
    public async findById(ID): Promise<Users | null> {
        return await this.usersRepository.findOneById(ID);
    }

    public async create(users: IUsers): Promise<Users> {
        return await this.usersRepository.create(users);
    }

    public async update(ID: number, newValue: IUsers): Promise<Users | null> {
        //先找出單筆資料
        let user = await this.usersRepository.findOneById(ID);
        //該筆資料不存在
        if (!user.ID) {
            console.error("user doesn't exist");
        }
        //呼叫user Model的方法
        await this.usersRepository.updateById(ID, newValue);
        return await this.usersRepository.findOneById(ID);
    }

    public async delete(ID: number): Promise<number> {
        //成功會回傳1,失敗回傳0
        await this.usersRepository.deleteById(ID);
        let user = await this.usersRepository.findOneById(ID);
        if (!user) {
            //刪除成功
            return 1;
        }
        else {
            //刪除失敗
            return 0;
        }
    }
}

比Sequelize寫法更為簡化也更直覺,像updateById(),可以傳入兩個參數,一個是ID,一個是新數據,內建就是部分更新,不用更新完整的資料。

  1. 實測一下CRUD。
    查詢全部
    請打開Postman,對http://localhost:3000/users 做GET請求。
    https://ithelp.ithome.com.tw/upload/images/20171223/20107195GrJHrSBTfQ.png
    單筆查詢
    請打開Postman,對http://localhost:3000/users/3 做GET請求。
    https://ithelp.ithome.com.tw/upload/images/20171223/201071956zGgXP4XTu.png
    新增單筆資料
    請打開Postman,對http://localhost:3000/users 做POST請求。
    https://ithelp.ithome.com.tw/upload/images/20171223/201071956j0OM6snuE.png
    修改單筆資料
    請打開Postman,對http://localhost:3000/users/3 做PATCH請求。
    https://ithelp.ithome.com.tw/upload/images/20171223/201071958hvW1JWvhP.png
    刪除單筆資料
    請打開Postman,對http://localhost:3000/users/3 做DELETE請求。
    https://ithelp.ithome.com.tw/upload/images/20171223/20107195EGIG1JVdV4.png

整體我覺得TypeORM蠻不錯的,尤其是支援WebSQL,寫法也比Sequelize來得更好,不過生態還不成熟,Prod產品可能還不適合導入,但切入學習是很OK的易上手。

程式碼都在github


上一篇
Nestjs framework 30天初探:Day19 Swagger
下一篇
Nestjs framework 30天初探:Day21 Passport(搭配JWT)
系列文
Nest.js framework 30天初探30

尚未有邦友留言

立即登入留言