TypeORM - Hướng dẫn nhanh

Khung TypeORM là một Object Relational Mapping (ORM)khuôn khổ. Nói chung,Object phần đề cập đến miền / mô hình trong ứng dụng của bạn, Relational phần đề cập đến mối quan hệ giữa các bảng trong Hệ thống quản lý cơ sở dữ liệu quan hệ (ví dụ: Oracle, MySQL, MS-SQL, PostgreSQL, v.v.) và cuối cùng là Mapping một phần đề cập đến hành động làm cầu nối giữa mô hình và các bảng của chúng tôi.

ORM là một loại công cụ ánh xạ các thực thể với các bảng cơ sở dữ liệu. ORM cung cấp quy trình phát triển đơn giản hóa bằng cách tự động chuyển đổi đối tượng sang bảng và bảng thành đối tượng. Khi bạn có thể viết mô hình dữ liệu của mình ở một nơi, việc cập nhật, bảo trì và sử dụng lại mã trở nên dễ dàng hơn.

Vì mô hình bị ràng buộc yếu với phần còn lại của ứng dụng, bạn có thể thay đổi mô hình này mà không phụ thuộc vào phần khác của ứng dụng và có thể dễ dàng sử dụng nó ở bất kỳ đâu bên trong ứng dụng. TypeORM rất linh hoạt, trừu tượng hóa hệ thống DB khỏi ứng dụng và cho phép chúng ta hưởng lợi từ việc sử dụng khái niệm OOPS.

Tổng quat

TypeORM là một thư viện Object Relational Mapper chạy trong node.js và được viết bằng TypeScript. TypeScript là một cải tiến của JavaScript với cách gõ tùy chọn. TypeScript là một ngôn ngữ biên dịch. Nó không được diễn giải trong thời gian chạy. Trình biên dịch TypeScript lấy các tệp TypeScript (.ts) và biên dịch chúng sang các tệp JavaScript (.js).

TypeORM hỗ trợ nhiều cơ sở dữ liệu như MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, SAP Hana và WebSQL. TypeORM là ORM dễ sử dụng để tạo các ứng dụng mới kết nối với cơ sở dữ liệu. Chức năng TypeORM là các khái niệm dành riêng cho RDBMS.

Chúng tôi có thể nhanh chóng tạo các dự án và dịch vụ vi mô mới. Nó được lấy cảm hứng từ công cụ tương tự như Hibernate, Doctrine, Entity framework, v.v., từ các ngôn ngữ lập trình khác.

Đặc điểm của TypeORM

TypeORM đi kèm với các tính năng sau:

  • Tự động tạo lược đồ bảng cơ sở dữ liệu dựa trên các mô hình của bạn.
  • Dễ dàng chèn, cập nhật và xóa đối tượng trong cơ sở dữ liệu.
  • Tạo ánh xạ (một-một, một-nhiều và nhiều-nhiều) giữa các bảng.
  • Cung cấp các lệnh CLI đơn giản.

Lợi ích của TypeORM

TypeORM rất dễ sử dụng khung ORM với mã hóa đơn giản. Nó có những lợi ích sau:

  • Các ứng dụng chất lượng cao và được ghép nối lỏng lẻo.
  • Các ứng dụng có thể mở rộng.
  • Dễ dàng tích hợp với các mô-đun khác.
  • Hoàn toàn phù hợp với mọi kiến ​​trúc từ ứng dụng nhỏ đến ứng dụng doanh nghiệp.

Chương này giải thích về cách cài đặt TypeORM trên máy của bạn. Trước khi chuyển sang cài đặt, hãy đảm bảo rằng npm đã được cài đặt. Để xác nhận rằng bạn có npm, bạn có thể chạy lệnh sau trong thiết bị đầu cuối của mình.

npm -v

Nó hiển thị phiên bản. Nếu nó chưa được cài đặt, hãy tải xuống phiên bản mới nhất và cài đặt trên máy của bạn.

Cài đặt TypeORM

Hãy để chúng tôi cài đặt TypeORM cục bộ bằng mô-đun npm -

npm install typeorm --save

Sau khi thực hiện lệnh trên, bạn sẽ nhận được phản hồi như bên dưới:

+ [email protected] 
+ 
added 1 package and audited 1236 packages in 4.729s

Ngoài ra, để cài đặt TypeORM trên toàn cầu, hãy sử dụng lệnh dưới đây:

npm install typeorm -g

Sau đó, cài đặt siêu dữ liệu phản ánh gói tùy chọn sử dụng npm -

npm install reflect-metadata --save

Bạn có thể thấy phản hồi sau:

+ [email protected] 

added 1 package and audited 1236 packages in 2.426s

Bây giờ, hãy cài đặt một gói tùy chọn khác. gõ nút bằng lệnh dưới đây:

npm install @types/node --save

Bạn có thể thấy phản hồi sau:

+ @types/[email protected] 

added 1 package and audited 1236 packages in 2.167s

Cài đặt trình điều khiển cơ sở dữ liệu

Trong phần này, hãy để chúng tôi cài đặt các gói nút cần thiết cho cơ sở dữ liệu của chúng tôi.

Để cài đặt MySQL hoặc là MariaDB gói, sử dụng lệnh dưới đây -

npm install mysql --save

Bạn có thể thấy phản hồi sau:

+ [email protected] 

added 1 package and audited 1236 packages in 4.36s

Để cài đặt PostgreSQL gói, sử dụng lệnh dưới đây -

npm install pg --save

Bạn có thể thấy phản hồi sau:

+ [email protected] 

added 1 package and audited 1236 packages in 2.863s

Để cài đặt SQLite gói, sử dụng lệnh dưới đây -

npm install sqlite3 --save

Bạn có thể thấy phản hồi sau:

+ [email protected] 
added 48 packages from 45 contributors and audited 1396 packages in 7.31s

Để cài đặt Microsoft SQL Server gói, sử dụng lệnh dưới đây -

npm install mssql --save

Màn hình của bạn trông tương tự như thế này,

+ [email protected] 

added 1 package and audited 1655 packages in 2.378s

Để cài đặt sql.js gói, sử dụng lệnh dưới đây -

npm install sql.js --save

Bạn có thể thấy phản hồi sau:

+ [email protected] 

added 1 package and audited 1655 packages in 6.462s

Để cài đặt Oracle server gói, sử dụng lệnh dưới đây -

npm install oracledb --save

Bạn có thể thấy phản hồi sau:

+ [email protected] 

added 1 package and audited 1655 packages in 2.265s

Để cài đặt mongodb gói, sử dụng lệnh dưới đây -

npm install mongodb --save

Bạn có thể thấy phản hồi sau:

+ [email protected] 

added 1 package and audited 1655 packages in 3.716s

Chương này giải thích về cách tạo ứng dụng TypeORM đơn giản. Hãy để chúng tôi tạo một thư mục mới có tên 'TypeORM' và chuyển vào thư mục.

cd /path/to/TypeORM/

Cú pháp

Sử dụng lệnh dưới đây để tạo dự án mới -

typeorm init --name <project-name> --database <database-name>

Thí dụ

typeorm init --name FirstProject --database mysql

Đây,

FirstProject là tên dự án của bạn và sqlite3là tên cơ sở dữ liệu. Sau khi thực hiện lệnh trên, bạn có thể thấy phản hồi sau:

Project created inside /path/to/TypeORM/FirstProject directory

Bây giờ, hãy chuyển đến thư mục dự án của chúng tôi và cài đặt các phụ thuộc dự án bằng npm mô-đun,

$ cd FirstProject $ npm install

Cấu trúc dự án

Hãy cho chúng tôi hiểu cấu trúc dự án của dự án mới tạo của chúng tôi, FirstProject.

FirstProject 
├──> src 
│ ├──> entity 
│ │ └──> User.ts 
│ ├──> migration 
│ └──> index.ts 
├──> node_modules 
├──> ormconfig.json 
├──> package.json 
├──> package-lock.json 
└──> tsconfig.json

Đây,

  • src - chứa mã nguồn của ứng dụng của bạn trong TypeScriptngôn ngữ. Nó có một tập tinindex.ts và hai thư mục con entitymigration.
  • index.ts - Điểm vào ứng dụng của bạn.
  • entity - Chứa các mô hình cơ sở dữ liệu.
  • migration - chứa mã di chuyển cơ sở dữ liệu.
  • node_modules - các mô-đun npm được lưu cục bộ.
  • ormconfig.json- Tệp cấu hình chính của ứng dụng của bạn. Nó chứa chi tiết cấu hình cơ sở dữ liệu và cấu hình thực thể.
  • package.json - Chứa các phụ thuộc mô-đun nút.
  • package-lock.json - Tệp được tạo tự động và liên quan đến package.json.
  • tsconfig.json - Chứa các tùy chọn trình biên dịch cụ thể của TypeScript.

tệp ormconfig.json

Hãy để chúng tôi kiểm tra tùy chọn cấu hình có sẵn cho ứng dụng của chúng tôi. Mở tệp ormconfig.json và nó trông giống như sau:

{ 
   "type": "mysql", 
   "host": "localhost", 
   "port": 3306, 
   "username": "test", 
   "password": "test", 
   "database": "test", 
   "synchronize": true, 
   "logging": false, 
   "entities": [ 
      "src/entity/**/*.ts" ], 
   "migrations": [ "src/migration/**/*.ts" 
   ], 
   "subscribers": [ "src/subscriber/**/*.ts" 
   ], 
   "cli": { 
      "entitiesDir":"src/entity", "migrationsDir":"src/migration", "subscribersDir":"src/subscriber
   }    
 }

Đây,

type, host, username, password, database và các tùy chọn cổng có liên quan đến thiết lập cơ sở dữ liệu. mysql có thể được định cấu hình bằng cách sử dụng cấu hình dưới đây -

{ 
   "type": "mysql", 
   "host": "localhost", 
   "port": 3306, 
   "username": "db_username", "password": "db_password", "database": "db_name" 
}
  • entities - đề cập đến vị trí của các lớp thực thể của bạn.
  • migrations - đề cập đến vị trí của các lớp di chuyển của bạn.
  • subscribers - đề cập đến vị trí của các lớp thuê bao của bạn.
  • cli - đề cập đến tùy chọn được sử dụng bởi TypeORM CLI để tự động tạo mã

Khởi động máy chủ MySql

Trước khi bắt đầu ứng dụng, hãy bắt đầu MySQL máy chủ hoặc bất kỳ máy chủ cơ sở dữ liệu nào do bạn sử dụng và đảm bảo rằng nó đang chạy bình thường.

Chạy ứng dụng

Sau khi mọi thứ được cấu hình, chúng ta có thể thực thi ứng dụng bằng lệnh dưới đây:

npm start

Bạn có thể thấy phản hồi sau:

> [email protected] start /Users/../../TypeORM/FirstProject 

> 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/koa/any other framework.

Ứng dụng đã chèn một người dùng mới vào cơ sở dữ liệu và sau đó tải ngược lại từ cơ sở dữ liệu và cuối cùng hiển thị người dùng đã tải trong bảng điều khiển. Chúng tôi đã tạo thành công mộtTypeORM ứng dụng, đã cấu hình nó và chạy ứng dụng.

Chúng ta sẽ thảo luận về cách dữ liệu được thực thi công phu trong các chương sắp tới.

Để tương tác với cơ sở dữ liệu, chúng ta cần một đối tượng kết nối với cơ sở dữ liệu. Chúng ta cần tạo một đối tượng kết nối trước khi thực hiện thao tác với cơ sở dữ liệu và phải kết thúc nó khi các thao tác cơ sở dữ liệu của bạn được thực hiện. Hãy để chúng tôi tìm hiểu về API kết nối do TypeORM cung cấp trong phần này.

