متن خبر

نحوه راه اندازی TypeORM DataSource در پروژه NestJS

نحوه راه اندازی TypeORM DataSource در پروژه NestJS

شناسهٔ خبر: 466932 -




سلام! 👋 از زمانی که کار با NestJS را شروع کردم، به دنبال راهی مطمئن برای مدیریت پایگاه داده خود با TypeORM بودم. امروز، من سفرم و مراحلی را که برای تنظیم آن انجام دادم به اشتراک می‌گذارم.

خوب، قبل از اینکه وارد آن شویم، بیایید سعی کنیم بفهمیم TypeORM و NestJS چیست.

فهرست مطالب:

TypeORM چیست؟

NestJS چیست؟

پیش نیازهای آموزشی

چگونه یک پروژه NestJS را راه اندازی کنیم

نحوه تنظیم TypeORM DataSource برای پایداری داده

گسترش مخزن منبع داده برای روش های سفارشی

نتیجه

منابع

TypeORM چیست؟

TypeORM یک ابزار Object-Relational Mapping (ORM) است که کار با پایگاه های داده را در برنامه های Node.js و TypeScript ساده می کند. این پایگاه داده های مختلفی مانند MySQL، PostgreSQL، SQLite و غیره را پشتیبانی می کند و به توسعه دهندگان این امکان را می دهد تا از مفاهیم برنامه نویسی شی گرا به جای پرداختن به پرس و جوهای سطح پایین SQL استفاده کنند.

TypeORM همچنین ویژگی هایی مانند مهاجرت طرحواره، ساخت پرس و جو و مدیریت روابط بین جداول را فراهم می کند.

NestJS چیست؟

NestJS یک فریم ورک پیشرو Node.js است که برای ساخت برنامه های کاربردی سمت سرور کارآمد، قابل اعتماد و مقیاس پذیر طراحی شده است. از ویژگی های TypeScript استفاده می کند تا توسعه دهندگان را قادر به نوشتن کدهای ساختاریافته و قابل نگهداری کند.

NestJS از یک الگوی معماری مدولار استفاده می کند و به شما امکان می دهد کد خود را در ماژول ها، کنترلرها، سرویس ها و ارائه دهندگان سازماندهی کنید. پشتیبانی داخلی از آپشن های ی مانند تزریق وابستگی، میان‌افزار و GraphQL را فراهم می‌کند و آن را به گزینه‌ای محبوب برای ساخت برنامه‌های وب مدرن و API تبدیل می‌کند.

علاوه بر این، NestJS به طور یکپارچه با سایر کتابخانه ها و چارچوب ها، از جمله TypeORM، ادغام می شود تا گردش کار توسعه را ساده کند. در زیر هود، از یک چارچوب سرور HTTP قوی مانند Express (پیش‌فرض) استفاده می‌کند و می‌تواند برای استفاده از سایر چارچوب‌های سرور HTTP Node.js پیکربندی شود.

خوب، این خیلی است، درست است؟ خوب، قبل از اینکه ادامه دهیم، بیایید سعی کنیم عبارت "NestJS یک چارچوب Node.js مترقی است" را تجزیه کنیم، که به سادگی به این معنی است که NestJS از آخرین ویژگی های زبان جاوا اسکریپت و فریمورک های سرور استفاده می کند و در نتیجه انعطاف پذیری را برای توسعه دهندگان برای نوشتن فراهم می کند. کد در مناسب ترین زبان برای پروژه های خود. (منبع)

پیش نیازهای آموزشی

Node.js. حداقل نسخه 18

npm حداقل نسخه 8

Postgresql. از اینجا دانلود کنید

آشنایی اولیه با Typescirpt و Nestjs

Pgadmin 4. از اینجا دانلود کنید

چگونه یک پروژه NestJS را راه اندازی کنیم

دستورات زیر را برای نصب پروژه NestJS خود اجرا کنید:

 npm i -g @nestjs/cli # install nestj cli globally nest new simple-crm # start a new nestjs project

پس از نصب، سرور توسعه را اجرا کنید:

 npm run start:dev # start the app in watch mode

اکنون، بیایید پروژه خود را آزمایش کنیم تا ببینیم آیا nest-cli به درستی همه کد صفحه دیگ بخار را با ارسال یک درخواست دریافت به آدرس ریشه / تنظیم کرده است.

