最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

NestJS中集成TypeORM進行數(shù)據(jù)庫操作

 更新時間:2024年12月28日 11:03:54   作者:乘風遠洋  
本文深入探討了如何在NestJS中集成TypeORM進行數(shù)據(jù)庫操作,包括TypeORM的配置和集成、實體設計和關系映射、Repository模式的應用、事務處理方案、數(shù)據(jù)庫遷移管理、性能優(yōu)化策略

本文深入探討了如何在NestJS中集成TypeORM進行數(shù)據(jù)庫操作,包括TypeORM的配置和集成、實體設計和關系映射、Repository模式的應用、事務處理方案、數(shù)據(jù)庫遷移管理、性能優(yōu)化策略。

TypeORM 集成配置

1. 安裝依賴

首先安裝必要的依賴包:

npm install @nestjs/typeorm typeorm pg
# 如果使用 MySQL
# npm install @nestjs/typeorm typeorm mysql2

2. 數(shù)據(jù)庫配置

// src/config/database.config.ts
import { TypeOrmModuleOptions } from '@nestjs/typeorm';

export const databaseConfig: TypeOrmModuleOptions = {
  type: 'postgres',
  host: process.env.DB_HOST || 'localhost',
  port: parseInt(process.env.DB_PORT) || 5432,
  username: process.env.DB_USERNAME || 'postgres',
  password: process.env.DB_PASSWORD || 'postgres',
  database: process.env.DB_DATABASE || 'nestjs_db',
  entities: ['dist/**/*.entity{.ts,.js}'],
  synchronize: process.env.NODE_ENV !== 'production',
  logging: process.env.NODE_ENV !== 'production',
  ssl: process.env.DB_SSL === 'true',
};

// src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { databaseConfig } from './config/database.config';

@Module({
  imports: [
    TypeOrmModule.forRoot(databaseConfig),
    // 其他模塊
  ],
})
export class AppModule {}

實體設計與關系映射

1. 基礎實體設計

// src/entities/base.entity.ts
import { 
  PrimaryGeneratedColumn, 
  CreateDateColumn, 
  UpdateDateColumn,
  DeleteDateColumn 
} from 'typeorm';

export abstract class BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;

  @DeleteDateColumn()
  deletedAt: Date;
}

// src/users/entities/user.entity.ts
import { Entity, Column, OneToMany } from 'typeorm';
import { BaseEntity } from '../entities/base.entity';
import { Post } from './post.entity';

@Entity('users')
export class User extends BaseEntity {
  @Column({ length: 100 })
  name: string;

  @Column({ unique: true })
  email: string;

  @Column({ select: false })
  password: string;

  @OneToMany(() => Post, post => post.author)
  posts: Post[];
}

// src/posts/entities/post.entity.ts
import { Entity, Column, ManyToOne, JoinColumn } from 'typeorm';
import { BaseEntity } from '../entities/base.entity';
import { User } from './user.entity';

@Entity('posts')
export class Post extends BaseEntity {
  @Column()
  title: string;

  @Column('text')
  content: string;

  @Column({ default: false })
  published: boolean;

  @ManyToOne(() => User, user => user.posts)
  @JoinColumn({ name: 'author_id' })
  author: User;
}

2. 關系映射策略

// src/users/entities/profile.entity.ts
import { Entity, Column, OneToOne, JoinColumn } from 'typeorm';
import { BaseEntity } from '../entities/base.entity';
import { User } from './user.entity';

@Entity('profiles')
export class Profile extends BaseEntity {
  @Column()
  avatar: string;

  @Column('text')
  bio: string;

  @OneToOne(() => User)
  @JoinColumn({ name: 'user_id' })
  user: User;
}

// src/posts/entities/tag.entity.ts
import { Entity, Column, ManyToMany } from 'typeorm';
import { BaseEntity } from '../entities/base.entity';
import { Post } from './post.entity';

@Entity('tags')
export class Tag extends BaseEntity {
  @Column({ unique: true })
  name: string;

  @ManyToMany(() => Post, post => post.tags)
  posts: Post[];
}

// 更新 Post 實體,添加標簽關系
@Entity('posts')
export class Post extends BaseEntity {
  // ... 其他字段

