TypeORM入门教程,三小时搞定数据库操作的保姆级指南

2025-07-19 0

上周帮同事调试一个NestJS项目,他盯着报错信息哀嚎:“TypeORM连不上数据库,文档全是英文术语!” 这场景太熟悉了——三年前我第一次用TypeORM时,光搞懂DataSourceEntity的关系就花了整晚。今天分享的​​极简入门法​​,专治“文档劝退症”!


一、为什么选TypeORM?新手绕不开的三大优势

  1. ​零配置玩转多数据库​​:

    TypeORM入门教程,三小时搞定数据库操作的保姆级指南它支持MySQL、PostgreSQL甚至MongoDB,切换时只需改DataSourcetype参数。我上个月把本地测试库从MySQL换成SQLite,代码一行没改——这对频繁切换环境的开发者太友好了。

  2. ​用TS类型代替SQL语句​​:

    比如定义用户表字段时直接写@Column({ type: "varchar", length: 200 }) name: string,TypeORM会自动生成建表语句。再也不用背VARCHAR(255)这种细节了!

  3. ​关联查询像套娃一样简单​​:

    举个例子:查用户订单时,只要在User实体里加@OneToMany(() => Order, order => order.user) orders: Order[],调用userRepository.find({ relations: ['orders'] })就能连带查出所有订单。比手写JOIN省心十倍。

​但别急着欢呼​​!TypeORM有两个坑新人必踩:

  • ​同步模式千万别上线​​:synchronize: true在开发时自动同步表结构很方便,但生产环境可能误删字段。去年我团队就因这个配置丢了客户数据,血泪教训啊!

  • ​Repository的save方法有陷阱​​:

    它默认返回完整实体对象,但如果插入时某字段为null,数据库默认值会失效!更稳的做法是用insert+手动赋值。


二、手把手搭建第一个项目(附避坑代码)

​Step 1:初始化项目​

bash复制
npm install typeorm @nestjs/typeorm mysql2 # 用MySQL示例  
npx typeorm init --name my-project --database mysql

​关键配置​​:打开data-source.ts,把synchronize改成false!然后手动创建src/entity/User.ts实体文件。

​Step 2:实体定义防坑指南​

typescript复制
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";  

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

  @Column({ default: "匿名用户" }) // 必须显式声明默认值!  
  name: string;  

  // 时间字段强烈推荐用这个  
  @CreateDateColumn({ precision: 3 }) // 精确到毫秒  
  createdAt: Date;  
}

​易错点​​:若漏写@Column装饰器,该字段会被忽略。我建议安装ESLint插件eslint-plugin-typeorm自动检查。

​Step 3:实战查询技巧​

typescript复制
// 避免用findOne!它可能返回undefined  
const user = await userRepository.findOneBy({ id: 1 });  

// 分页查询正确姿势  
const [users, total] = await userRepository.findAndCount({  
  skip: (page - 1) * 10,  
  take: 10,  
  order: { createdAt: "DESC" }  
});  

// 关联查询记得加relations  
const userWithOrders = await userRepository.findOne({  
  where: { id: 1 },  
  relations: ["orders"]  
});

三、高频报错自救方案(亲测有效)

​坑①:Cannot find module 'entity/User'

👉 在data-source.tsentities数组里改用[__dirname + "/entity/*.js"](编译后是js文件!)

​坑②:关联查询结果为空​

👉 检查实体类关系装饰器的eager参数。如果设为true,关联数据会自动加载,否则需要手动relations

​坑③:QueryFailedError: Duplicate entry

👉 用upsert替代save!它支持唯一约束冲突时自动更新:

typescript复制
await userRepository.upsert(  
  { name: "李雷", email: "lilei@test.com" },  
  ["email"] // 以email为唯一键  
);

TypeORM像一把瑞士军刀——功能多但需要熟悉卡扣位置。如果你卡在某个报错超过半小时,直接去GitHub的​​Discussion板块​​搜错误码(别翻Issue!),那里有大量民间高手总结的野路子解法。

(小贴士:实体字段改名时,先用@Column({ name: "old_name" })兼容旧数据,再逐步迁移)

相关文章

如何成为旅行博主?又该如何靠旅行赚钱?
如何通过 Medium 赚钱?有哪些有效的 Medium 变现方法?
新手必看:比特币减半周期操作指南,抓住下一波牛市!
NFL球员收入几何?他们究竟能赚多少钱?
Airbnb 真的取消分期付款功能了吗?Keepbit Platform 怎么了?
日内交易真的能赚钱吗?或者说,日内交易到底能不能赚到钱?