Tạo kết nối mới

Trước khi tạo kết nối mới, chúng ta cần định cấu hình chi tiết kết nối cơ sở dữ liệu trong ormconfig.jsontập tin cấu hình. Chi tiết kết nối mẫu được hiển thị bên dưới -

ormconfig.json

{ 
   name: "firstconnection", 
   type: "mysql", 
   host: "localhost", 
   port: 3306, 
   username: "root", 
   password: "root", 
   database: "firstDB" 
}

Đây,

  • name - Tên của kết nối cơ sở dữ liệu.
  • type - Loại cơ sở dữ liệu.
  • host - Tên máy chủ của máy chủ cơ sở dữ liệu.
  • port - Cổng máy chủ cơ sở dữ liệu.
  • username - Tên tài khoản có quyền truy cập vào cơ sở dữ liệu.
  • password - Mật khẩu của tài khoản nêu trên.
  • database - Tên cơ sở dữ liệu cần kết nối.

createConnection

CreateConnectionđược cung cấp bởi TypeORM để tạo một kết nối mới. Nó được định nghĩa như dưới đây,

import { createConnection, Connection } from "typeorm"; 

const connection = await createConnection({ 

});

Đây, createConnection sẽ sử dụng chi tiết cấu hình được chỉ định trong tệp ormconfig.json.

Ngoài ra, bạn có thể xác định URL kết nối làm đối số cho phương thức createConnection như được chỉ định sau:

const connection = createConnection({ type: 'mysql', 
     url: 'localhost:8888/firstDB' 
})

Đây,

createConnection trả về một đối tượng, có thể được sử dụng để mở / đóng kết nối với cơ sở dữ liệu.

Nhiều kết nối

TypeORM cung cấp một tùy chọn để tạo nhiều kết nối cơ sở dữ liệu. Đầu tiên, tệp cấu hình ormconfig.json có thể được sử dụng để chỉ định chi tiết của kết nối nhiều cơ sở dữ liệu. Hãy để chúng tôi định cấu hình nhiều cơ sở dữ liệu trong ormconfig.json như được chỉ định sau,

ormconfig.json

{  name: "firstconnection", 
   type: "mysql", 
   host: "localhost", 
   port: 3306, 
   username: "root", 
   password: "root", 
   database: "firstDB" 
}, 
{  name: "secondconnection", 
   type: "mysql", 
   host: "localhost", 
   port: 3306, 
   username: "root", 
   password: "root", 
   database: "secondDB" 
}, 
{  name: "thirdconnection", 
   type: "mysql", 
   host: "localhost", 
   port: 3306, 
   username: "root", 
   password: "root", 
   database: "thirdDB" 
}

Bây giờ, chúng ta có thể sử dụng đối số được cung cấp bởi phương thức createConnection để chỉ định tên của kết nối để tạo đối tượng kết nối như được đề cập bên dưới:

const firstconnection: Connection = await createConnection("firstconnection");

Đây,

createConnection sẽ sử dụng chi tiết cấu hình của firstconnection được chỉ định trong ormconfig.json để tạo đối tượng kết nối.

TypeORM cũng cung cấp một API khác, createConnections để tạo nhiều kết nối cùng một lúc và sau đó, sử dụng nó bất cứ khi nào cần thiết như được chỉ định bên dưới -

import { createConnections, Connection } from "typeorm"; 

const connections: Connection[] = await createConnections([ 

]);

Đây,

connections giữ tất cả các đối tượng kết nối dưới dạng một mảng.

Quản lý kết nối

TypeORM cũng cung cấp một API khác, connectionManager để tạo kết nối. Nó được định nghĩa dưới đây -

import {getConnectionManager, ConnectionManager, Connection} from "typeorm"; 

const connectionManager = getConnectionManager(); 

const connection = connectionManager.create({ 

}); 
await connection.connect();

TypeORM thích sử dụng createConnection kết thúc ConnectionManager để tạo các đối tượng kết nối.

Thực thể là một tập hợp các trường và các hoạt động cơ sở dữ liệu liên quan. Nó được sử dụng để ánh xạ bảng cơ sở dữ liệu và các trường của nó với các thực thể và thuộc tính của nó. Chương này giải thích chi tiết về các thực thể TypeORM.

Giới thiệu

Hãy để chúng tôi tạo một lớp Thực thể đơn giản trong mã của chúng tôi. Di chuyển đến vị trí gốc dự án của bạn và vào bên trong thư mục src và chuyển đến thư mục thực thể. Bây giờ, tạo tệp TypeScript, Student.ts và nhập mã bên dưới -

Student.ts

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

@Entity() 
export class Student {   

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   Name: string; 
   
   @Column() 
   age: number; 
}

Đây,

  • Entity() lớp decorator được sử dụng để biểu thị rằng Student lớp là một thực thể.
  • PrimaryGeneratedColumn() lớp decorator được sử dụng để biểu thị rằng cột id là cột khóa chính của Student thực thể.
  • Column() lớp decorator được sử dụng để đại diện cho các cột khác như NameAge sau đó Student thực thể.

Bây giờ, lớp Thực thể Studentđược tạo ra. TypeORM sẽ tự động tạo một bảng tương ứng vớiStudent thực thể trong cơ sở dữ liệu của chúng tôi và nó sẽ được đặt tên là student. Bây giờ, chuyển sangsrc/index.ts tập tin và thêm mã sau:

index.ts

import "reflect-metadata"; 
import {createConnection} from "typeorm";
import {Student} from "./entity/Student"; //import Student entity

createConnection().then(async connection => { 

   console.log("Inserting a new record into the student database..."); 
   
   //create student object const stud = new Student(); 
   
   //Assign student name and age here stud.Name = "student1"; 
   stud.age = 12; 
   
    //save student object in connection await connection.manager.save(stud); console.log("Saved a new user with id: " + stud.id);
    
    console.log("Loading users from the database...");

    //Display student saved records const students = await connection.manager.find(Student); console.log("Loaded users: ", students);

    console.log("Here you can setup and run express/koa/any other framework.");
}).catch(error => console.log(error));

Đây,

  • Dòng 1 - 3 nhập các lớp liên quan, createConnectionStudent
  • Dòng 5 tạo một kết nối mới với cơ sở dữ liệu bằng cách sử dụng createConnection và nếu kết nối được thiết lập, nó sẽ thực thi mã bên trong then khối.
  • Dòng 10 tạo đối tượng Student mới, stud.
  • Dòng 13-14 đặt các thuộc tính của đối tượng stud mới tạo của chúng ta.
  • Dòng 17 lưu thực thể vào cơ sở dữ liệu bằng cách sử dụng phương thức lưu có sẵn trong connection.manager vật.
  • Dòng 23 tìm nạp thông tin chi tiết về học sinh từ cơ sở dữ liệu bằng cách sử dụng phương pháp tìm có sẵn trong connection.manager vật.

Khởi động máy chủ Mysql và chạy ứng dụng của bạn

Chúng tôi đã tạo thực thể Sinh viên và tạo kết nối trong index.ts. Hãy để chúng tôi khởi động cả máy chủ MySql và ứng dụng của bạn.

npm start

Thao tác này sẽ trả về kết quả sau trên màn hình của bạn:

Đầu ra

Mở mysql máy chủ theo dõi student bảng được thêm vào bên trong cơ sở dữ liệu của bạn.

Cột

Như đã học trước đó, Thực thể thực sự là một tập hợp các thuộc tính. Như đối tượng thực thể tham chiếu đến bảng cơ sở dữ liệu. Các thuộc tính / biến thành viên của nó tham chiếu đến các trường / cột của bảng cơ sở dữ liệu tương ứng. TypeORM hỗ trợ tất cả các loại trường cơ sở dữ liệu thông qua lớp Column. Hãy để chúng tôi tìm hiểu các loại cột khác nhau được hỗ trợ bởi TypeORM trong chương này.

@Column() lớp decorator được sử dụng để đại diện cho cột và kiểu của nó trong thực thể.

Ví dụ: thuộc tính tuổi của thực thể sinh viên và loại thuộc tính tuổi có thể được xác định như sau:

@Column("int") age: integer; // OR @Column({ type: "int" }) age: integer;

Đây,

  • agelà thuộc tính của thực thể. Nói cách khác, tuổi là một trường / cột trong bảng sinh viên trong cơ sở dữ liệu.
  • int đại diện cho loại cột tuổi trong cơ sở dữ liệu.

TypeORM hỗ trợ gần như tất cả các kiểu có sẵn trong cơ sở dữ liệu phổ biến. Trên thực tế, TypeORM cho phép đặt các kiểu khác nhau cho mỗi công cụ cơ sở dữ liệu. Chúng tôi có thể sử dụng bất kỳ loại cơ sở dữ liệu nào được hỗ trợ bởi công cụ cơ sở dữ liệu của chúng tôi mà không gặp bất kỳ vấn đề gì.

Ví dụ, kiểu được hỗ trợ bởi TypeORM cho công cụ cơ sở dữ liệu postgresql như sau:

int, int2, int4, int8, smallint, integer, bigint, decimal, numeric, real, float, float4, float8, double precision, money, character varying,

varchar, character, char, text, citext, hstore, bytea, bit, varbit, bit

varying, timetz, timestamptz, timestamp, timestamp without time zone, timestamp with time zone, date, time, time without time zone, time with time zone, interval, bool, boolean, enum, point, line, lseg, box, path, polygon, circle, cidr, inet, macaddr, tsvector, tsquery, uuid, xml, json, jsonb, int4range, int8range, numrange, tsrange, tstzrange, daterange, geometry, geography, cube

Tương tự, TypeORM hỗ trợ một tập dữ liệu khác nhau cho MySQL.

Tùy chọn cột

TypeORM cung cấp một loạt các tùy chọn khác với loại để mô tả cột. Ví dụ: tùy chọn độ dài đề cập đến độ dài của trường cơ sở dữ liệu và nó có thể được chỉ định như sau:

@Column("varchar", { length: 100 })

Một số tùy chọn cột phổ biến nhất như sau:

  • name - Tên của trường / cột cơ sở dữ liệu.
  • length - Độ dài của trường / cột cơ sở dữ liệu.
  • nullable - Chỉ định trường / cột cơ sở dữ liệu có cho phép null hay không.
  • default - Giá trị mặc định của trường / cột cơ sở dữ liệu.
  • primary - Chỉ định trường / cột cơ sở dữ liệu có phải là khóa chính của bảng hay không.
  • unique - Chỉ định xem trường / cột cơ sở dữ liệu là duy nhất
  • *precision** - Độ chính xác của trường / cột cơ sở dữ liệu
  • scale - Quy mô của trường / cột cơ sở dữ liệu
  • comment - Nhận xét hoặc mô tả về trường / cột cơ sở dữ liệu

@Generated decorator

TypeORM cung cấp trình trang trí bổ sung, @Generated để tự động tạo các giá trị cột. Ví dụ: Mã định danh duy nhất phổ biến (UUID) khá phổ biến được sử dụng trong cơ sở dữ liệu để lưu trữ giá trị duy nhất trong một cột. Mã mẫu để tạo UUID như sau:

@Entity() 
export class Student {
 
   @PrimaryColumn() 
   id: number; 
   
   @Column() 
   @Generated("uuid") 
   uuid: string; 
}

Đây,

uuid được tạo tự động và lưu trữ bên trong cơ sở dữ liệu.

Cột chính