init_test
init_test

خوب! پروژه ما در حال اجر است.

نحوه تنظیم TypeORM DataSource برای پایداری داده

 npm install --save @nestjs/typeorm typeorm # nestjs typeorm drivers npm install --save pg # typeorm postgressql driver

بیایید پایگاه داده پروژه را از رابط Pgadmin 4 ایجاد کنیم

رابط Pgadmin 4 را باز کنید و روی تب Databases کلیک راست کنید تا پایگاه داده جدید ایجاد کنید.

create_db-1
create_db-1
create_db-2
create_db-2

تایید کنید پایگاه داده شما با موفقیت ایجاد شده است.

confirm_db
confirm_db

عالی است، وقت آن است که پایگاه داده را با استفاده از TypeORM به برنامه NestJS خود اضافه کنیم.

پوشه جدید، منبع داده را در پوشه src/ برنامه خود ایجاد کنید، مانند این 👇

datasource_folder
confirm_folder

یک فایل typeorm.module.ts جدید در پوشه datasource ایجاد کنید و کد زیر را اضافه کنید:

 import { DataSource } from 'typeorm'; import { Global, Module } from '@nestjs/common'; @Global() // makes the module available globally for other modules once imported in the app modules @Module({ imports: [], providers: [ { provide: DataSource, // add the datasource as a provider inject: [], useFactory: async () => { // using the factory function to create the datasource instance try { const dataSource = new DataSource({ type: 'postgres', host: 'localhost', port: 5432, username: 'ayo', password: 'haywon', database: 'simple-crm_db', synchronize: true, entities: [`${__dirname}/../**/**.entity{.ts,.js}`], // this will automatically load all entity file in the src folder }); await dataSource.initialize(); // initialize the data source console.log('Database connected successfully'); return dataSource; } catch (error) { console.log('Error connecting to database'); throw error; } }, }, ], exports: [DataSource], }) export class TypeOrmModule {}

ماژول TypeORM را به آرایه واردات ماژول App اضافه کنید، مانند این 👇

 import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { TypeOrmModule } from './datasource/typeorm.module'; @Module({ imports: [TypeOrmModule], controllers: [AppController], providers: [AppService], }) export class AppModule {}

سپس ذخیره کرده و از کنسول خود تأیید کنید که آیا پایگاه داده با موفقیت وصل شده است.

db_conn_success
show_db_success_conn

اگر دیدید که پایگاه داده با موفقیت متصل شده است، کار خوبی است! در غیر این صورت، به مراحل قبلی برگردید تا ببینید آیا تنظیمات را به درستی دنبال کرده اید یا خیر.

اکنون، می‌توانیم با استفاده از TypeORM به مصرف سرویس datasource خود ادامه دهیم.

بیایید ماژول users ، کنترل‌کننده، ارائه‌دهنده و موجودیت ایجاد کنیم تا با پایگاه داده جدید متصل شده خود تعامل داشته باشیم.

 nest g module users && nest g service users && nest g controller users

دستور بالا ماژول users ، سرویس و کنترلر را تولید می کند و app.module.ts را با ماژول users به روز می کند.

کد زیر را داخل فایل users.entity.ts اضافه کنید و سرور توسعه خود را مجددا راه اندازی کنید تا جدول user در پایگاه داده ایجاد شود.

 import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; @Entity('user') export class UserEntity { @PrimaryGeneratedColumn() id: number; @Column({ unique: true }) username: string; @Column() password: string; }

رابط Pgadmin 4 خود را تحلیل کنید و تأیید کنید که TypeORM به طور خودکار UserEntity را بارگیری کرده و جدول user را در پایگاه داده شما ایجاد کرده است، مانند این 👇.

confirm_user_table
confirm_user_table

اگر ابتدا پایگاه داده را نمی بینید، ممکن است بخواهید آن را به روز کنید.

