Basic Entity Definition
import {
Entity, PrimaryGeneratedColumn, Column,
CreateDateColumn, UpdateDateColumn, Index
} from "typeorm";
@Entity("users")
@Index(["email"])
@Index(["lastName", "firstName"])
export class User {
@PrimaryGeneratedColumn()
id: number;
@PrimaryGeneratedColumn("uuid")
uuid: string;
@Column({ unique: true, length: 255 })
email: string;
@Column({ name: "first_name", length: 100 })
firstName: string;
@Column({ nullable: true })
lastName?: string;
@Column({ type: "enum", enum: ["admin","user","guest"], default: "user" })
role: string;
@Column({ type: "decimal", precision: 10, scale: 2, default: 0 })
balance: number;
@Column({ type: "jsonb", nullable: true })
metadata: Record<string, unknown> | null;
@Column({ default: true })
isActive: boolean;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
}
Relations
import { OneToMany, ManyToOne, ManyToMany, JoinTable, JoinColumn } from "typeorm";
// One-to-Many / Many-to-One
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@ManyToOne(() => User, user => user.posts, { onDelete: "CASCADE" })
@JoinColumn({ name: "author_id" })
author: User;
@Column()
authorId: number;
}
@Entity()
export class User {
@OneToMany(() => Post, post => post.author)
posts: Post[];
}
// Many-to-Many with join table
@Entity()
export class Article {
@ManyToMany(() => Tag, tag => tag.articles)
@JoinTable({
name: "article_tags",
joinColumn: { name: "article_id" },
inverseJoinColumn: { name: "tag_id" }
})
tags: Tag[];
}
@Entity()
export class Tag {
@ManyToMany(() => Article, article => article.tags)
articles: Article[];
}
// One-to-One
@Entity()
export class Profile {
@OneToOne(() => User, { onDelete: "CASCADE" })
@JoinColumn()
user: User;
}
Repository & QueryBuilder
import { AppDataSource } from "./data-source";
const userRepo = AppDataSource.getRepository(User);
// Basic CRUD
const user = await userRepo.findOne({ where: { email: "[email protected]" } });
const users = await userRepo.find({
where: { isActive: true },
relations: ["posts"],
order: { createdAt: "DESC" },
take: 20, skip: 0
});
await userRepo.save({ email: "[email protected]", role: "user" });
await userRepo.update({ id: 1 }, { isActive: false });
await userRepo.delete({ id: 1 });
// QueryBuilder for complex queries
const result = await userRepo.createQueryBuilder("u")
.leftJoinAndSelect("u.posts", "p", "p.published = :pub", { pub: true })
.where("u.role = :role", { role: "admin" })
.andWhere("u.createdAt > :date", { date: new Date("2024-01-01") })
.orderBy("u.createdAt", "DESC")
.take(10)
.getMany();
Listeners & Subscribers
import { BeforeInsert, BeforeUpdate, AfterLoad } from "typeorm";
import * as bcrypt from "bcrypt";
@Entity()
export class User {
@Column({ select: false })
password: string;
@BeforeInsert()
@BeforeUpdate()
async hashPassword() {
if (this.password) {
this.password = await bcrypt.hash(this.password, 12);
}
}
@AfterLoad()
setFullName() {
this.fullName = `${this.firstName} ${this.lastName}`;
}
}