Ít nhất một trường cột chính là bắt buộc đối với bất kỳ thực thể nào trong cơ sở dữ liệu. Nó được phân thành các loại trang trí khác nhau. Chúng ta sẽ thảo luận về nó từng cái một.

@PrimaryColumn()

Trình trang trí @PrimaryColumn () được sử dụng để tạo cột chính cho bất kỳ loại dữ liệu nào. Ví dụ đơn giản được hiển thị bên dưới,

import {Entity, PrimaryColumn} from "typeorm"; 

@Entity() 
export class Student {        
@PrimaryColumn() 
   id: number; 
}

Đây,

id là một số nguyên, không chấp nhận các giá trị trùng lặp, nhưng chúng ta cần gán các giá trị.

Chúng tôi cũng có thể chỉ định cột chính cho một hoặc nhiều trường, nếu tình huống yêu cầu.

Thí dụ

import {Entity, PrimaryColumn} from "typeorm"; 

@Entity() 
export class Student { 
   
   @PrimaryColumn() 
   id: number; 
   
   @PrimaryColumn() 
   email: string; 
   
   @PrimaryColumn() 
   phone: number; 
}

@PrimaryGeneratedColumn ()

@PrimaryGeneratedColumn()được sử dụng để chỉ định cột chính cũng như tự động tạo giá trị cột trong cơ sở dữ liệu. Nó được hiển thị bên dưới -

import {Entity, PrimaryGeneratedColumn} from "typeorm"; 

@Entity() 
export class Student {

   @PrimaryGeneratedColumn() 
   id: number;
}

Đây,

Bạn không phải gán giá trị id; nó sẽ được tạo tự động bởi TypeORM trong bảng cơ sở dữ liệu.

@PrimaryGeneratedColumn (“uuid”)

@PrimaryGeneratedColumn cũng chấp nhận một đối số để chỉ định loại trình tạo. Một trong những cách sử dụng chính là tạo id duy nhất dựa trên UUID.

import {Entity, PrimaryGeneratedColumn} from "typeorm";

@Entity() 
export class Student {  
   @PrimaryGeneratedColumn("uuid") id: string; 
}

kiểu cột đơn giản

Cơ sở dữ liệu quan hệ nâng cao hỗ trợ kiểu dữ liệu mảng. Để hỗ trợ kiểu dữ liệu mảng, TypeORM cung cấp một kiểu cột đặc biệt, * mảng đơn giản "để lưu trữ các giá trị mảng nguyên thủy. Mã mẫu để sử dụng như sau:

@Entity() 
export class Student { 
   
   @PrimaryGeneratedColumn() 
   id: number;

   @Column("simple-array") 
   names: string[]; 
}

loại cột đơn giản json

Rất nhiều công cụ cơ sở dữ liệu hiện đại hỗ trợ cơ sở dữ liệu JSON. Để sử dụng kiểu dữ liệu JSON, TypeORM cung cấp một kiểu đặc biệt, json đơn. Mã mẫu để sử dụng nó như sau:

@Entity() 
export class Student { 

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column("simple-json")
   info: { firstName: string, middleName: string, lastName: string }; 
}

Giá trị này có thể được xác định trong index.ts là,

index.ts

const stud = new Student(); 
stud.info = { firstName: "John", middleName: "peter", lastName: "Michael" };

Cột đặc biệt

TypeORM hỗ trợ các cột đặc biệt sau

  • @CreateDateColumn - Đây là một cột đặc biệt để tự động đặt ngày chèn của thực thể.
  • @UpdateDateColumn - Nó được sử dụng để đặt thời gian cập nhật của thực thể tự động.
  • @VersionColumn - Đặt số phiên bản cho thực thể tự động.

Thực thể kế thừa

Kế thừa thực thể được sử dụng để giảm sự trùng lặp của các thực thể. Hãy xem xét các thực thể dưới đây -

Result.ts

@Entity() 
export class Result {    

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   title: string; 
   
   @Column() 
   description: string; 
   
   @Column() 
   eligible: string 
}

Điểm.

Mã cho lớp.ts như sau:

@Entity() 
export class Grade {

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
   
   @Column() 
   title: string; 
   
   @Column() 
   description: string;
   
   
   
   @Column() 
   grading : string; 
}

Đây,

Hai thực thể trên có id cột, tiêu đề và mô tả. Sử dụng kế thừa thực thể, chúng tôi tạo một Chi tiết lớp cơ sở và kết hợp hai thực thể trên như được chỉ định bên dưới.

Thông tin chi tiết.

export abstract class Details {

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   title: string; 
   
   @Column() 
   description: string; 
} 
@Entity() 
export class Result extends Details{  

   @Column() 
   eligible: string 
} 
@Entity() 
export class Grade extends Details{   

   @Column() 
   name : string; 
   
   @Column() 
   grading : string; 
}

Bây giờ khởi động máy chủ của bạn, bạn có thể thấy phản hồi bên dưới,

Bây giờ hãy mở máy chủ mysql của bạn và di chuyển đến cơ sở dữ liệu của bạn, bạn có thể thấy các bảng sau,

Bảng điểm

Bảng kết quả

Quan hệ được sử dụng để chỉ mối quan hệ giữa bảng trong cơ sở dữ liệu. Nói chung, một mối quan hệ tồn tại giữa hai bảng khi một trong số chúng có khóa ngoại tham chiếu đến khóa chính của bảng kia. Tính năng này làm cho cơ sở dữ liệu quan hệ mạnh mẽ hơn và lưu trữ thông tin hiệu quả hơn.

TypeORM cho phép các thực thể có liên quan với nhau và sau đó là các bảng cơ sở dữ liệu. Nói chung, mối quan hệ có thể được phân thành bốn loại rộng hơn. Chúng như sau,

one-to-one- Một đối tượng của thực thể đã cho chỉ liên quan đến một đối tượng của thực thể đích và ngược lại. Ví dụ, một quốc gia sẽ chỉ có một thủ đô và tương tự, một thành phố sẽ chỉ là thủ đô của một quốc gia.

many-to-one- Nhiều đối tượng của thực thể đã cho liên quan đến một đối tượng của thực thể đích. Ví dụ: thành phố chỉ thuộc một quốc gia nhưng quốc gia có thể có nhiều thành phố.

one-to-many - Tương tự như nhiều-một ngoại trừ mối quan hệ bị đảo ngược.

many-to-many- Nhiều đối tượng của thực thể đã cho liên quan đến nhiều đối tượng của thực thể đích. Ví dụ: một bài viết có thể được gắn thẻ theo nhiều chủ đề như ngôn ngữ lập trình, tài chính, v.v., và đồng thời một thẻ cụ thể cũng có thể có nhiều bài viết.

TypeORM cũng cung cấp các tùy chọn để tăng cường mối quan hệ của các thực thể. Chúng như sau:

  • eager - Đối tượng thực thể nguồn cũng tải các đối tượng thực thể đích.
  • cascade - Đối tượng thực thể đích được chèn hoặc cập nhật trong khi đối tượng thực thể nguồn được chèn hoặc cập nhật.
  • onDelete - Các đối tượng thực thể đích cũng bị xóa trong khi đối tượng thực thể nguồn bị xóa.
  • primary - Dùng để chỉ định cột quan hệ có phải là khóa chính hay không.
  • nullable - Được sử dụng để chỉ định rằng cột quan hệ có thể rỗng hoặc không.

Hãy để chúng tôi đi qua các loại ánh xạ quan hệ khác nhau một cách chi tiết.

Một-một

Như chúng ta đã học trước đó, nó được gọi là trường hợp của một trường bảng chứa trường hợp của trường bảng khác và ngược lại. Hãy để chúng tôi tạo ra mộtDetails bàn -

Thông tin chi tiết.

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

@Entity() 
export class Details {
   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   gender: string; 
   
   @Column() 
   country: string; 
}

Hãy tạo một thực thể khác là Khách hàng như sau:

Khách hàng.ts

import {Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn} from "typeorm"; 

import {Details} from "./Details"; 

@Entity() 
export class Customer { 

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
   
   @OneToOne(type => Details) @JoinColumn() 
   details: Details;
}

Đây,

Chúng tôi đã thêm ánh xạ OneToOne đến Details bàn. @JoinColumn() chứa "id quan hệ" và khóa ngoại để Customerbàn. Chúng ta có thể lưu mối quan hệ trongindex.ts như sau -

const details = new Details(); details.gender = "female"; details.country = "india" await connection.manager.save(details);

const customer = new Customer(); customer.name = 'customer1'; customer.details = Details; await connection.manager.save(Customer);

Một-nhiều và Nhiều-một

Như chúng ta đã học trước đó, nó được gọi là trường thể hiện của trường bảng đầu tiên chứa nhiều trường hợp của trường bảng thứ hai được gọi là One-to-Many ánh xạ và nhiều phiên bản của bảng đầu tiên chỉ chứa một phiên bản của bảng thứ hai được gọi là Many-to-One lập bản đồ.

Hãy xem xét một ví dụ về Studentproject trong khi đó, sinh viên có thể làm việc trên nhiều dự án nhưng mỗi dự án chỉ được xử lý bởi một sinh viên.

Hãy tạo một Project thực thể như sau -

Dự án

import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm"; import {Student} from "./Student"; 
@Entity() 
export class Project {  

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   projects: string; 
   
   @ManyToOne(type => Student, student => student.projects) student: Student; 
}

Bây giờ, chúng tôi tạo Student thực thể như bên dưới -

import {Entity, PrimaryGeneratedColumn, Column, OneToMany} from "typeorm"; import {Project} from "./Project"; 

@Entity() 
export class User {  
   
   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
   
   @OneToMany(type => Project, project => project.student) projects: Project[];  
}

Đây,

@OneToMany bản đồ tài sản Project@ManyToOne tài sản được ánh xạ tới Student. Tuy nhiên,@OneToMany không thể tồn tại mà không có @ManyToOne@ManyToOne thuộc tính chứa "id quan hệ" và khóa ngoại.

Chúng tôi có thể lưu kết nối trong index.ts như sau -

const proj1 = new Project(); proj1.projects = "database management"; await connection.manager.save(proj1); 

const proj2 = new Project(); proj2.projects = "web application"; await connection.manager.save(proj2); 

const stud = new Student(); stud.name = "Student1"; stud.projects = [proj1, proj2]; await connection.manager.save(stud);

Nhiều nhiều

Như chúng ta đã học trước đó, nó được tham chiếu bởi nhiều bản ghi trong một bảng có liên quan đến nhiều bản ghi trong bảng khác. Hãy xem xét một ví dụ, sinh viên Đại học có thể đăng ký nhiều lớp cùng một lúc, nghĩa là sinh viên có thể có bốn hoặc năm lớp mỗi học kỳ và một lớp có thể có nhiều sinh viên.

Chúng ta có thể kết luận một cách đơn giản, một học sinh có nhiều lớp, và một lớp có nhiều học sinh. Hãy tạo một thực thể choClasses như sau -

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

@Entity() 
export class Classes { 

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
}

Bây giờ, chúng tôi tạo Student thực thể như bên dưới -

import {Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable} from "typeorm"; 
import {Classes} from "./Classes";

@Entity() 
export class Student { 

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string;

   @Column() 
   subjects: string; 
   
   @ManyToMany(type => Classes) @JoinTable() 
   classes: Classes[];
}

Kho lưu trữ dành riêng cho một thực thể. Nói cách khác, mỗi thực thể sẽ có kho lưu trữ tích hợp riêng và nó có thể được truy cập bằng phương thức getRepository () của đối tượng kết nối như được chỉ định bên dưới:

const studRepository = manager.getRepository(Student);

