# TypeORM TypeScript: ORM for TypeScript Apps

# TypeORM: TypeScript ORM for Modern Applications

TypeORM is a powerful Object-Relational Mapping (ORM) library for TypeScript and JavaScript that simplifies database interactions in your applications. Here's a comprehensive guide:

## What is TypeORM?

TypeORM is an ORM that allows you to work with databases using TypeScript classes and decorators instead of writing raw SQL queries. It supports multiple databases including PostgreSQL, MySQL, SQLite, MongoDB, and more.

## Key Features

- **Decorator-based**: Uses TypeScript decorators for elegant entity definitions
- **Multiple Database Support**: Works with PostgreSQL, MySQL, MariaDB, SQLite, Oracle, SQL Server, and MongoDB
- **Query Builder**: Fluent API for building complex queries
- **Relations**: Supports one-to-one, one-to-many, and many-to-many relationships
- **Migrations**: Built-in migration system for schema management
- **Active Record & Data Mapper**: Two architectural patterns supported
- **Lazy Relations**: Load related data on demand
- **Transaction Support**: Handle complex multi-step operations safely

## Installation

```bash
npm install typeorm reflect-metadata
npm install --save-dev @types/node typescript
```

## Basic Setup

### 1. Configure TypeScript

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}
```

### 2. Create Data Source

```typescript
import "reflect-metadata";
import { DataSource } from "typeorm";
import { User } from "./entities/User";
import { Post } from "./entities/Post";

export const AppDataSource = new DataSource({
  type: "postgres",
  host: "localhost",
  port: 5432,
  username: "postgres",
  password: "password",
  database: "typeorm_db",
  synchronize: true,
  logging: false,
  entities: [User, Post],
  migrations: ["src/migrations/*.ts"],
  subscribers: ["src/subscribers/*.ts"],
});
```

## Defining Entities

### Simple Entity

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

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

  @Column()
  firstName: string;

  @Column()
  lastName: string;

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

  @Column({ default: true })
  isActive: boolean;

  @Column({ type: "timestamp", default: () => "CURRENT_TIMESTAMP" })
  createdAt: Date;
}
```

### Entity with Relations

```typescript
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  OneToMany,
  ManyToOne,
  JoinColumn,
} from "typeorm";

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

  @Column()
  name: string;

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

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

  @Column()
  title: string;

  @Column()
  content: string;

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

  @Column()
  authorId: number;
}
```

### Many-to-Many Relation

```typescript
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from "typeorm";

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

  @Column()
  name: string;

  @ManyToMany(() => Course)
  @JoinTable()
  courses: Course[];
}

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

  @Column()
  title: string;

  @ManyToMany(() => Student, (student) => student.courses)
  students: Student[];
}
```

## CRUD Operations

### Using Repository Pattern

```typescript
import { AppDataSource } from "./data-source";
import { User } from "./entities/User";

// Initialize connection
await AppDataSource.initialize();

const userRepository = AppDataSource.getRepository(User);

// Create
const user = userRepository.create({
  firstName: "John",
  lastName: "Doe",
  email: "john@example.com",
});
await userRepository.save(user);

// Read
const foundUser = await userRepository.findOne({
  where: { id: 1 },
});

// Update
user.firstName = "Jane";
await userRepository.save(user);

// Delete
await userRepository.remove(user);
```

## Query Builder

```typescript
// Complex queries with Query Builder
const users = await userRepository
  .createQueryBuilder("user")
  .leftJoinAndSelect("user.posts", "post")
  .where("user.isActive = :isActive", { isActive: true })
  .andWhere("post.createdAt > :date", { date: new Date("2024-01-01") })
  .orderBy("user.createdAt", "DESC")
  .take(10)
  .skip(0)
  .getMany();

// Aggregation
const count = await userRepository
  .createQueryBuilder("user")
  .select("COUNT(user.id)", "count")
  .getRawOne();
```

## Migrations

```bash
# Generate migration
npx typeorm migration:generate src/migrations/InitialMigration

# Run migrations
npx typeorm migration:run

# Revert migration
npx typeorm migration:revert
```

## Best Practices

1. **Use Repositories**: Always use repositories instead of raw queries
2. **Lazy Load Relations**: Use `lazy: true` for large datasets
3. **Validation**: Combine with class-validator for data validation
4. **Error Handling**: Wrap database operations in try-catch blocks
5. **Connection Pooling**: Configure appropriate pool sizes
6. **Indexes**: Add indexes to frequently queried columns
7. **Transactions**: Use transactions for data consistency

## Integration with Express

```typescript
import express from "express";
import { AppDataSource } from "./data-source";

const app = express();

AppDataSource.initialize()
  .then(() => {
    app.listen(3000, () => {
      console.log("Server running on port 3000");
    });
  })
  .catch((error) => console.log(error));

app.get("/users", async (req, res) => {
  const userRepository = AppDataSource.getRepository(User);
  const users = await userRepository.find();
  res.json(users);
});
```

## Conclusion

TypeORM provides a robust, type-safe way to interact with databases in TypeScript applications. Its decorator-based approach, powerful query builder, and support for multiple databases make it an excellent choice for modern backend development.