  @ManyToMany(() => Tag, tag => tag.posts)
  @JoinTable({
    name: 'posts_tags',
    joinColumn: { name: 'post_id' },
    inverseJoinColumn: { name: 'tag_id' }
  })
  tags: Tag[];
}

數(shù)據(jù)庫操作實現(xiàn)

1. Repository 模式

// src/users/users.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { CreateUserDto, UpdateUserDto } from './dto';

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>
  ) {}

  async create(createUserDto: CreateUserDto): Promise<User> {
    const user = this.usersRepository.create(createUserDto);
    return await this.usersRepository.save(user);
  }

  async findAll(): Promise<User[]> {
    return await this.usersRepository.find({
      relations: ['posts', 'profile']
    });
  }

  async findOne(id: string): Promise<User> {
    const user = await this.usersRepository.findOne({
      where: { id },
      relations: ['posts', 'profile']
    });

    if (!user) {
      throw new NotFoundException(`User with ID ${id} not found`);
    }

    return user;
  }

  async update(id: string, updateUserDto: UpdateUserDto): Promise<User> {
    const user = await this.findOne(id);
    Object.assign(user, updateUserDto);
    return await this.usersRepository.save(user);
  }

  async remove(id: string): Promise<void> {
    const user = await this.findOne(id);
    await this.usersRepository.softRemove(user);
  }
}

2. 查詢構(gòu)建器

// src/posts/posts.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Post } from './entities/post.entity';

@Injectable()
export class PostsService {
  constructor(
    @InjectRepository(Post)
    private postsRepository: Repository<Post>
  ) {}

  async findPublishedPosts() {
    return await this.postsRepository
      .createQueryBuilder('post')
      .leftJoinAndSelect('post.author', 'author')
      .leftJoinAndSelect('post.tags', 'tags')
      .where('post.published = :published', { published: true })
      .orderBy('post.createdAt', 'DESC')
      .getMany();
  }

  async searchPosts(query: string) {
    return await this.postsRepository
      .createQueryBuilder('post')
      .leftJoinAndSelect('post.author', 'author')
      .where('post.title ILIKE :query OR post.content ILIKE :query', {
        query: `%${query}%`
      })
      .orderBy('post.createdAt', 'DESC')
      .getMany();
  }

  async getPostStats() {
    return await this.postsRepository
      .createQueryBuilder('post')
      .select('author.name', 'authorName')
      .addSelect('COUNT(*)', 'postCount')
      .leftJoin('post.author', 'author')
      .groupBy('author.name')
      .getRawMany();
  }
}

事務處理

1. 事務裝飾器

// src/common/decorators/transaction.decorator.ts
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { getManager } from 'typeorm';

export const Transaction = createParamDecorator(
  async (data: unknown, ctx: ExecutionContext) => {
    const queryRunner = getManager().connection.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();
    return queryRunner;
  }
);

// 使用示例
@Post('transfer')
async transfer(
  @Transaction() queryRunner,
  @Body() transferDto: TransferDto
) {
  try {
    // 執(zhí)行轉(zhuǎn)賬操作
    await queryRunner.manager.update(Account, 
      transferDto.fromId, 
      { balance: () => `balance - ${transferDto.amount}` }
    );

    await queryRunner.manager.update(Account, 
      transferDto.toId, 
      { balance: () => `balance + ${transferDto.amount}` }
    );

    await queryRunner.commitTransaction();
  } catch (err) {
    await queryRunner.rollbackTransaction();
    throw err;
  } finally {
    await queryRunner.release();
  }
}

2. 事務管理器

// src/common/services/transaction.service.ts
import { Injectable } from '@nestjs/common';
import { Connection, QueryRunner } from 'typeorm';

@Injectable()
export class TransactionService {
  constructor(private connection: Connection) {}

  async executeInTransaction<T>(
    callback: (queryRunner: QueryRunner) => Promise<T>
  ): Promise<T> {
    const queryRunner = this.connection.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();

    try {
      const result = await callback(queryRunner);
      await queryRunner.commitTransaction();
      return result;
    } catch (err) {
      await queryRunner.rollbackTransaction();
      throw err;
    } finally {
      await queryRunner.release();
    }
  }
}