Sau khi đối tượng kho lưu trữ sinh viên được tạo, nó có thể được sử dụng để thực hiện tất cả các hoạt động cơ sở dữ liệu của đối tượng sinh viên.

Các loại kho lưu trữ

Repositoryđược phân thành bốn loại. Chúng như sau:

Kho

Kho lưu trữ mặc định của một thực thể và nó có thể được truy cập bằng cách sử dụng getRepository() như được chỉ định bên dưới -

const studRepository = manager.getRepository(Student);

Hiện nay, studRepository có thể được sử dụng để truy vấn bảng sinh viên

TreeRepository

Được sử dụng cho các thực thể cấu trúc giống cây và nó có thể được truy cập bằng cách sử dụng getTreeRepository() như được chỉ định bên dưới -

const studcaRepository = manager.getTreeRepository(Student);

MongoRepository

Được sử dụng bên trong các thực thể hoạt động mongoDB và nó có thể được truy cập bằng cách sử dụng getMongoRepository() như được chỉ định bên dưới -

const detailsRepository = manager.getMongoRepository(Details);

CustomRepository

Được sử dụng để tùy chỉnh kho lưu trữ và nó có thể được truy cập bằng cách sử dụng getCustomRepository() như được chỉ định bên dưới,

const myUserRepository = manager.getCustomRepository(UserRepository);

API kho lưu trữ

Chúng ta hãy tìm hiểu phương pháp quan trọng nhất của EntityManager trong chương này.

giám đốc

Chúng tôi có thể truy cập EntityManager sử dụng phương pháp người quản lý như được chỉ định bên dưới -

const manager = repository.manager;

queryRunner

queryRunnerphương thức trả về đối tượng người chạy truy vấn tùy chỉnh và nó được sử dụng cho các hoạt động cơ sở dữ liệu bởi kho lưu trữ. Mã mẫu như sau:

const queryRunner = repository.queryRunner;

metadata

metadatatrả về siêu dữ liệu của kho lưu trữ. Mã mẫu như sau:

const metadata = repository.metadata;

truy vấn

queryphương thức thực thi các truy vấn SQL. Truy vấn chọn đơn giản như được hiển thị bên dưới -

const qur = await repository.query(`select * from students`);

chèn

insertđược sử dụng để chèn một thực thể mới hoặc một mảng các thực thể vào cơ sở dữ liệu. Mã mẫu như sau:

await repository.insert({ 
   Name: "Student3", 
   Age: 14 
});

Truy vấn trên tương đương với,

insert into student(Name,age) values("Student3",14)

cập nhật

update được sử dụng để cập nhật các bản ghi hiện có trong cơ sở dữ liệu.

await repository.update(1, { Name: "Adam" });

Truy vấn này hoạt động tương tự như truy vấn được đề cập bên dưới -

update student SET Name = "Adam" where id = 1

xóa bỏ

delete phương thức sẽ xóa bản ghi được chỉ định khỏi bảng,

await repository.delete(Student, 1);

Thao tác này sẽ xóa sinh viên có id 1 từ studentbàn. Nó tương đương với,

delete from student where id=1;

Nếu bạn muốn xóa theo tên thì hãy sử dụng truy vấn dưới đây,

await repository.delete({ Name: "Student1" });

Truy vấn này sẽ xóa tất cả học sinh có tên, Student1

** softDelete and restore **

Nó được sử dụng để xóa mềm dữ liệu và bạn có thể khôi phục hồ sơ dựa trên id của học sinh. Mã mẫu như sau:

await repository.softDelete(1);

Bạn có thể khôi phục hồ sơ học sinh bằng lệnh dưới đây:

await repository.restore(1);

Một tùy chọn thay thế để xóa và khôi phục là sử dụng softRemoverecovercác phương pháp. Mã mẫu như sau:

//find the entities const enty = await repository.find(); 

//soft removed entity const entySoftRemove = await repository.softRemove(enty);

Và, bạn có thể khôi phục chúng bằng phương pháp khôi phục như được chỉ định bên dưới,

await repository.recover(entySoftRemove);

tiết kiệm

saveđược sử dụng để lưu thực thể đã cho vào cơ sở dữ liệu. Thực thể Sinh viên Đơn giản có thể được lưu như hình dưới đây -

import {Student} from "./entity/Student"; 

