能否在NestJS中不使用TypeORM查询MySQL并执行原生SQL?
在NestJS中不借助ORM直接执行MySQL原生SQL查询
当然可以,你有两种主流方式实现:
方法1:通过TypeORM执行原生SQL
TypeORM本身支持原生SQL查询,不需要完全替换掉它。你可以利用EntityManager或QueryRunner来执行原生语句:
使用EntityManager.query()(基础场景)
import { Injectable } from '@nestjs/common'; import { InjectEntityManager } from '@nestjs/typeorm'; import { EntityManager } from 'typeorm'; @Injectable() export class UserService { constructor( @InjectEntityManager() private readonly entityManager: EntityManager, ) {} async getUsers() { // 执行原生SELECT查询 const users = await this.entityManager.query('SELECT * FROM users'); return users; } async createUser(name: string, email: string) { // 用参数绑定防止SQL注入 const result = await this.entityManager.query( 'INSERT INTO users (name, email) VALUES (?, ?)', [name, email], ); return result; } }
使用QueryRunner(事务场景)
如果需要处理事务,QueryRunner是更合适的选择:
import { Injectable } from '@nestjs/common'; import { InjectConnection } from '@nestjs/typeorm'; import { Connection, QueryRunner } from 'typeorm'; @Injectable() export class UserService { constructor(@InjectConnection() private readonly connection: Connection) {} async getUserWithTransaction(userId: number) { const queryRunner = this.connection.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { const user = await queryRunner.query('SELECT * FROM users WHERE id = ?', [userId]); // 执行其他数据库操作... await queryRunner.commitTransaction(); return user; } catch (err) { await queryRunner.rollbackTransaction(); throw err; } finally { await queryRunner.release(); } } }
方法2:直接使用mysql2包连接(完全脱离ORM)
如果你想彻底不依赖ORM,可以直接用Node.js生态中常用的MySQL驱动mysql2:
步骤1:安装依赖
npm install mysql2
步骤2:创建数据库连接服务
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; import mysql from 'mysql2/promise'; @Injectable() export class DatabaseService implements OnModuleInit, OnModuleDestroy { private connection: mysql.Connection; async onModuleInit() { this.connection = await mysql.createConnection({ host: 'localhost', user: 'your_db_username', password: 'your_db_password', database: 'your_db_name', }); } async onModuleDestroy() { await this.connection.end(); } // 封装通用查询方法 async query(sql: string, params?: any[]) { const [rows] = await this.connection.execute(sql, params); return rows; } }
步骤3:在业务服务中调用
import { Injectable } from '@nestjs/common'; import { DatabaseService } from './database.service'; @Injectable() export class UserService { constructor(private readonly dbService: DatabaseService) {} async getUsers() { const users = await this.dbService.query('SELECT * FROM users'); return users; } }
注意事项
- 无论哪种方式,务必使用参数绑定,绝对不要直接将用户输入拼接进SQL语句,避免SQL注入风险。
- 生产环境中,使用
mysql2时建议用连接池(mysql.createPool())代替单连接,提升性能和稳定性。
内容的提问来源于stack exchange,提问作者William Pineda MHA
相关产品推荐
相关产品推荐