// 使用示例
@Injectable()
export class PaymentService {
  constructor(
    private transactionService: TransactionService,
    private ordersService: OrdersService
  ) {}

  async processPayment(paymentDto: PaymentDto) {
    return await this.transactionService.executeInTransaction(async queryRunner => {
      const order = await this.ordersService.findOne(paymentDto.orderId);
      
      // 更新訂單狀態(tài)
      await queryRunner.manager.update(Order, order.id, {
        status: 'paid'
      });

      // 創(chuàng)建支付記錄
      const payment = queryRunner.manager.create(Payment, {
        order,
        amount: paymentDto.amount
      });
      await queryRunner.manager.save(payment);

      return payment;
    });
  }
}

數(shù)據(jù)庫遷移

1. 遷移配置

// ormconfig.js
module.exports = {
  type: 'postgres',
  host: process.env.DB_HOST,
  port: parseInt(process.env.DB_PORT),
  username: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_DATABASE,
  entities: ['dist/**/*.entity{.ts,.js}'],
  migrations: ['dist/migrations/*{.ts,.js}'],
  cli: {
    migrationsDir: 'src/migrations'
  }
};

// package.json
{
  "scripts": {
    "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js",
    "migration:create": "npm run typeorm migration:create -- -n",
    "migration:generate": "npm run typeorm migration:generate -- -n",
    "migration:run": "npm run typeorm migration:run",
    "migration:revert": "npm run typeorm migration:revert"
  }
}

2. 遷移示例

// src/migrations/1642340914321-CreateUsersTable.ts
import { MigrationInterface, QueryRunner, Table } from 'typeorm';

export class CreateUsersTable1642340914321 implements MigrationInterface {
  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.createTable(
      new Table({
        name: 'users',
        columns: [
          {
            name: 'id',
            type: 'uuid',
            isPrimary: true,
            generationStrategy: 'uuid',
            default: 'uuid_generate_v4()'
          },
          {
            name: 'name',
            type: 'varchar',
            length: '100'
          },
          {
            name: 'email',
            type: 'varchar',
            isUnique: true
          },
          {
            name: 'password',
            type: 'varchar'
          },
          {
            name: 'created_at',
            type: 'timestamp',
            default: 'now()'
          },
          {
            name: 'updated_at',
            type: 'timestamp',
            default: 'now()'
          },
          {
            name: 'deleted_at',
            type: 'timestamp',
            isNullable: true
          }
        ]
      })
    );
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.dropTable('users');
  }
}

性能優(yōu)化

1. 查詢優(yōu)化

// src/posts/posts.service.ts
@Injectable()
export class PostsService {
  constructor(
    @InjectRepository(Post)
    private postsRepository: Repository<Post>
  ) {}

  // 使用分頁和緩存
  async findAll(page = 1, limit = 10) {
    const [posts, total] = await this.postsRepository.findAndCount({
      relations: ['author', 'tags'],
      skip: (page - 1) * limit,
      take: limit,
      cache: {
        id: `posts_page_${page}`,
        milliseconds: 60000 // 1分鐘緩存
      }
    });

    return {
      data: posts,
      meta: {
        total,
        page,
        lastPage: Math.ceil(total / limit)
      }
    };
  }

  // 使用子查詢優(yōu)化
  async findPopularPosts() {
    return await this.postsRepository
      .createQueryBuilder('post')
      .leftJoinAndSelect('post.author', 'author')
      .addSelect(subQuery => {
        return subQuery
          .select('COUNT(*)', 'commentCount')
          .from('comments', 'comment')
          .where('comment.postId = post.id');
      }, 'commentCount')
      .orderBy('commentCount', 'DESC')
      .limit(10)
      .getMany();
  }
}

2. 索引優(yōu)化

// src/posts/entities/post.entity.ts
@Entity('posts')
@Index(['title', 'content']) // 復合索引
export class Post extends BaseEntity {
  @Column()
  @Index() // 單列索引
  title: string;

  @Column('text')
  content: string;

  @Column()
  @Index()
  authorId: string;

  // ... 其他字段
}

寫在最后