createConnection().then(async connection => {                     
   console.log("Inserting a new record into the student database..."); 
   const stud = new Student();
   stud.Name = "student1"; 
   stud.age = 12; 
   await repository.save(stud);

Thao tác này sẽ thêm hồ sơ học sinh mới vào cơ sở dữ liệu.

tẩy

removeđược sử dụng để xóa thực thể đã cho khỏi cơ sở dữ liệu. Thực thể Sinh viên đơn giản có thể bị xóa như hình dưới đây -

await repository.remove(stud);

đếm

countphương thức sẽ trả về số lượng bản ghi có sẵn trong bảng và bạn có thể sử dụng nó cho mục đích phân trang. Mã mẫu như sau:

const cnt = await repository.count(Student, { age: 12 });

tìm thấy

findphương pháp được sử dụng cho mục đích tìm kiếm. Nó tìm nạp tất cả bản ghi từ cơ sở dữ liệu như hình dưới đây:

const result = await repository.find({ id: 1 });

tìm một

Tương tự với findnhưng trả về bản ghi phù hợp đầu tiên. Mã mẫu như sau:

const result = await repository.findOne({ id: 1 });

thông thoáng

clearphương thức xóa tất cả dữ liệu khỏi bảng. Mã mẫu như sau:

await repository.clear();

EntityManager tương tự như Repositoryvà được sử dụng để quản lý các hoạt động của cơ sở dữ liệu như chèn, cập nhật, xóa và tải dữ liệu. Trong khiRepository xử lý một thực thể, EntityManager là chung cho tất cả các thực thể và có thể thực hiện các hoạt động trên tất cả các thực thể.

API trình quản lý thực thể

Chúng tôi có thể truy cập EntityManager sử dụng getManager() như được chỉ định bên dưới -

import { getManager } from "typeorm"; const entityManager = getManager();

Chúng ta hãy tìm hiểu phương pháp quan trọng nhất của EntityManager trong chương này.

kết nối

connectionphương thức trả về kết nối cơ sở dữ liệu ORM với cơ sở dữ liệu cụ thể. Mã mẫu như sau:

const connection = manager.connection;

QueryRunner

queryRunnerphương thức trả về đối tượng người chạy truy vấn tùy chỉnh và nó được sử dụng cho các hoạt động cơ sở dữ liệu bởi trình quản lý thực thể. Mã mẫu như sau:

const queryRunner = manager.queryRunner;

Giao dịch

Nếu nhiều yêu cầu cơ sở dữ liệu được gọi, giao dịch sẽ thực hiện trong một giao dịch cơ sở dữ liệu duy nhất. Mã mẫu để nhận giao dịch như sau:

await manager.transaction(async manager => { 
});

truy vấn

queryphương thức thực hiện các truy vấn sql. Truy vấn chèn đơn giản như hình dưới đây -

const qur = await manager.query(`insert into student(name,age) values('stud2',13)`);

chèn

insertđược sử dụng để chèn một thực thể mới hoặc một mảng các thực thể vào cơ sở dữ liệu. Mã mẫu như sau:

await manager.insert(Student, { 
   Name: "Student3", 
   Age: 14 
});

cập nhật

update được sử dụng để cập nhật các bản ghi hiện có trong cơ sở dữ liệu.

await manager.update(User, 1, { Name: "Adam" });

Truy vấn này hoạt động tương tự như truy vấn SQL bên dưới,

UPDATE student SET Name = "Adam" WHERE id = 1

xóa bỏ

phương pháp xóa sẽ xóa bản ghi được chỉ định khỏi bảng,

await manager.delete(Student, 1);

Thao tác này sẽ xóa với id 1 của hồ sơ học sinh.

tiết kiệm

saveđược sử dụng để lưu thực thể đã cho vào cơ sở dữ liệu. Thực thể Sinh viên Đơn giản có thể được lưu như hình dưới đây -

import {Student} from "./entity/Student";

createConnection().then(async connection => {   
   console.log("Inserting a new record into the student database..."); 
   const stud = new Student(); stud.Name = "student1"; 
   stud.age = 12; 
   await connection.manager.save(stud); 
}

Thao tác này sẽ thêm hồ sơ học sinh mới vào cơ sở dữ liệu. phương thức lưu sẽ chèn học sinh, nếu học sinh đã cho không tồn tại trong cơ sở dữ liệu. Nếu không, lưu sẽ cập nhật hồ sơ học sinh hiện có trong cơ sở dữ liệu.

tẩy

removeđược sử dụng để xóa thực thể đã cho khỏi cơ sở dữ liệu. Thực thể Sinh viên đơn giản có thể bị xóa như hình dưới đây -

await manager.remove(stud);

đếm

countphương thức sẽ trả về số lượng bản ghi có sẵn trong bảng và bạn có thể sử dụng nó cho mục đích phân trang. Mã mẫu như sau:

const cnt = await manager.count(Student, { age: 12 });

tìm thấy

findphương pháp được sử dụng cho mục đích tìm kiếm. Nó tìm nạp tất cả bản ghi từ cơ sở dữ liệu như hình dưới đây:

console.log("Loading users from the database..."); 
const students = await connection.manager.find(Student); console.log("Loaded users: ", students);

tìm một

Tương tự với findnhưng trả về bản ghi phù hợp đầu tiên. Mã mẫu như sau:

const stud = await manager.findOne(Student, 1);

thông thoáng

phương thức clear xóa tất cả dữ liệu khỏi bảng. Mã mẫu như sau:

await manager.clear(Student);

Trình tạo truy vấn được sử dụng để xây dựng các truy vấn SQL phức tạp một cách dễ dàng. Nó được khởi tạo từ phương thức Connection và các đối tượng QueryRunner.

Chúng ta có thể tạo QueryBuilder theo ba cách.

Kết nối

Hãy xem xét một ví dụ đơn giản về cách sử dụng QueryBuilder bằng phương thức kết nối.

import {getConnection} from "typeorm"; 

const user = await getConnection() .createQueryBuilder() 
.select("user") 
.from(User, "user") 
.where("user.id = :id", { id: 1 }) .getOne();

Người quản lý thực thể

Hãy tạo trình tạo truy vấn bằng trình quản lý thực thể như sau:

import {getManager} from "typeorm"; 

const user = await getManager() .createQueryBuilder(User, "user") .where("user.id = :id", { id: 1 })    .getOne();

Kho

Chúng ta có thể sử dụng kho lưu trữ để tạo trình tạo truy vấn. Nó được mô tả dưới đây,

import {getRepository} from "typeorm"; 

const user = await getRepository(User) .createQueryBuilder("user") .where("user.id = :id", { id: 1 }) .getOne();

Bí danh

Bí danh giống như bí danh SQL. Chúng tôi tạo bí danh cho bảng Sinh viên bằng QueryBuilder như được mô tả bên dưới:

import {getConnection} from "typeorm"; 

const user = await getConnection() .createQueryBuilder() 
.select("stud") 
.from(Student, "stud")

Truy vấn này tương đương với,

select * from students as stud

Thông số

Parametersđược sử dụng làm trình giữ chỗ cho các giá trị động trong truy vấn. Trong nhiều trường hợp, truy vấn để tìm đối tượng thực thể khác nhau sẽ giống nhau ngoại trừ các giá trị. Ví dụ: truy vấn để tìm học sinh khác nhau là giống nhau ngoại trừStudent IDdữ liệu. Trong trường hợp này, chúng ta có thể sử dụng tham số choStudent ID và sau đó thay đổi tham số để nhận các đối tượng học sinh khác nhau.

Một cách sử dụng quan trọng khác của tham số là ngăn chặn SQL injection. Đây là một trong những vi phạm bảo mật quan trọng trong ứng dụng web hiện đại. Bằng cách sử dụng tham số trong truy vấn, chúng ta có thể sống sót sau các cuộc tấn công SQL injection.

Một cách sử dụng quan trọng khác của tham số là ngăn chặn SQL injection. Đây là một trong những vi phạm bảo mật quan trọng trong ứng dụng web hiện đại. Bằng cách sử dụng tham số trong truy vấn, chúng ta có thể sống sót sau các cuộc tấn công SQL injection.

Ví dụ

"student.id = :id", { id: 1 }

Đây,

: id - tên tham số.

{id: 1} - giá trị của tham số

Thêm biểu thức

Phần này giải thích về cách sử dụng các biểu thức.

Ở đâu

where được sử dụng để lọc các bản ghi nếu điều kiện được khớp.

createQueryBuilder("student") .where("student.id = :id", { id: 1 })

Truy vấn này tương đương với,

select * from students student where student.id=1;

Chúng ta cũng có thể sử dụng các điều kiện AND, OR, NOT, IN bên trong.

đang có

Biểu thức có đơn giản được định nghĩa dưới đây:

createQueryBuilder("student") .having("student.id = :id", { id: 1 })

Truy vấn này tương đương với,

select * from students student having student.id=1;

đặt bởi

orderby được sử dụng để sắp xếp các bản ghi dựa trên trường.

createQueryBuilder("student") .orderBy("student.name")

Truy vấn này tương đương với,

select * from students student order by student.name;

groupBy

Nó được sử dụng để nhóm các bản ghi dựa trên cột được chỉ định.

createQueryBuilder("student") .groupBy("student.id")

Truy vấn này tương đương với,

select * from students student group by student.id;

giới hạn

Nó được sử dụng để giới hạn việc lựa chọn các hàng. Dưới đây, ví dụ cho thấy cách sử dụng giới hạn trong trình tạo truy vấn,

createQueryBuilder("student") .limit(5)

Truy vấn này tương đương với,

select * from students student limit 5;

bù lại

Offset được sử dụng để chỉ định, có bao nhiêu hàng để bỏ qua kết quả. Nó được định nghĩa dưới đây -

createQueryBuilder("student") .offset(5)

Truy vấn này tương đương với,

select * from students student offset 5;

tham gia

mệnh đề nối được sử dụng để kết hợp các hàng từ hai hoặc nhiều bảng, dựa trên một cột có liên quan. Hãy xem xét hai thực thể -

Student.ts

import {Entity, PrimaryGeneratedColumn, Column, OneToMany} from "typeorm"; 
import {Project} from "./Project"; 

@Entity() 
export class User {
   
   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
   
   @OneToMany(type => Project, project => project.student) projects: project[]; 
}

Project.ts

import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm"; 
import {Student} from "./Student"; 

@Entity() 
export class Project { 

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   title: string; 
   
   @ManyToOne(type => Student, student => student.projects) student: Student; 
}

Hãy để chúng tôi thực hiện phép nối bên trái đơn giản bằng cách sử dụng truy vấn dưới đây:

const student = await createQueryBuilder("student") .leftJoinAndSelect("student.projects", "project") 
.where("student.name = :name", { name: "Student1" }) 
.getOne();

Truy vấn này tương đương với,

SELECT student.*, project.* FROM students student 
   LEFT JOIN projects project ON project.student = student.id 
   WHERE student.name = 'Student1'

Tương tự, chúng ta cũng có thể thử tham gia nội bộ.

Tham gia mà không cần lựa chọn

Chúng tôi có thể nối dữ liệu mà không cần sử dụng select. Chúng ta hãy thử ví dụ này bằng cách sử dụng phép nối bên trong như sau:

const student = await createQueryBuilder("student") .innerJoin("student.projects", "project") 
   .where("student.name = :name", { name: "student1" }) 
   .getOne();

Truy vấn trên tương đương với -

SELECT student.* FROM students student 
   INNER JOIN projects project ON project.student = student.id 
   WHERE student.name = 'Student1';

Phân trang

Nếu bạn có nhiều dữ liệu hơn trong ứng dụng của mình, bạn cần các chức năng phân trang, thanh trượt trang hoặc cuộn.

Ví dụ: nếu bạn muốn hiển thị năm dự án sinh viên đầu tiên trong ứng dụng của mình,

const students = await getRepository(Student) .createQueryBuilder("student") .leftJoinAndSelect("student.projects", "project") 
   .take(5) 
   .getMany();

truy vấn phụ

Nó được gọi là truy vấn trong một truy vấn khác hoặc truy vấn lồng nhau. Chúng tôi sử dụng truy vấn con trong các biểu thức FROM, WHERE và JOIN.

Ví dụ đơn giản được hiển thị bên dưới -

const projects = await connection .createQueryBuilder() .select("project.id", "id")
.addSelect(subQuery => { 
   return subQuery 
      .select("student.name", "name") .from(Student, "student") 
      .limit(1); 
}, "name")
.from(Project, "project") .getMany();

Giấu trang

Nếu bất kỳ trường cột nào của bạn được đánh dấu là {select: false} thì cột đó được coi là cột ẩn. Hãy xem xét thực thể dưới đây -

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

@Entity() 
export class Student {

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
   
   @Column({select: false}) 
   address: string; 
}

Đây,

address trường được đánh dấu là hidden. Chúng ta có thể sử dụngaddSelectphương pháp để lấy thông tin từ cột. Nó được định nghĩa dưới đây,

const student = await connection.getRepository(Student) .createQueryBuilder() .select("student.id", "student")    .addSelect("student.address") .getMany();

getSql ()

Phương pháp này được sử dụng để lấy truy vấn SQL được tạo bởi trình tạo truy vấn. Nó được định nghĩa dưới đây -

const sql = createQueryBuilder("student") .where("student.name = :name", { name: "Student1" })  .orWhere("student.age = :age", { age: 14 }) 
.getSql();

Thao tác dữ liệu được sử dụng để quản lý và xem dữ liệu. Phần này giải thích về cách truy cập các truy vấn cơ sở dữ liệu như chèn, cập nhật, chọn và xóa các truy vấn bằng QueryBuilder. Chúng ta hãy đi qua từng chi tiết một.

Xây dựng truy vấn chèn

Hãy để chúng tôi tạo một thực thể Khách hàng như sau:

Khách hàng.ts

import {Entity, PrimaryGeneratedColumn, Column} from "typeorm"; 
@Entity() 
export class Customer {       

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   name: string; 
   
   @Column() 
   age: number; 
}

Hãy thêm các thay đổi sau trong index.ts như sau:

index.ts

import "reflect-metadata"; 
import {createConnection} from "typeorm"; 
import {Customer} from "./entity/Customer"; 
import {getConnection} from "typeorm"; 

createConnection().then(async connection => { 
   await getConnection().createQueryBuilder()   .insert() 
      .into(Customer)  
      .values([ { name: "Adam",age:11}, 
         { name: "David",age:12} ]) .execute(); 
}).catch(error => console.log(error));

Bây giờ, hãy khởi động ứng dụng của bạn bằng lệnh dưới đây -

npm start

Đầu ra

Bạn có thể thấy kết quả sau trên màn hình của mình:

Bây giờ mở máy chủ mysql của bạn, bảng được chèn với hai trường như hình dưới đây -

Xây dựng truy vấn cập nhật

Phần cuối cùng, chúng tôi đã chèn hai hàng dữ liệu. Hãy kiểm tra cách hoạt động của truy vấn cập nhật. Thêm các thay đổi sau trong index.ts như sau:

import "reflect-metadata"; 
import {createConnection} from "typeorm"; 
import {Customer} from "./entity/Customer"; 
import {getConnection} from "typeorm";

createConnection().then(async connection => { 

await getConnection()         
   .createQueryBuilder() .update(Customer) 
   .set({ name: "Michael" }) .where("id = :id", { id: 1 }) .execute(); 
   console.log("data updated"); 
   
}).catch(error => console.log(error));

Bây giờ, hãy khởi động ứng dụng của bạn bằng lệnh dưới đây -

npm start

Bạn có thể thấy kết quả sau trên màn hình của mình:

Bảng Mysql được sửa đổi như hình dưới đây -

Tạo truy vấn chọn

selecttruy vấn được sử dụng để hiển thị các bản ghi từ bảng. Hãy thêm đoạn mã sau vàoindex.ts như sau -

index.ts

import "reflect-metadata"; 
import {createConnection} from "typeorm"; 
import {Customer} from "./entity/Customer"; 

createConnection().then(async connection => { 

   console.log("Display records from Customer table..."); 
   const cus = new Customer();

   console.log("Loading customers from the database..."); 
   const customers = await connection.manager.find(Customer); console.log("Loaded users: ", customers); 
}).catch(error => console.log(error));

Bạn có thể thấy kết quả sau trên màn hình của mình:

biểu hiện ở đâu

Hãy để chúng tôi thêm biểu thức where trong truy vấn để lọc khách hàng. Mã mẫu như sau:

import "reflect-metadata"; 
import {createConnection} from "typeorm"; 
import {Customer} from "./entity/Customer"; 
import {getConnection} from "typeorm";

createConnection().then(async connection => { 
   const customer = await getConnection() .createQueryBuilder() .select("cus") 
   .from(Customer, "cus") .where("cus.id = :id", { id: 1 }) .getOne(); 
   
   console.log(customer); 
})
.catch(error => console.log(error));

Chương trình trên sẽ trả về các bản ghi id đầu tiên. Bạn có thể thấy kết quả sau trên màn hình của mình,

Tương tự, bạn cũng có thể thử các biểu thức khác.

Tạo truy vấn xóa

Phần cuối, chúng tôi đã chèn, cập nhật và chọn lọc dữ liệu. Hãy kiểm tra cách hoạt động của truy vấn xóa. Thêm các thay đổi sau trong index.ts như sau:

import "reflect-metadata"; 
import {createConnection} from "typeorm"; 
import {Customer} from "./entity/Customer"; 
import {getConnection} from "typeorm"; 

createConnection().then(async connection => { 
   await getConnection() .createQueryBuilder() 
   .delete() 
   .from(Customer) 
   .where("id = :id", { id: 1 }) .execute();
console.log("data deleted"); }).catch(error => console.log(error));

Bạn có thể thấy kết quả sau trên màn hình của mình:

Và bảng mysql của bạn được sửa đổi như sau:

Nói chung, giao dịch là một đơn vị logic chịu trách nhiệm thực hiện truy xuất và cập nhật dữ liệu. Phần này giải thích chi tiết về Giao dịch.

Tạo giao dịch

Chúng tôi có thể tạo giao dịch bằng kết nối hoặc EntityManage. Ví dụ dưới đây được sử dụng để chỉ định tạo kết nối và lưu dữ liệu bên trong nó.

import {getConnection} from "typeorm"; 

await getConnection().transaction(async transactionalEntityManager => { 

   await connection.manager.save(students); 

});

EntityManager được hiển thị bên dưới -

import {getManager} from "typeorm";

await getManager().transaction(async transactionalEntityManager => { 
   await transactionalEntityManager.save(students); 
});

Trang trí

Chúng tôi có ba loại trang trí liên quan đến giao dịch trong TypeORM.

  • @Transaction - Kết thúc tất cả việc thực thi trong một lần chuyển cơ sở dữ liệu.
  • @TransactionManager- Được sử dụng để thực hiện các truy vấn bên trong giao dịch. Nó được định nghĩa dưới đây,
@Transaction({ isolation: "SERIALIZABLE" }) 

save(@TransactionManager() manager: EntityManager, student: Student) {     
   return manager.save(student); 
}

Đây,

Chúng tôi đã sử dụng SERIALIZABLE mức cô lập cho giao dịch.

  • @TransactionRepository- Được sử dụng để đưa giao dịch vào kho lưu trữ. Nó được định nghĩa dưới đây,
@Transaction() save(student: Student, @TransactionRepository(Student) studentRepository: 
Repository<Student>) { 
   return studentRepository.save(student); 
}

Giao dịch trong QueryRunner

QueryRunner được sử dụng để thực thi tất cả các truy vấn cơ sở dữ liệu. Nó có một kết nối cơ sở dữ liệu duy nhất. Giao dịch cơ sở dữ liệu có thể được tổ chức bằng QueryRunner . Hãy thực hiện một giao dịch duy nhất bằng QueryRunner .

import {getConnection} from "typeorm"; 

// get a connection and create a new query runner 
const connection = getConnection(); const queryRunner = connection.createQueryRunner(); 

// establish real database connection using our new query runner 
await queryRunner.connect(); 

// now we can execute any queries on a query runner, for example: await queryRunner.query("SELECT * FROM students");

Bây giờ, hãy bắt đầu giao dịch bằng câu lệnh dưới đây -

await queryRunner.startTransaction();

Sau đó, cam kết và khôi phục giao dịch bằng cách sử dụng câu lệnh dưới đây,

try { 
   await queryRunner.commitTransaction(); 
}

Nếu có bất kỳ lỗi nào, nó sẽ được xử lý bằng hàm catch (),

catch (err) { 

   // since we have errors lets rollback changes we made await queryRunner.rollbackTransaction(); 
}

Bây giờ, hãy phát hành queryRunner như bên dưới:

finally { 
   
   // you need to release query runner which is manually created: await queryRunner.release(); 
}

Nói chung, Indexinglà một quá trình để tối ưu hóa hiệu suất của cơ sở dữ liệu bằng cách tối ưu hóa việc lưu trữ dữ liệu. Nó được sử dụng để nhanh chóng xác định vị trí và truy cập dữ liệu trong cơ sở dữ liệu. Phần này giải thích về cách sử dụng chỉ mục trong TypeORM. Các chỉ số được phân thành nhiều loại khác nhau. Chúng ta hãy đi qua từng chi tiết một.

Chỉ số cột

Chúng tôi có thể tạo chỉ mục cho cột cụ thể bằng cách sử dụng @Index. Hãy xem xét một ví dụ về thực thể Khách hàng như được hiển thị bên dưới và chỉ mục được xác định chofirstName cột,

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

@Entity() 
export class Student { 

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Index() 
   @Column() 
   firstName: string; 
   
   @Column() 
   lastName: string; 
   
   @Column() 
   age: number; 
   
   @Column() 
   address: string; 
}

@Index cũng cho phép chỉ định tên cho một chỉ mục -

@Index("Name-idx") 
@Column() 
firstName: string;

Chỉ số duy nhất

Để chỉ định các ràng buộc Duy nhất trong cột của bạn, hãy sử dụng thuộc tính dưới đây:

{ unique: true }

Ví dụ: dưới đây là mã để chỉ định chỉ mục duy nhất cho cột Tên -

@Index({ unique: true }) 
@Column() 
firstName: string;

Để áp dụng các chỉ số cho nhiều hơn một cột, chúng ta có thể chỉ định trực tiếp nó sau @Entity (). Mã mẫu như sau:

@Entity() 
@Index(["firstName", "lastName"]) @Index(["firstName", "lastName"], { unique: true })

Chỉ số không gian

Chỉ mục không gian cho phép truy cập các đối tượng không gian. MySQL và PostgreSQL hỗ trợ các chỉ số không gian. Để bật các chỉ số không gian trong cột của bạn, hãy thêm thuộc tính sau:

{ spatial: true }

Kiểu không gian có nhiều kiểu phụ như, hình học, điểm, chuỗi dòng, đa giác, v.v., Ví dụ: nếu bạn muốn thêm kiểu không gian điểm trong cột của mình, hãy sử dụng mã bên dưới:

@Column("point") 
@Index({ spatial: true }) 
point: string;

Tắt đồng bộ hóa

Để tắt đồng bộ hóa, hãy sử dụng tùy chọn dưới đây trên @Index người trang trí -

{ synchronize: false }

Trình nghe thực thể được sử dụng trong các thực thể hỗ trợ phương pháp tùy chỉnh và lắng nghe các sự kiện cụ thể. Chúng tôi có thể xác định bất kỳ phương pháp tùy chỉnh thực thể nào bằng cách sử dụng trình trang trí. Hãy hiểu ngắn gọn về trang trí.

  • @AfterLoad - Khi thực thể được tải bằng QueryBuilder hoặc repository / manager, phương thức này sẽ được gọi.
  • @BeforeInsert - Phương thức này sẽ gọi trước khi thực thể được chèn bằng cách sử dụng kho / trình quản lý.
  • @AfterInsert - Phương thức này sẽ gọi sau khi thực thể được chèn bằng cách sử dụng kho / trình quản lý.
  • @BeforeUpdate - Phương thức này sẽ gọi nó trước khi một thực thể hiện có được cập nhật bằng cách sử dụng kho / trình quản lý.
  • @AfterUpdate - Nó sẽ gọi sau khi một thực thể được cập nhật.
  • @BeforeRemove - Nó sẽ gọi trước khi một thực thể bị xóa.
  • @AfterRemove - Nó sẽ gọi sau khi một thực thể bị xóa.

Người đăng kí

Người đăng ký được sử dụng để lắng nghe các sự kiện thực thể cụ thể. Nó được thực hiện từEntitySubscriberInterface. Hãy hiểu một ví dụ đơn giản về cách sử dụng trình nghe thực thể trong thuê bao. Hãy xem xét thực thể Sinh viên được hiển thị bên dưới:

Student.ts

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

@Entity() 
export class Student {     

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   Name: string; 
   
   @Column() 
   age: number; 
}

Tạo người đăng ký sinh viên

Người đăng ký được tạo bằng lệnh dưới đây:

typeorm subscriber:create -n StudentSubscriber

Lệnh trên tạo một thư mục người đăng ký bên trong dự án của bạn src. Sau đó, tệp StudentSubscriber.ts được tạo bên trong người đăng ký của bạn. Bạn có thể thấy phản hồi sau đây,

Subscriber /Users/workspace/TypeORM/FirstProject/src/subscriber/StudentSubscriber.ts has been created successfully.

Bây giờ chuyển sang tệp, bạn có thể thấy mã dưới đây:

StudentSubscriber.ts

import {EventSubscriber, EntitySubscriberInterface} from "typeorm"; 

@EventSubscriber() 
export class StudentSubscriber implements EntitySubscriberInterface<any> { 
}

Bây giờ, hãy thêm các thay đổi sau vào tệp,

import {EventSubscriber, EntitySubscriberInterface,InsertEvent} from "typeorm"; 
import {Student} from "../entity/Student"; 

@EventSubscriber() 
export class StudentSubscriber implements EntitySubscriberInterface<any> { 
   listenTo() 
   { 
      return Student; 
   } 
   
   afterInsert(event: InsertEvent<Student>) { 
      console.log(event); 
   } 
}

Đây,

Chúng tôi vừa dùng afterInsert()phương thức để gọi sự kiện thực thể. Tương tự, bạn cũng có thể sử dụng các sự kiện khác. Chúng tôi đã định cấu hình tệp ormconfig.json. Bây giờ, hãy thêm các thay đổi bên dưới vàoindex.ts tập tin như sau -

index.ts

import "reflect-metadata"; import {createConnection} from "typeorm"; import {Student} from "./entity/Student"; 

createConnection().then(async connection => {

   console.log('connection established'); 
}).catch(error => console.log(error));

Sau khi thực hiện ứng dụng, bạn có thể thấy kết quả bên dưới trên màn hình của mình,

Ghi nhật ký

Ghi nhật ký cơ sở dữ liệu là một phần quan trọng trong thiết kế giải pháp cơ sở dữ liệu có tính khả dụng cao của bạn vì nhật ký cơ sở dữ liệu giúp bạn có thể khôi phục khi bị lỗi và chúng giúp đồng bộ hóa cơ sở dữ liệu chính và phụ.

Tất cả các cơ sở dữ liệu đều có nhật ký được liên kết với chúng. Các bản ghi này lưu giữ hồ sơ về các thay đổi cơ sở dữ liệu. Nếu cơ sở dữ liệu cần được khôi phục đến một điểm ngoài lần sao lưu ngoại tuyến, đầy đủ cuối cùng, thì cần có nhật ký để chuyển dữ liệu về phía trước đến điểm bị lỗi.

Tùy chọn ghi nhật ký

Ghi nhật ký được bật bằng cách thêm {logging: true} vào kết nối cơ sở dữ liệu. Các tùy chọn ghi nhật ký được phân thành nhiều loại khác nhau. Chúng như sau:

query- trả lại tất cả các truy vấn nhật ký. Nó được định nghĩa như sau:

{ 
   host: "localhost",
   ... 
   logging: ["query"] 
}

error- trả lại nhật ký cho tất cả các truy vấn không thành công và lỗi. Nó được định nghĩa dưới đây -

{ 
   host: "localhost",
   ... 
   logging: ["error"] 
}

schema - trả về nhật ký cho lược đồ.

warn - trả về cảnh báo ORM nội bộ.

info - trả lại nhật ký các tin nhắn thông tin ORM nội bộ.

log - trả về thông báo nhật ký ORM nội bộ.

Trình ghi nhật ký tùy chỉnh

Ghi nhật ký tùy chỉnh là tùy chọn ghi nhật ký đơn giản và có thể tùy chỉnh cao. Chúng tôi có thể tạo lớp trình ghi nhật ký của riêng mình bằng đoạn mã dưới đây:

import {Logger} from "typeorm"; 

export class MyCustomLogger implements Logger { 
   
   // implement all methods from logger class 
}

Tùy chọn kết nối được chỉ định trong ormconfig.json như sau:

name: "mysql", 
type: "mysql", 
host: "localhost", 
port: 3306, 
username: "root", 
password: "root", 
database: "test", 
logger: new MyCustomLogger()

Ngôn ngữ mặc định được hỗ trợ bởi TypeORMTypeScript. Vì TypeScript hỗ trợ nhập tĩnh, các lớp và trình trang trí, nên dễ dàng xác định thực thể và các thuộc tính của nó. Đồng thời,JavaScript cũng cần thiết trong một số dự án mà ngôn ngữ ưu tiên là JavaScript. TypeORMcung cấp hỗ trợ đầy đủ cho ngôn ngữ JavaScript. TypeORM hỗ trợ cả phiên bản JavaScript es5 và es6.

Trong chương này, chúng ta hãy tìm hiểu cách viết ứng dụng TypeORM trong JavaScript ES5 (ECMAScript 5).

Mở dấu nhắc lệnh và chuyển đến không gian làm việc của bạn.

cd /path/to/workspace/

Chạy lệnh dưới đây để tạo một dự án TypeORM.

typeorm init --name typeorm-javascript-student-app --database mysql

Mở package.json để xóa các tham chiếu typecipt.

nguyên

{ 
   "name": "typeorm-javascript-student-app", "version": "0.0.1", 
   "description": "Awesome project developed with TypeORM.", "devDependencies": { 
      "ts-node": "3.3.0", "@types/node": "^8.0.29", "typescript": "3.3.3333" 
   }, 
   "dependencies": { 
      "typeorm": "0.2.24", "reflect-metadata": "^0.1.10", "mysql": "^2.14.1" 
   }, 
   "scripts": { 
      "start": "ts-node src/index.ts" } 
}

cập nhật

{ 
   "name": "typeorm-javascript-student-app", "version": "0.0.1", 
   "description": "Awesome project developed with TypeORM.", "dependencies": { 
      "typeorm": "0.2.24",
      "mysql": "^2.14.1" 
   }, 
   "scripts": { 
   "start": "node src/index.js" 
   } 
}

Đây,

  • Di chuyển devDependencies phần và gói liên quan đến tập chữ trong dependences phần.
  • Đã thay đổi tập lệnh bắt đầu thành mã javascript thay vì mã typecript.

Chạy lệnh dưới đây để cài đặt các gói cần thiết.

npm install

Tẩy tsconfig.json và tệp index.ts.

Xóa tệp User.ts bên trong thư mục thực thể và sau đó tạo thực thể sinh viên ở định dạng json, student.json như được chỉ định bên dưới -

{ 
   "name": "Student", 
   "columns": { 
      "id": { 
         "primary": true, 
         "type": "int", 
         "generated": true 
      }, 
      "name": { 
         "type": "varchar" 
      }, 
      "age": { 
         "type": "integer" 
      } 
   } 
}

Tạo một tệp mới, src / index.js và đặt mã bên dưới:

var typeorm = require("typeorm"); var EntitySchema = typeorm.EntitySchema; 

typeorm.createConnection({ 
   "type": "mysql", 
   "host": "localhost", 
   "port": 3306, 
   "username": "root", 
   "password": "123456", 
   "database": "typeorm_test_db",
   "synchronize": true, 
   "logging": false, 
   entities: [ new EntitySchema(require("./entity/student.json")) 
   ] 
}) 
.then(function(connection) { 
   return connection.getRepository("Student"); }) .then(function(studentRepository) { 
   var student = { 
      name: "Student1", 
      age: 18 
   }; 
   return studentRepository.save(student) .then(function(savedStudent) { console.log("Student has been successfully saved: ", savedStudent); 
   return studentRepository.find(); }) 
   .then(function(students) { console.log("All students: ", students); 
   return; 
   }) 
   .catch(function(error) { console.log("Error: ", error); return; 
   }) 
}) 
.catch(function(error) { console.log("Error: ", error) 
   return; });

Đây,

Chúng tôi đã sử dụng cùng một phương pháp typeORM ngoại trừ những thay đổi được đề cập bên dưới,

  • Đã sử dụng EntitySchema để định cấu hình thực thể sinh viên.
  • Đã sử dụng các khối JavaScript Promise khái niệm (sau đó / bắt / cuối cùng).

Bây giờ, chạy ứng dụng bằng lệnh dưới đây -

npm start

Ứng dụng chèn thông tin học sinh vào cơ sở dữ liệu và sau đó tìm nạp tất cả học sinh trong cơ sở dữ liệu và hiển thị trong bảng điều khiển như hình dưới đây -

> [email protected] start /path/to/workspace/typeorm-javascript-student-app

> node src/index.js 

Student has been successfully saved: { name: 'Student1', age: 18, id: 1 } All students: [ { id: 1, name: 'Student1', age: 18 } ]

Chương này giải thích hỗ trợ cơ sở dữ liệu MongoDB mở rộng do TypeORM cung cấp. Hy vọng rằng, chúng tôi đã cài đặt mongodb bằng npm. Nếu nó chưa được cài đặt, hãy sử dụng lệnh dưới đây để cài đặt trình điều khiển MongoDB,

npm install mongodb --save

Tạo một dự án

Hãy tạo một dự án mới bằng MongoDB như sau:

typeorm init --name MyProject --database mongodb

Định cấu hình ormconfig.json

Hãy định cấu hình các tùy chọn máy chủ, cổng và cơ sở dữ liệu MongoDB trong tệp ormconfig.json như được chỉ định bên dưới:

ormconfig.json

{ 
   "type": "mongodb", 
   "host": "localhost", 
   "port": 27017, 
   "database": "test", 
   "synchronize": true, 
   "logging": false, 
   "entities": [ 
      "src/entity/**/*.ts" 
   ], 
   "migrations": [ "src/migration/**/*.ts" 
   ], 
   "subscribers": [ "src/subscriber/**/*.ts" 
   ], 
   "cli": { 
      "entitiesDir": "src/entity", "migrationsDir": "src/migration", "subscribersDir": "src/subscriber" 
   } 
}

Xác định các thực thể và cột

Hãy để chúng tôi tạo một thực thể mới có tên là Sinh viên bên trong thư mục src của bạn. Các thực thể và cột giống nhau. Để tạo cột khóa chính, chúng tôi sử dụng@PrimaryColumn hoặc là

@PrimaryGeneratedColumn. Điều này có thể được định nghĩa là @ObjectIdColumn. Ví dụ đơn giản được hiển thị bên dưới -

Student.ts

import {Entity, ObjectID, ObjectIdColumn, Column} from "typeorm"; 

@Entity() 
export class Student {  

   @ObjectIdColumn() 
   id: ObjectID; 
   
   @Column() 
   Name: string; 
   
   @Column() 
   Country: string; 
}

Để lưu thực thể này, hãy mở tệp index.ts và thêm các thay đổi sau:

index.ts

import "reflect-metadata"; 
import {createConnection} from "typeorm"; 
import {Student} from "./entity/Student"; 

createConnection().then(async connection => { 

   console.log("Inserting a new Student into the database..."); const std = new Student(); std.Name = "Student1"; 
   std.Country = "India"; 
   await connection.manager.save(std); console.log("Saved a new user with id: " + std.id); 
   
   console.log("Loading users from the database..."); 
   const stds = await connection.manager.find(Student); console.log("Loaded users: ", stds); 
   
   console.log("TypeORM with MongoDB"); 
}).catch(error => console.log(error));

Bây giờ, khởi động máy chủ của bạn và bạn sẽ nhận được phản hồi sau:

npm start

MongoDB EntityManager

Chúng tôi cũng có thể sử dụng EntityManager để tìm nạp dữ liệu. Ví dụ đơn giản được hiển thị bên dưới -

import {getManager} from "typeorm";

const manager = getManager(); 
const result = await manager.findOne(Student, { id:1 });

Tương tự, chúng ta cũng có thể sử dụng kho lưu trữ để truy cập dữ liệu.

import {getMongoRepository} from "typeorm"; 

const studentRepository = getMongoRepository(Student); 
const result = await studentRepository.findOne({ id:1 });

Nếu bạn muốn lọc dữ liệu bằng cách sử dụng tùy chọn bằng như sau:

import {getMongoRepository} from "typeorm"; 

const studentRepository = getMongoRepository(Student); 
const result = await studentRepository.find({ 
   where: { 
      Name: {$eq: "Student1"}, 
   } 
});

Như chúng ta đã thấy trong chương này, TypeORM giúp dễ dàng làm việc với công cụ cơ sở dữ liệu MongoDB.

Express là một trong những khung JavaScript phổ biến để tạo ứng dụng web. Hãy để chúng tôi học cách sử dụngTypeORM cùng với khung thể hiện trong chương này.

Tạo một ứng dụng đơn giản

TypeORM CLI cung cấp một tùy chọn dễ dàng để tạo một ứng dụng web nhanh hoạt động hoàn chỉnh (ứng dụng API Restful) được tích hợp với TypeORM. Lệnh CLI để tạo ứng dụng như sau:

cd /path/to/workspace typeorm init --express --name typeorm-express-sample --database mysql

Lệnh trên sẽ tạo một ứng dụng web mới trong thư mục typeorm-express-sample. Cấu trúc của ứng dụng như sau:

│ .gitignore 
│ ormconfig.json 
│ package.json 
│ README.md 
│ tsconfig.json 
│ └───src 
      │ index.ts 
      │ routes.ts 
      │ 
      ├───controller 
      │      UserController.ts 
      │ 
      ├───entity 
      │      User.ts 
      │ 
      └───migration

Đây,

Như chúng ta biết, ormconfig.jsonTypeORMtập tin cấu hình. Mã như sau,

{ 
   "type": "mysql", 
   "host": "localhost", 
   "port": 3306, 
   "username": "test", 
   "password": "test", 
   "database": "test", 
   "synchronize": true, 
   "logging": false, 
   "entities": [
      "src/entity/**/*.ts" 
   ], 
   "migrations": [ "src/migration/**/*.ts" 
   ], 
   "subscribers": [ "src/subscriber/**/*.ts" 
   ], 
   "cli": { 
      "entitiesDir": "src/entity", "migrationsDir": "src/migration", "subscribersDir": "src/subscriber" 
   } 
}

Tại đây, hãy thay đổi cài đặt cơ sở dữ liệu để phù hợp với cài đặt cơ sở dữ liệu cục bộ của bạn.

package.json tệp là cấu hình chính của ứng dụng.

tsconfig.json tệp chứa cấu hình liên quan đến TypeScript.

entity thư mục chứa TypeORMcác mô hình. Mô hình Người dùng mặc định sẽ được tạo bởi CLI và nó như sau:

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

@Entity() 
export class User { 
   
   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   firstName: string; 
   
   @Column() 
   lastName: string; 
   
   @Column() 
   age: number; 
}

controllerthư mục chứa các bộ điều khiển nhanh. CLI tạo bộ điều khiển API người dùng mặc định với thêm / danh sách / xóa chi tiết người dùng. Mã như sau:

import {getRepository} from "typeorm"; import {NextFunction, Request, Response} from "express"; import {User} from "../entity/User"; 

export class UserController {

   private userRepository = getRepository(User); 
   
   async all(request: Request, response: Response, next: NextFunction) { 
      return this.userRepository.find(); 
   } 
   
   async one(request: Request, response: Response, next: NextFunction) { 
      return this.userRepository.findOne(request.params.id); 
   } 
   
   async save(request: Request, response: Response, next: NextFunction) { 
      return this.userRepository.save(request.body); 
   } 
   
   async remove(request: Request, response: Response, next: NextFunction) { 
      let userToRemove = await this.userRepository.findOne(request.params.id); 
      await this.userRepository.remove(userToRemove); 
   } 
}

Đây,

all được sử dụng để tìm nạp tất cả người dùng từ cơ sở dữ liệu.

one phương thức được sử dụng để tìm nạp một người dùng từ cơ sở dữ liệu bằng cách sử dụng user id

save được sử dụng để lưu thông tin người dùng vào cơ sở dữ liệu.

delete được sử dụng để xóa người dùng khỏi cơ sở dữ liệu bằng cách sử dụng user id

routes.ts tệp ánh xạ các phương thức của bộ điều khiển người dùng tới URL thích hợp và mã như sau:

import {UserController} from "./controller/UserController"; 

export const Routes = [{ 
      method: "get", 
      route: "/users", 
      controller: UserController, action: "all" 
   }, { 
      method: "get", 
      route: "/users/:id", controller: UserController, action: "one" 
   }, { 
      method: "post", 
      route: "/users", 
      controller: UserController, action: "save" 
   }, { 
      method: "delete", route: "/users/:id", controller: UserController,
      action: "remove" 
}];

Đây,

/ users url được ánh xạ tới bộ điều khiển người dùng. Mỗi bài đăng động từ, nhận và xóa được ánh xạ đến các phương thức khác nhau.

Cuối cùng, index.tslà điểm nhập ứng dụng web chính của chúng tôi. Mã nguồn như sau:

import "reflect-metadata"; 
import {createConnection} from "typeorm"; 
import * as express from "express"; import * as bodyParser from "body-parser"; 
import {Request, Response} from "express"; 
import {Routes} from "./routes"; import {User} from "./entity/User"; 

createConnection().then(async connection => { 

   // create express app const app = express(); app.use(bodyParser.json()); 

   // register express routes from defined application routes Routes.forEach(route => { 
      (app as any)[route.method](route.route, (req:   Request, res: Response, next: Function) => { 
         const result = (new (route.controller as any))[route.action](req, res, next); 
         if (result instanceof Promise) { 
            result.then(result => result !== null && result !== undefined ? res.send(result) : undefined); 
         } else if (result !== null && result !== undefined) { 
            .json(result); 
         } 
      }); 
   }); 
      
   // setup express app here 
   // ... 
      
   // start express server app.listen(3000); 
      
   // insert new users for test await connection.manager.save(connection.manager.create(User, { 
      firstName: "Timber",
      lastName: "Saw", 
      age: 27 
   }));
   await connection.manager.save(connection.manager.create(User, { 
      firstName: "Phantom", 
      lastName: "Assassin", 
      age: 24 
   })); 
      
   console.log("Express server has started on port 3000. Open http://localhost:3000/users to see results"); 
}).catch(error => console.log(error));

