Skip to main content

10. TypeOrm with MSSQL

https://typeorm.io/

Giới thiệu

TypeORM là một Object-Relational Mapper (ORM) cho TypeScript và JavaScript (ES7, ES6, ES5). Nó giúp bạn tạo ra các đối tượng và cơ sở dữ liệu chung, tạo và thực thi truy vấn.

MSSQL (Microsoft SQL Server) là một hệ thống quản lý cơ sở dữ liệu phổ biến của Microsoft.

Lý do kết hợp TypeORM và MSSQL

TypeORM:

  • Hỗ trợ TypeScript natively.
  • Tích hợp chặt chẽ với modern ES/TS.
  • Linh hoạt và mở rộng.

MSSQL:

  • Bảo mật cao.
  • Hiệu suất tốt.
  • Hỗ trợ tốt từ Microsoft và cộng đồng
  • Đã học từ trước.

Cài đặt các packages

npm install typeorm reflect-metadata mssql

Ví dụ

Mã nguồn

https://github.com/ngothanhtung/nodejs-tutorials/tree/main/Batch31/express-typescript

Cấu hình datasource

data-source.ts
import 'reflect-metadata';

import { DataSource } from 'typeorm';

export const AppDataSource = new DataSource({
type: 'mssql',
host: '113.160.224.121',
port: 1433,
username: 'developer',
password: 'developer',
database: 'TypeOrm',
entities: ['entities/**/*.entity{.ts,.js}'],
synchronize: true,
logging: false,
options: {
encrypt: false,
},
});

Tạo entity

entities/category.entity.ts
import { Column, Entity, PrimaryGeneratedColumn, BaseEntity, OneToMany } from 'typeorm';
import { Product } from './product.entity';

@Entity({ name: 'Categories' })
export class Category extends BaseEntity {
@PrimaryGeneratedColumn({ name: 'Id' })
id: number;

// ----------------------------------------------------------------------------------------------
// NAME
// ----------------------------------------------------------------------------------------------
@Column({ name: 'Name', unique: true, length: 50 })
name: string;

// ----------------------------------------------------------------------------------------------
// DESCRIPTION
// ----------------------------------------------------------------------------------------------
@Column({ name: 'Description', length: 500, nullable: true })
description: string;

// ----------------------------------------------------------------------------------------------
// RELATIONS
// ----------------------------------------------------------------------------------------------
@OneToMany(() => Product, (p) => p.category)
products: Product[];
}

Tạo router

routes/categories.ts
import express, { Express, Request, Response } from 'express';

import { AppDataSource } from '../data-source';
import { Category } from '../entities/category.entity';

const router = express.Router();

const repository = AppDataSource.getRepository(Category);

/* GET categories */
router.get('/', async (req: Request, res: Response, next: any) => {
try {
const categories = await repository.find();
if (categories.length === 0) {
res.status(204).send();
} else {
res.json(categories);
}
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});

/* GET category by id */
router.get('/:id', async (req: Request, res: Response, next: any) => {
try {
const category = await repository.findOneBy({ id: parseInt(req.params.id) });
if (!category) {
return res.status(404).json({ error: 'Not found' });
}
res.json(category);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});

/* POST category */
router.post('/', async (req: Request, res: Response, next: any) => {
try {
const category = new Category();
category.name = req.body.name;
category.description = req.body.description;
await repository.save(category);
res.status(201).json(category);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});

/* PATCH category */
router.patch('/:id', async (req: Request, res: Response, next: any) => {
try {
const category = await repository.findOneBy({ id: parseInt(req.params.id) });
if (!category) {
return res.status(404).json({ error: 'Not found' });
}

Object.assign(category, req.body);
await repository.save(category);

const updatedCategory = await repository.findOneBy({ id: parseInt(req.params.id) });
res.json(updatedCategory);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});

/* DELETE category */
router.delete('/:id', async (req: Request, res: Response, next: any) => {
try {
const category = await repository.findOneBy({ id: parseInt(req.params.id) });
if (!category) {
return res.status(404).json({ error: 'Not found' });
}
await repository.delete({
id: category.id,
});
res.status(200).send();
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});

export default router;

Bài tập CRUD với RESTful API

Cấu trúc database online-shop

Categories

IdColumn NameData TypeNullKeyDefaultConstraint
1IdintPKAUTONUMBER
2Namenvarchar(50)UNIQUE
3Descriptionnvarchar(500)yes

Suppliers

IdColumn NameData TypeNullKeyDefaultConstraint
1IdintPKAUTONUMBER
2Namenvarchar(100)
3Emailvarchar(50)UNIQUE
4PhoneNumbervarchar(50)UNIQUE
5Addressnvarchar(500)

Customers

IdColumn NameData TypeNullKeyDefaultConstraint
1IdintPKAUTONUMBER
2FirstNamenvarchar(50)
3LastNamenvarchar(50)
4Emailvarchar(50)UNIQUE
5PhoneNumbervarchar(50)UNIQUE
6Addressnvarchar(500)
7Birthdaydatetimeyes

Employees

IdColumn NameData TypeNullKeyDefaultConstraint
1IdintPKAUTONUMBER
2FirstNamenvarchar(50)
3LastNamenvarchar(50)
4Emailvarchar(50)UNIQUE
5PhoneNumbervarchar(50)UNIQUE
6Addressnvarchar(500)
7Birthdaydatetimeyes

Products

IdColumn NameData TypeNullKeyDefaultConstraint
1IdintPKAUTONUMBER
2Namenvarchar(100)
3Pricemoneyn > 0
4Discountdecimal(18,2)00 <= n <= 90
5Stockdecimal(18,2)0n >= 0
6Descriptionnvarchar(max)yes
7CategoryIdintFKRefrence to Categories (Id)
8SupplierIdintFKRefrence to Suppliers (Id)

Orders

IdColumn NameData TypeNullKeyDefaultConstraint
1IdintPKAUTONUMBER
2CreatedDatedatetimeNOW
3ShippedDatedatetimeyesn < CreatedDate
4Statusvarchar(50)WAITINGn in [WAINTING, COMPLETED, CANCEL]
5Descriptionnvarchar(max)
6ShippingAddressnvarchar(500)yes
7ShippingCitynvarchar(50)
8PaymentTypevarchar(20)CASHn in [CASH, CREDIT CARD]
9CustomerIdintFKRefrence to Customers (Id)
10EmployessIdintFKRefrence to Employees (Id)

Order Details

IdColumn NameData TypeNullKeyDefaultConstraint
1OrderIdintPK + FKRefrence to Orders (Id)
2ProductIdintPK + FKRefrence to Products (Id)
3Quantitydecimal(18,2)n > 0
4Pricedecimal(18,2)n > 0
5Discountdecimal(18,2)0 <= n <=90

1. Viết RESTful API cho Categories

  • Get all
  • Get by id
  • Create
  • Update by id
  • Delete by id

2. Viết RESTful API cho Suppliers

  • Get all
  • Get by id
  • Create
  • Update by id
  • Delete by id

3. Viết RESTful API cho Customers

  • Get all
  • Get by id
  • Create
  • Update by id
  • Delete by id

4. Viết RESTful API cho Employees

  • Get all
  • Get by id
  • Create
  • Update by id
  • Delete by id

5. Viết RESTful API cho Products

  • Get all
  • Get by id
  • Create
  • Update by id
  • Delete by id

6. Viết RESTful API cho Orders

  • Get all
  • Get by id
  • Create
  • Update by id
  • Delete by id