اکنون بیایید اولین کنترل کننده خدمات users خود را پیاده سازی کنیم، کد زیر را به فایل users.service.ts خود اضافه کنیم:

 import { HttpException, HttpStatus, Injectable, InternalServerErrorException, Logger, } from '@nestjs/common'; import { DataSource } from 'typeorm'; import { UserEntity } from './users.entity'; export interface CreateUser { username: string; password: string; } @Injectable() export class UsersService { private userRepository; private logger = new Logger(); // inject the Datasource provider constructor(private dataSource: DataSource) { // get users table repository to interact with the database this.userRepository = this.dataSource.getRepository(UserEntity); } // create handler to create new user and save to the database async createUser(createUser: CreateUser): Promise<UserEntity> { try { const user = await this.userRepository.create(createUser); return await this.userRepository.save(user); } catch (err) { if (err.code == 23505) { this.logger.error(err.message, err.stack); throw new HttpException('Username already exists', HttpStatus.CONFLICT); } this.logger.error(err.message, err.stack); throw new InternalServerErrorException( 'Something went wrong, Try again!', ); } } }

ما متد createUser اضافه کرده‌ایم تا زمانی که یک درخواست POST با بدنه درخواست مورد نیاز به کنترل‌کننده نقطه پایانی ارسال می‌شود که از متد سرویس createUser استفاده می‌کند، ایجاد یک کاربر را مدیریت کند.

تابع یک شی createUser به عنوان آرگومان از نوع CreateUser interface می گیرد. معمولاً، این باید یک DTO (Data Transfer Object) برای ساختار نوع داده و اعتبارسنجی باشد، اما از آنجایی که خارج از محدوده این آموزش است، ما از رابط فقط برای شکل داده استفاده می کنیم.

ما متد create userRepository را فراخوانی کردیم و سپس بازگشت آن را به متغیر user برای نگه داشتن شی کاربر جدید ایجاد شده اختصاص دادیم. سپس متد save را برای ذخیره شی در پایگاه داده فراخوانی کردیم.

اکنون، اجازه دهید از کنترلر سرویس createUser در کنترلر users خود استفاده کنیم که درخواست POST را برای ایجاد کاربر جدید مدیریت می کند.

 import { Body, Controller, Post } from '@nestjs/common'; import { CreateUser, UsersService } from './users.service'; @Controller('users') export class UsersController { constructor(private userService: UsersService) {} @Post('/create') // handles the post request to /users/create endpoint to create new user async signUp(@Body() user: CreateUser) { return await this.userService.createUser(user); } }

نقطه پایانی جدید ایجاد شده را با ارسال یک درخواست POST به http://localhost:3000/users/create با نام کاربری و رمز عبور به عنوان بدنه درخواست آزمایش کنید.

test_user_create
test_user_create_endpoint

خوب، بیایید پایگاه داده را تحلیل کنیم تا مطمئن شویم که همه اینها است، زیرا ما قبلاً یک کد وضعیت پاسخ 201 دریافت کرده ایم که باید برای دانستن اینکه برنامه ما به راحتی با پایگاه داده ما با استفاده از منبع داده TypeORM در تعامل است کافی است.

confirm_user_db
confirm_user_db

گسترش مخزن منبع داده برای روش های سفارشی

خواه به دنبال بهینه سازی پرس و جوهای پایگاه داده، معرفی عملیات دستکاری داده های جدید، یا ادغام با خدمات شخص ثالث هستید، گسترش مخزن DataSource با روش های سفارشی می تواند یک تغییر بازی در تعامل یکپارچه با پایگاه داده باشد.

در اینجا، مزایای روش‌های سفارشی را تحلیل می‌کنیم و راهنمای گام به گام پیاده‌سازی آن‌ها در برنامه‌های NestJS شما را ارائه می‌کنیم. پس ، بیایید غواصی کنیم و پتانسیل کامل مخزن DataSource را باز کنیم!

برخی از مزایای اساسی روش های سفارشی مخزن عبارتند از:

عملکرد متناسب: روش‌های سفارشی به توسعه‌دهندگان اجازه می‌دهد تا قابلیت‌های خاصی را معرفی کنند که در مخزن استاندارد DataSource موجود نیستند. با تنظیم مخزن DataSource با روش‌های سفارشی، توسعه‌دهندگان می‌توانند موارد استفاده منحصربه‌فرد، عملیات دستکاری داده‌ها و تجمیع‌ها یا بهینه‌سازی‌هایی را که برای نیازمندی‌های پروژه‌شان ضروری است، تحلیل کنند.

عملکرد بهینه شده: روش های سفارشی را می توان برای بهینه سازی پرس و جوهای پایگاه داده، بازیابی داده ها و عملیات دستکاری داده ها طراحی کرد که منجر به بهبود عملکرد و کارایی می شود. با استفاده از روش‌های سفارشی، توسعه‌دهندگان می‌توانند الگوریتم‌های بهینه، مکانیسم‌های کش یا بهینه‌سازی‌های پرس و جو را متناسب با نیازها و آپشن های برنامه‌های کاربردی خود پیاده‌سازی کنند.

قابلیت استفاده مجدد و نگهداری کد بهبود یافته: روش های سفارشی قابلیت استفاده مجدد کد را با کپسوله کردن منطق، الگوریتم ها یا عملیات خاص در اجزای قابل استفاده مجدد افزایش می دهند. با مدولار کردن روش‌های سفارشی، توسعه‌دهندگان می‌توانند پایگاه‌های کد تمیزتر، سازمان‌یافته‌تر و قابل نگهداری‌تر را حفظ کنند و مدیریت، اشکال‌زدایی و ارتقای مخزن DataSource را در دراز مدت آسان‌تر کنند.

خوب، همین است، بیایید به سمت عمل حرکت کنیم. پس ، ما یک برنامه CRM ساده داریم که با مدیریت کاربر ارتباط دارد. بیایید یک روش مخزن سفارشی اضافه کنیم که می تواند به ما کمک کند کاربران را بر اساس نام کاربری فیلتر کنیم.

برای پیاده سازی این، اجازه دهید ماژول datasource و سرویس datasource خود را ایجاد کنیم. ما قصد داریم این فایل ها را ایجاد کنیم تا با اصول ماژولار بودن الگوی معماری NestJS هماهنگ شوند.

فایل ها را در پوشه منبع داده ای که قبلا ایجاد کرده اید ایجاد کنید و کد زیر را اضافه کنید:

 // datasource.module.ts import { Module } from '@nestjs/common'; import { TypeOrmModule } from './typeorm.module'; import { DataSourceService } from './datasource.service'; @Module({ imports: [TypeOrmModule], providers: [DataSourceService], exports: [DataSourceService], }) export class DataSourceModule {}
 // datasource.service.ts import { Injectable } from '@nestjs/common'; import { UserEntity } from 'src/users/users.entity'; import { DataSource } from 'typeorm'; export interface UsernameQuery { username: string; } @Injectable() export class DataSourceService { constructor(private dataSource: DataSource) {} // extend userRepository to add custom methods userCustomRepository = this.dataSource.getRepository(UserEntity).extend({ async filterUser(usernameQuery: UsernameQuery): Promise<UserEntity[]> { const { username } = usernameQuery; console.log(username); // initialize a query builder for the userrepository const query = this.createQueryBuilder('user'); // filter user where username is like the passed username query.where('(LOWER(user.username) LIKE LOWER(:username))', { username: `%${username}%`, }); return await query.getMany(); }, }); }

از کد بالا datasource.service.ts ، UserRepository را با فراخوانی متد getRepository در سرویس dataSource و ارسال UserEntity به عنوان آرگومان برای دریافت مخزن برای جدول خاص، گسترش دادیم.

سپس متد extend را در userRepository که از getRepository خود برگشتیم فراخوانی کردیم تا متد سفارشی خود را اضافه کنیم. در متد extend خود، یک شی ارسال کردیم که حاوی تمام متدهای سفارشی ما برای مخزن سفارشی است که به userCustomRepository اختصاص داده‌ایم. در اینجا، ما فقط یک روش سفارشی را به مخزن کاربر سفارشی خود اضافه کرده ایم که filterUser است. این یک پرس و جو فیلتر را بر روی جدول کاربر توسط نام کاربری ارائه شده اجرا می کند.

از آنجایی که DataSourseService ما تزریقی است، می‌توانیم آن را در UserService خود تزریق کنیم و پس از اضافه کردن DataSourceModule به آرایه واردات ماژول کاربر، آن را به روش جدید filterUser مصرف کنیم.

 // users.module.ts import { Module } from '@nestjs/common'; import { UsersController } from './users.controller'; import { UsersService } from './users.service'; import { DataSourceModule } from 'src/datasource/datasource.module'; @Module({ imports: [DataSourceModule], // add the DataSourceModule to the import array providers: [UsersService], controllers: [UsersController], }) export class UsersModule {}

بیایید روش فیلتر را از CustomUserRepository در UserService خود مصرف کنیم تا کاربران را با هر نام کاربری که هنگام ارسال درخواست به عنوان آرگومان درخواست ما ارسال می شود فیلتر کنیم.

 // users.service.ts import { HttpException, HttpStatus, Injectable, InternalServerErrorException, Logger, } from '@nestjs/common'; import { DataSource } from 'typeorm'; import { UserEntity } from './users.entity'; import { DataSourceService, UsernameQuery, } from 'src/datasource/datasource.service'; export interface CreateUser { username: string; password: string; } @Injectable() export class UsersService { private userRepository; private customUserRepository; private logger = new Logger(); // inject the Datasource provider constructor( private dataSource: DataSource, private dataSourceService: DataSourceService, // inject our datasource service ) { // get users table repository to interact with the database this.userRepository = this.dataSource.getRepository(UserEntity); // assigning the dataSourceService userCustomRepository to the class customUserRepository this.customUserRepository = this.dataSourceService.userCustomRepository; } // create handler to create new user and save to the database async createUser(createUser: CreateUser): Promise<UserEntity> { try { const user = await this.userRepository.create(createUser); return await this.userRepository.save(user); } catch (err) { if (err.code == 23505) { this.logger.error(err.message, err.stack); throw new HttpException('Username already exists', HttpStatus.CONFLICT); } this.logger.error(err.message, err.stack); throw new InternalServerErrorException( 'Something went wrong, Try again!', ); } } // the userService filterByUsername handler async filterByUsername(usernameQuery: UsernameQuery): Promise<UserEntity[]> { try { // calling the customUserRepository filterUser custom method return await this.customUserRepository.filterUser(usernameQuery); } catch (err) { this.logger.error(err.message, err.stack); throw new InternalServerErrorException( 'Something went wrong, Try again!', ); } } }

از موارد بالا، کدی را که ما DataSourceService سفارشی خود را با گفت ن موارد زیر به private dataSourceService: DataSourceService, .

سرویس filterByUsername درخواستی را که ما در روش سفارشی filterUser مصرف می‌کنیم رسیدگی می‌کند await this .customUserRepository.filterUser(usernameQuery); ، که یک وعده را برمی گرداند.

اکنون، بیایید از این کنترلر سرویس در کنترلر کاربر خود برای فیلتر کردن کاربران بر اساس نام کاربری خود استفاده کنیم.

 // users.controller.ts import { Body, Controller, Get, Post, Query } from '@nestjs/common'; import { CreateUser, UsersService } from './users.service'; import { UserEntity } from './users.entity'; import { UsernameQuery } from 'src/datasource/datasource.service'; @Controller('users') export class UsersController { constructor(private userService: UsersService) {} @Post('/create') // handles the post request to /users/create endpoint to create new user async signUp(@Body() user: CreateUser): Promise<UserEntity> { return await this.userService.createUser(user); } @Get('') // get request handler that returns the filtered results of the users table async filterUser( @Query() usernameQuery: UsernameQuery // extracts the username query param for the endpoint url, ): Promise<UserEntity[]> { return await this.userService.filterByUsername(usernameQuery); } }

نقطه پایانی فیلتر ما را آزمایش کنید،

تست-فیلتر
test_filter_endpoint

در اینجا، ما یک فهرست با یک شی کاربر با نام کاربری مانند نام کاربری که به عنوان پرس و جو ارسال کردیم، دریافت کردیم.

نتیجه

وویلا! تمام است، اکنون شما آماده شروع کار با NestJS، TypeORM و DataSource هستید.

با تشکر برای خواندن!

اگر آن را مفید یافتید، لطفاً آن را با دوستان و همکاران خود به اشتراک بگذارید! منتظر مطالب روشنگرتر باشید و بیایید با هم به یادگیری و رشد ادامه دهیم. به سلامتی برای ساخت راه حل های هوشمندتر و کارآمدتر با NestJS!

منابع

صفحه اسناد NestJS

صفحه اسناد TypeORM

دوره کامل NestJS را یاد بگیرید

توییتر

لینکدین

GitHub

خبرکاو

ارسال نظر




تبليغات ايهنا تبليغات ايهنا

تمامی حقوق مادی و معنوی این سایت متعلق به خبرکاو است و استفاده از مطالب با ذکر منبع بلامانع است