Tại đây, ứng dụng định cấu hình các tuyến đường, chèn hai người dùng và sau đó khởi động ứng dụng web ở cổng 3000 . Chúng ta có thể truy cập ứng dụng tạihttp://localhost:3000

Để chạy ứng dụng, hãy làm theo các bước sau:

Hãy để chúng tôi cài đặt các gói cần thiết bằng lệnh dưới đây -

npm install

Đầu ra

npm notice created a lockfile as package-lock.json. You should commit this file. 
npm WARN [email protected] No repository field. 
npm WARN [email protected] No license field. 

added 176 packages from 472 contributors and audited 351 packages in 11.965s 

3 packages are looking for funding  run `npm fund` for details 

found 0 vulnerabilities

Chạy lệnh dưới đây để khởi động ứng dụng.

npm start

Đầu ra

> [email protected] start /path/to/workspace/typeorm-express-sample 
> ts-node src/index.ts 

Express server has started on port 3000. Open http://localhost:3000/users to see results

Hãy để chúng tôi truy cập API ứng dụng web của chúng tôi bằng lệnh curl như bên dưới:

curl http://localhost:3000/users

Đây,

curl là một ứng dụng dòng lệnh để truy cập ứng dụng web từ dấu nhắc lệnh. Nó hỗ trợ tất cả các động từ HTTP như get, post, delete, v.v.,