本文詳細介紹了 NestJS 中的數(shù)據(jù)庫操作實踐:

  1. TypeORM 的配置和集成
  2. 實體設計和關系映射
  3. Repository 模式的應用
  4. 事務處理方案
  5. 數(shù)據(jù)庫遷移管理
  6. 性能優(yōu)化策略

到此這篇關于NestJS中集成TypeORM進行數(shù)據(jù)庫操作的文章就介紹到這了,更多相關NestJS集成TypeORM數(shù)據(jù)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • node.js中Koa框架的具體實現(xiàn)

    node.js中Koa框架的具體實現(xiàn)

    Koa由Express團隊打造,解決回調(diào)地獄等問題,采用async/await和統(tǒng)一Context對象,下面就來介紹一下Koa框架的使用,感興趣的可以了解一下
    2025-08-08
  • nodejs之koa2請求示例(GET,POST)

    nodejs之koa2請求示例(GET,POST)

    本篇文章主要介紹了nodejs之koa2請求示例(GET,POST),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • 詳解node+express+ejs+bootstrap構(gòu)建項目

    詳解node+express+ejs+bootstrap構(gòu)建項目

    本篇文章主要介紹了詳解node+express+ejs+bootstrap構(gòu)建項目,非常具有實用價值,需要的朋友可以參考下
    2017-09-09
  • nodejs redis 發(fā)布訂閱機制封裝實現(xiàn)方法及實例代碼

    nodejs redis 發(fā)布訂閱機制封裝實現(xiàn)方法及實例代碼

    這篇文章主要介紹了nodejs redis 發(fā)布訂閱機制封裝的相關資料,這里提供了實現(xiàn)方法,及實例代碼,具有參考價值,需要的朋友可以參考下
    2016-12-12
  • 圖解NodeJS實現(xiàn)登錄注冊功能

    圖解NodeJS實現(xiàn)登錄注冊功能

    這篇文章主要介紹了NodeJS實現(xiàn)登錄注冊功能,本文圖文并茂給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • windows如何把已安裝的nodejs高版本降級為低版本(圖文教程)

    windows如何把已安裝的nodejs高版本降級為低版本(圖文教程)

    這篇文章主要介紹了windows如何把已安裝的nodejs高版本降級為低版本,本文分步驟通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Node.js(安裝,啟動,測試)

    Node.js(安裝,啟動,測試)

    這里主要介紹基于windows平臺上最簡單方便的安裝方式,啟動以及簡單測試
    2014-06-06
  • NodeJS制作爬蟲全過程

    NodeJS制作爬蟲全過程

    這篇文章主要介紹了NodeJS制作爬蟲的全過程,包括項目建立,目標網(wǎng)站分析、使用superagent獲取源數(shù)據(jù)、使用cheerio解析、使用eventproxy來并發(fā)抓取每個主題的內(nèi)容等方面,有需要的小伙伴參考下吧。
    2014-12-12
  • Node.js學習教程之HTTP/2服務器推送【譯】

    Node.js學習教程之HTTP/2服務器推送【譯】

    這篇文章主要給大家介紹了關于Node.js學習教程之HTTP/2服務器推送的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2017-10-10
  • 10個Node.js庫幫助你優(yōu)化代碼和簡化開發(fā)

    10個Node.js庫幫助你優(yōu)化代碼和簡化開發(fā)

    這篇文章主要介紹了10個Node.js庫幫助你優(yōu)化代碼和簡化開發(fā),其中包括處理數(shù)組、對象、字符串庫Lodash,緩存數(shù)據(jù)處理庫Node-cache,解析、操作和格式化日期和時間庫Moment.js,Redis操作庫,發(fā)送電子郵件庫Nodemailer
    2023-05-05

最新評論

海城市| 德州市| 弥勒县| 宜宾县| 宁武县| 滨海县| 张家港市| 澎湖县| 牡丹江市| 盐城市| 津南区| 太和县| 连山| 山西省| 清苑县| 榆中县| 德钦县| 清涧县| 铜鼓县| 宜昌市| 盐山县| 钟祥市| 深泽县| 吉木萨尔县| 临沂市| 邯郸县| 白玉县| 博客| 信丰县| 博客| 阜阳市| 资源县| 土默特左旗| 河北区| 阳信县| 阳曲县| 农安县| 遂宁市| 巴南区| 西盟| 盐津县|