Đầu ra

[{"id":1,"firstName":"Timber","lastName":"Saw","age":27},{"id":2,"firstName":"Phantom","lastName":"Assassin","age":24}]

Để tìm nạp bản ghi đầu tiên, chúng ta có thể sử dụng lệnh dưới đây:

curl http://localhost:3000/users/1

Đầu ra

{"id":1,"firstName":"Timber","lastName":"Saw","age":27}

Để xóa bản ghi người dùng, chúng ta có thể sử dụng lệnh dưới đây:

curl -X DELETE http://localhost:3000/users/1

Như chúng ta đã thấy trong chương này, TypeORM có thể dễ dàng tích hợp vào ứng dụng nhanh.

Di chuyển giống như kiểm soát phiên bản cho cơ sở dữ liệu của bạn. Nó được sử dụng để sửa đổi và chia sẻ lược đồ cơ sở dữ liệu của ứng dụng. Phần này giải thích về cách di chuyển hoạt động trong TypeORM.

Tạo di chuyển mới

Để tạo một di chuyển mới, trước tiên chúng ta cần thiết lập kết nối trong ormconfig.json. Nó được định nghĩa dưới đây -

ormconfig.json

"type": "mysql", 
"host": "localhost", 
"port": 8889, 
"username": "root", 
"password": "root", 
"database": "Library", 
"entities": ["entity/*.js"], "migrationsTableName": "student_migration_table", "migrations": ["migration/*.js"], "cli": { 
   "migrationsDir": "migration" 
}

Đây,

  • migrationsTableName - nó đề cập đến tên bảng di chuyển.
  • migrations - TypeORM tải các di chuyển từ thư mục nhất định.
  • cli - cho biết việc di chuyển sẽ tạo bên trong thư mục cụ thể.

Tạo thực thể Sách

Hãy tạo một thực thể có tên Book thực thể bên trong src/entity/Book.ts như sau -

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; 
@Entity() 
export class Book { 

   @PrimaryGeneratedColumn() 
   id: number; 
   
   @Column() 
   title: string;
   
   @Column() 
   text: string; 
}

Thực thi CLI để tạo di chuyển mới

Bây giờ, chúng ta có thể thực hiện quá trình di chuyển mới bằng CLI như sau:

Cú pháp

typeorm migration:create -n <migration-name>

Thí dụ

typeorm migration:create -n myMigration

Sau khi thực hiện lệnh trên, bạn có thể thấy phản hồi bên dưới:

Migration /path/to/project/src/migration/1587101104904-myMigration.ts has been generated successfully.

Bây giờ, di chuyển vào trong src/migration/1587101104904-myMigration.ts tệp trông tương tự như thế này.

import {MigrationInterface, QueryRunner} from "typeorm"; 

export class myMigration1587101104904 implements MigrationInterface {      

   public async up(queryRunner: QueryRunner): Promise<any> { 
   } 
   
   public async down(queryRunner: QueryRunner): Promise<any> { 
   } 
}

Đây,

Chúng tôi có hai phương pháp updown. up phương thức được sử dụng để thêm các thay đổi đối với việc di chuyển và down được sử dụng để hoàn nguyên các thay đổi trong quá trình di chuyển của bạn.

Hãy để chúng tôi thêm up phương pháp bên trong myMigration.ts tệp như được chỉ định bên dưới -

import {MigrationInterface, QueryRunner} from "typeorm"; 

export class Book1587131893261 implements MigrationInterface { 

   public async up(queryRunner: QueryRunner): Promise<any> { 
      await queryRunner.query(`ALTER TABLE book ADD COLUMN price int`); 
   }
   public async down(queryRunner: QueryRunner): Promise<any> { } 
}

Đây,

Chúng tôi đã thêm một cột mới price phía trong bookbàn. Bây giờ, hãy thực thi CLI để thêm các thay đổi trên.

ts-node ./node_modules/typeorm/cli.js migration:run

Lệnh trên thực hiện chuyển đổi và chạy chúng theo trình tự. Bây giờ, bạn có thể thấy những thay đổi dưới đây trên màn hình của mình -

Đầu ra

Bây giờ mở máy chủ mysql của bạn, cột mới được thêm vào. Nó được hiển thị bên dưới -

Tương tự, Chúng tôi có thể sửa đổi kiểu dữ liệu tiêu đề cột thành varchar (30) như sau,

import {MigrationInterface, QueryRunner} from "typeorm"; 

export class Book1587131893261 implements MigrationInterface { 

   public async up(queryRunner: QueryRunner): Promise<any> { 
   await queryRunner.query(`ALTER TABLE book MODIFY COLUMN title varchar(30)`); 
      } 
   public async down(queryRunner: QueryRunner): Promise<any> { 
   } 
}

Bây giờ, thực hiện cùng một lệnh và bạn có thể thực hiện các thay đổi bên dưới:

ts-node ./node_modules/typeorm/cli.js migration:run

Đầu ra

Book bảng được sửa đổi thành,

Hoàn nguyên di chuyển

Hãy thêm mã bên dưới vào bên trong down phương pháp hoàn nguyên di chuyển -

import {MigrationInterface, QueryRunner} from "typeorm"; 

export class Book1587131893261 implements MigrationInterface { 
   
   public async up(queryRunner: QueryRunner): Promise<any> { 
   
   } 
   public async down(queryRunner: QueryRunner): Promise<any> { 
   
      await queryRunner.query(`ALTER TABLE book drop column price`); // reverts things made in "up" method
   } 
}

Bây giờ, thực hiện lệnh dưới đây để hoàn nguyên tất cả các thay đổi -

ts-node ./node_modules/typeorm/cli.js migration:revert

Bạn có thể thấy phản hồi sau:

Đầu ra

Book bảng được sửa đổi thành,

Đầu ra

Như chúng ta đã thấy trong chương này, TypeORM giúp bạn dễ dàng viết tập lệnh di chuyển cơ sở dữ liệu.

Phần này giải thích chi tiết về các lệnh TypeORM CLI.

Tạo dự án TypeORM

typeorm initlà cách dễ nhất và nhanh nhất để thiết lập một dự án TypeORM. Bạn có thể tạo một dự án mới với tư cách là

typeorm init --name Demoproject --database mysql

Sau khi thực hiện lệnh, bạn sẽ nhận được kết quả sau trên màn hình của mình:

Project created inside /Users/workspace/TypeORM/Demoproject directory.

Tạo một thực thể

Để tạo một thực thể mới bằng cách sử dụng CLI,

typeorm entity:create -n Person

Bây giờ, thực thể Person được tạo bên trong thư mục src dự án của bạn.

Entity /Users/workspace/TypeORM/Demoproject/src/entity/Person.ts has been created successfully.

Nếu bạn có cấu trúc dự án nhiều mô-đun với nhiều thực thể trong các thư mục khác nhau, bạn có thể sử dụng lệnh dưới đây,

typeorm entity:create -n Person -d src/Person/entity

Tạo một người đăng ký mới

Để tạo một thuê bao mới bằng CLI như sau:

typeorm subscriber:create -n PersonSubscriber

Bạn có thể thấy phản hồi sau:

Subscriber /path/to/TypeORM/Demoproject/src/subscriber/PersonSubscriber.ts has been created successfully.

Tạo di chuyển

Bạn có thể tạo một di chuyển mới bằng CLI như được đề cập bên dưới -

typeorm migration:create -n PersonMigration

Lệnh trên đã tạo một thư mục di chuyển bên trong dự án của bạn src. Các tệp di chuyển được lưu trữ bên trong nó.

Migration /path/to/TypeORM/Demoproject/src/migration/1587395030750-PersonMigration.ts has been generated successfully.

Lược đồ cơ sở dữ liệu

Để đồng bộ hóa một lược đồ cơ sở dữ liệu, hãy sử dụng lệnh dưới đây:

typeorm schema:sync

Để loại bỏ hoàn toàn một lược đồ cơ sở dữ liệu, hãy sử dụng lệnh dưới đây:

typeorm schema:drop

Truy vấn sql

Nếu bạn muốn thực hiện bất kỳ truy vấn sql nào, chúng tôi có thể thực thi trực tiếp từ đây. Ví dụ: để hiển thị tất cả các bản ghi của khách hàng, hãy sử dụng truy vấn dưới đây:

typeorm query "select * from customers"

Nếu bạn muốn xóa mọi thứ được lưu trữ trong bộ nhớ cache. Bạn có thể làm điều đó bằng cách sử dụng lệnh sau:

typeorm cache:clear

Phần kết luận

TypeORM là một khung ORM mã nguồn mở tuyệt vời để tạo ra các ứng dụng chất lượng cao và có khả năng mở rộng từ các ứng dụng quy mô nhỏ đến các ứng dụng doanh nghiệp quy mô lớn với nhiều cơ sở dữ liệu.