556 changes: 554 additions & 2 deletions CHANGELOG.md

Large diffs are not rendered by default.

15 changes: 2 additions & 13 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
version: "3"
services:
# mysql-5.5
#mysql5.5:
# image: "mysql:5.5"
# container_name: "typeorm-mysql-5.5"
# ports:
# - "3306:3306"
# environment:
# MYSQL_ROOT_PASSWORD: "admin"
# MYSQL_USER: "test"
# MYSQL_PASSWORD: "test"
# MYSQL_DATABASE: "test"

# mysql
mysql:
image: "mysql:5.7.24"
image: "mysql:5.7.37"
container_name: "typeorm-mysql"
ports:
- "3306:3306"
Expand Down Expand Up @@ -120,7 +109,7 @@ services:

# mongodb
mongodb:
image: "mongo:3.4.18"
image: "mongo:5.0.6"
container_name: "typeorm-mongodb"
ports:
- "27017:27017"
Expand Down
123 changes: 47 additions & 76 deletions docs/active-record-data-mapper.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Active Record vs Data Mapper

* [What is the Active Record pattern?](#what-is-the-active-record-pattern)
* [What is the Data Mapper pattern?](#what-is-the-data-mapper-pattern)
* [Which one should I choose?](#which-one-should-i-choose)
- [What is the Active Record pattern?](#what-is-the-active-record-pattern)
- [What is the Data Mapper pattern?](#what-is-the-data-mapper-pattern)
- [Which one should I choose?](#which-one-should-i-choose)

## What is the Active Record pattern?

Expand All @@ -16,23 +16,21 @@ You can read more about the Active Record pattern on [Wikipedia](https://en.wiki
Example:

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

@Entity()
export class User extends BaseEntity {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
firstName: string;
firstName: string

@Column()
lastName: string;
lastName: string

@Column()
isActive: boolean;

isActive: boolean
}
```

Expand All @@ -41,59 +39,57 @@ Example of how to work with such entity:

```typescript
// example how to save AR entity
const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.isActive = true;
await user.save();
const user = new User()
user.firstName = "Timber"
user.lastName = "Saw"
user.isActive = true
await user.save()

// example how to remove AR entity
await user.remove();
await user.remove()

// example how to load AR entities
const users = await User.find({ skip: 2, take: 5 });
const newUsers = await User.find({ isActive: true });
const timber = await User.findOne({ firstName: "Timber", lastName: "Saw" });
const users = await User.find({ skip: 2, take: 5 })
const newUsers = await User.findBy({ isActive: true })
const timber = await User.findOneBy({ firstName: "Timber", lastName: "Saw" })
```

`BaseEntity` has most of the methods of the standard `Repository`.
`BaseEntity` has most of the methods of the standard `Repository`.
Most of the time you don't need to use `Repository` or `EntityManager` with active record entities.

Now let's say we want to create a function that returns users by first and last name.
We can create such functions as a static method in a `User` class:

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

@Entity()
export class User extends BaseEntity {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
firstName: string;
firstName: string

@Column()
lastName: string;
lastName: string

@Column()
isActive: boolean;
isActive: boolean

static findByName(firstName: string, lastName: string) {
return this.createQueryBuilder("user")
.where("user.firstName = :firstName", { firstName })
.andWhere("user.lastName = :lastName", { lastName })
.getMany();
.getMany()
}

}
```

And use it just like other methods:

```typescript
const timber = await User.findByName("Timber", "Saw");
const timber = await User.findByName("Timber", "Saw")
```

## What is the Data Mapper pattern?
Expand All @@ -110,81 +106,56 @@ You can read more about data mapper on [Wikipedia](https://en.wikipedia.org/wiki
Example:

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

@Entity()
export class User {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
firstName: string;
firstName: string

@Column()
lastName: string;
lastName: string

@Column()
isActive: boolean;

isActive: boolean
}
```

Example of how to work with such entity:

```typescript
const userRepository = connection.getRepository(User);
const userRepository = dataSource.getRepository(User)

// example how to save DM entity
const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.isActive = true;
await userRepository.save(user);
const user = new User()
user.firstName = "Timber"
user.lastName = "Saw"
user.isActive = true
await userRepository.save(user)

// example how to remove DM entity
await userRepository.remove(user);
await userRepository.remove(user)

// example how to load DM entities
const users = await userRepository.find({ skip: 2, take: 5 });
const newUsers = await userRepository.find({ isActive: true });
const timber = await userRepository.findOne({ firstName: "Timber", lastName: "Saw" });
```

Now let's say we want to create a function that returns users by first and last name.
We can create such a function in a "custom repository".

```typescript
import {EntityRepository, Repository} from "typeorm";
import {User} from "../entity/User";

@EntityRepository()
export class UserRepository extends Repository<User> {

findByName(firstName: string, lastName: string) {
return this.createQueryBuilder("user")
.where("user.firstName = :firstName", { firstName })
.andWhere("user.lastName = :lastName", { lastName })
.getMany();
}

}
```

And use it this way:

```typescript
const userRepository = connection.getCustomRepository(UserRepository);
const timber = await userRepository.findByName("Timber", "Saw");
const users = await userRepository.find({ skip: 2, take: 5 })
const newUsers = await userRepository.findBy({ isActive: true })
const timber = await userRepository.findOneBy({
firstName: "Timber",
lastName: "Saw",
})
```

Learn more about [custom repositories](custom-repository.md).
In order to extend standard repository with custom methods, use [custom repository pattern](custom-repository.md).

## Which one should I choose?

The decision is up to you.
Both strategies have their own cons and pros.

One thing we should always keep in mind with software development is how we are going to maintain our applications.
The `Data Mapper` approach helps with maintainability, which is more effective in bigger apps.
The `Data Mapper` approach helps with maintainability, which is more effective in larger apps.
The `Active Record` approach helps keep things simple which works well in smaller apps.
And simplicity is always a key to better maintainability.
And simplicity is always a key to better maintainability.
69 changes: 32 additions & 37 deletions docs/caching.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Caching queries

You can cache results selected by these `QueryBuilder` methods: `getMany`, `getOne`, `getRawMany`, `getRawOne` and `getCount`.
You can cache results selected by these `QueryBuilder` methods: `getMany`, `getOne`, `getRawMany`, `getRawOne` and `getCount`.

You can also cache results selected by these `Repository` methods: `find`, `findAndCount`, `findByIds`, and `count`.
You can also cache results selected by `find*` and `count*` methods of the `Repository` and `EntityManager`.

To enable caching you need to explicitly enable it in your connection options:
To enable caching you need to explicitly enable it in data source options:

```typescript
{
Expand All @@ -17,26 +17,25 @@ To enable caching you need to explicitly enable it in your connection options:
```

When you enable cache for the first time,
you must synchronize your database schema (using CLI, migrations or the `synchronize` connection option).
you must synchronize your database schema (using CLI, migrations or the `synchronize` data source option).

Then in `QueryBuilder` you can enable query cache for any query:

```typescript
const users = await connection
const users = await dataSource
.createQueryBuilder(User, "user")
.where("user.isAdmin = :isAdmin", { isAdmin: true })
.cache(true)
.getMany();
.getMany()
```

Equivalent `Repository` query:

```typescript
const users = await connection
.getRepository(User)
.find({
where: { isAdmin: true },
cache: true
});
const users = await dataSource.getRepository(User).find({
where: { isAdmin: true },
cache: true,
})
```

This will execute a query to fetch all admin users and cache the results.
Expand All @@ -49,25 +48,23 @@ Any users inserted during the 1 second cache window won't be returned to the use
You can change cache time manually via `QueryBuilder`:

```typescript
const users = await connection
const users = await dataSource
.createQueryBuilder(User, "user")
.where("user.isAdmin = :isAdmin", { isAdmin: true })
.cache(60000) // 1 minute
.getMany();
.getMany()
```

Or via `Repository`:

```typescript
const users = await connection
.getRepository(User)
.find({
where: { isAdmin: true },
cache: 60000
});
const users = await dataSource.getRepository(User).find({
where: { isAdmin: true },
cache: 60000,
})
```

Or globally in connection options:
Or globally in data source options:

```typescript
{
Expand All @@ -84,34 +81,32 @@ Or globally in connection options:
Also, you can set a "cache id" via `QueryBuilder`:

```typescript
const users = await connection
const users = await dataSource
.createQueryBuilder(User, "user")
.where("user.isAdmin = :isAdmin", { isAdmin: true })
.cache("users_admins", 25000)
.getMany();
.getMany()
```

Or with `Repository`:

```typescript
const users = await connection
.getRepository(User)
.find({
where: { isAdmin: true },
cache: {
id: "users_admins",
milliseconds: 25000
}
});
const users = await dataSource.getRepository(User).find({
where: { isAdmin: true },
cache: {
id: "users_admins",
milliseconds: 25000,
},
})
```

This gives you granular control of your cache,
for example, clearing cached results when you insert a new user:

```typescript
await connection.queryResultCache.remove(["users_admins"]);
await dataSource.queryResultCache.remove(["users_admins"])
```


By default, TypeORM uses a separate table called `query-result-cache` and stores all queries and results there.
Table name is configurable, so you could change it by specifying a different value in the tableName property.
Example:
Expand Down Expand Up @@ -217,7 +212,7 @@ If none of the built-in cache providers satisfy your demands, then you can also

```typescript
class CustomQueryResultCache implements QueryResultCache {
constructor(private connection: Connection) {}
constructor(private dataSource: DataSource) {}
...
}
```
Expand All @@ -226,8 +221,8 @@ class CustomQueryResultCache implements QueryResultCache {
{
...
cache: {
provider(connection) {
return new CustomQueryResultCache(connection);
provider(dataSource) {
return new CustomQueryResultCache(dataSource);
}
}
}
Expand Down
342 changes: 0 additions & 342 deletions docs/connection-api.md

This file was deleted.

554 changes: 0 additions & 554 deletions docs/connection-options.md

This file was deleted.

207 changes: 0 additions & 207 deletions docs/connection.md

This file was deleted.

176 changes: 41 additions & 135 deletions docs/custom-repository.md
Original file line number Diff line number Diff line change
@@ -1,165 +1,71 @@
# Custom repositories

You can create a custom repository which should contain methods to work with your database.
Usually custom repositories are created for a single entity and contains its specific queries.
For example, let's say we want to have a method called `findByName(firstName: string, lastName: string)`
which will search for users by a given first and last names.
The best place for this method is in `Repository`,
which will search for users by a given first and last names.
The best place for this method is a `Repository`,
so we could call it like `userRepository.findByName(...)`.
You can achieve this using custom repositories.

There are several ways how custom repositories can be created.

* [Custom repository extends standard Repository](#custom-repository-extends-standard-repository)
* [Custom repository extends standard AbstractRepository](#custom-repository-extends-standard-abstractrepository)
* [Custom repository without extends](#custom-repository-without-extends)
* [Using custom repositories in transactions](#using-custom-repositories-in-transactions-or-why-custom-repositories-cannot-be-services)
- [How to create custom repository](#how-to-create-custom-repository)
- [Using custom repositories in transactions](#using-custom-repositories-in-transactions)

## Custom repository extends standard Repository
## How to create custom repository

The first way to create a custom repository is to extend `Repository`.
Example:
It's common practice assigning a repository instance to a globally exported variable,
and use this variable across your app, for example:

```typescript
import {EntityRepository, Repository} from "typeorm";
import {User} from "../entity/User";

@EntityRepository(User)
export class UserRepository extends Repository<User> {
```ts
// user.repository.ts
export const UserRepository = dataSource.getRepository(User)

findByName(firstName: string, lastName: string) {
return this.findOne({ firstName, lastName });
// user.controller.ts
export class UserController {
users() {
return UserRepository.find()
}

}
```

Then you can use it this way:

```typescript
import {getCustomRepository} from "typeorm";
import {UserRepository} from "./repository/UserRepository";

const userRepository = getCustomRepository(UserRepository); // or connection.getCustomRepository or manager.getCustomRepository()
const user = userRepository.create(); // same as const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
await userRepository.save(user);

const timber = await userRepository.findByName("Timber", "Saw");
```

As you can see you can "get" the repository using `getCustomRepository`
and you can access any method created inside it and any method in the standard entity repository.

## Custom repository extends standard AbstractRepository

The second way to create a custom repository is to extend `AbstractRepository`:
In order to extend `UserRepository` functionality you can use `.extend` method of `Repository` class:

```typescript
import {EntityRepository, AbstractRepository} from "typeorm";
import {User} from "../entity/User";

@EntityRepository(User)
export class UserRepository extends AbstractRepository<User> {

createAndSave(firstName: string, lastName: string) {
const user = new User();
user.firstName = firstName;
user.lastName = lastName;
return this.manager.save(user);
}

// user.repository.ts
export const UserRepository = dataSource.getRepository(User).extend({
findByName(firstName: string, lastName: string) {
return this.repository.findOne({ firstName, lastName });
return this.createQueryBuilder("user")
.where("user.firstName = :firstName", { firstName })
.andWhere("user.lastName = :lastName", { lastName })
.getMany()
},
})

// user.controller.ts
export class UserController {
users() {
return UserRepository.findByName("Timber", "Saw")
}

}
```

Then you can use it this way:

```typescript
import {getCustomRepository} from "typeorm";
import {UserRepository} from "./repository/UserRepository";

const userRepository = getCustomRepository(UserRepository); // or connection.getCustomRepository or manager.getCustomRepository()
await userRepository.createAndSave("Timber", "Saw");
const timber = await userRepository.findByName("Timber", "Saw");
```

The difference between this type of repository and the previous one is that it does not expose all the methods `Repository` has.
`AbstractRepository` does not have any public methods,
it only has protected methods, like `manager` and `repository`, which you can use in your own
public methods.
Extending `AbstractRepository` is useful if you don't want to expose all methods the standard `Repository` has to the public.

## Custom repository without extends
## Using custom repositories in transactions

The third way to create a repository is to not extend anything,
but define a constructor which always accepts an entity manager instance:
Transactions have their own scope of execution: they have their own query runner, entity manager and repository instances.
That's why using global (data source's) entity manager and repositories won't work in transactions.
In order to execute queries properly in scope of transaction you **must** use provided entity manager
and it's `getRepository` method. In order to use custom repositories within transaction,
you must use `withRepository` method of the provided entity manager instance:

```typescript
import {EntityRepository, Repository, EntityManager} from "typeorm";
import {User} from "../entity/User";

@EntityRepository()
export class UserRepository {

constructor(private manager: EntityManager) {
}

createAndSave(firstName: string, lastName: string) {
const user = new User();
user.firstName = firstName;
user.lastName = lastName;
return this.manager.save(user);
}

findByName(firstName: string, lastName: string) {
return this.manager.findOne(User, { firstName, lastName });
}

}
```

Then you can use it this way:

```typescript
import {getCustomRepository} from "typeorm";
import {UserRepository} from "./repository/UserRepository";

const userRepository = getCustomRepository(UserRepository); // or connection.getCustomRepository or manager.getCustomRepository()
await userRepository.createAndSave("Timber", "Saw");
const timber = await userRepository.findByName("Timber", "Saw");
```

This type of repository does not extend anything - you only need to define a constructor
which must accept `EntityManager`. Then you can use it everywhere in your repository methods.
Also, this type of repository is not bound to a specific entity,
thus, you can operate with multiple entities inside them.

## Using custom repositories in transactions or why custom repositories cannot be services

Custom repositories cannot be services,
because there isn't a single instance of a custom repository (just like regular repositories or entity manager) in the app.
Besides the fact that there can be multiple connections in your app (where entity manager and repositories are different)
repositories and managers are different in transactions as well.
For example:

```typescript
await connection.transaction(async manager => {
await connection.transaction(async (manager) => {
// in transactions you MUST use manager instance provided by a transaction,
// you cannot use global managers, repositories or custom repositories
// you cannot use global entity managers or repositories,
// because this manager is exclusive and transactional
// and if let's say we would do custom repository as a service
// it has a "manager" property which should be unique instance of EntityManager
// but there is no global EntityManager instance and cannot be
// thats why custom managers are specific to each EntityManager and cannot be services.
// this also opens opportunity to use custom repositories in transactions without any issues:

const userRepository = manager.getCustomRepository(UserRepository); // DONT USE GLOBAL getCustomRepository here!
await userRepository.createAndSave("Timber", "Saw");
const timber = await userRepository.findByName("Timber", "Saw");
});

const userRepository = manager.withRepository(UserRepository)
await userRepository.createAndSave("Timber", "Saw")
const timber = await userRepository.findByName("Timber", "Saw")
})
```
172 changes: 172 additions & 0 deletions docs/data-source-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# DataSource API

- `options` - Options used to create this dataSource.
Learn more about [DataSourceOptions](data-source-options.md).

```typescript
const dataSourceOptions: DataSourceOptions = dataSource.options
```

- `isInitialized` - Indicates if DataSource was initialized and initial connection / connection pool with database was established or not.

```typescript
const isInitialized: boolean = dataSource.isInitialized
```

- `driver` - Underlying database driver used in this dataSource.

```typescript
const driver: Driver = dataSource.driver
```

- `manager` - `EntityManager` used to work with entities.
Learn more about [Entity Manager and Repository](working-with-entity-manager.md).

```typescript
const manager: EntityManager = dataSource.manager
// you can call manager methods, for example find:
const users = await manager.find()
```

- `mongoManager` - `MongoEntityManager` used to work with entities for mongodb data source.
For more information about MongoEntityManager see [MongoDB](mongodb.md) documentation.

```typescript
const manager: MongoEntityManager = dataSource.mongoManager
// you can call manager or mongodb-manager specific methods, for example find:
const users = await manager.find()
```

- `initialize` - Initializes data source and opens connection pool to the database.

```typescript
await dataSource.initialize()
```

- `destroy` - Destroys the DataSource and closes all database connections.
Usually, you call this method when your application is shutting down.

```typescript
await dataSource.destroy()
```

- `synchronize` - Synchronizes database schema. When `synchronize: true` is set in data source options it calls this method.
Usually, you call this method when your application is starting.

```typescript
await dataSource.synchronize()
```

- `dropDatabase` - Drops the database and all its data.
Be careful with this method on production since this method will erase all your database tables and their data.
Can be used only after connection to the database is established.

```typescript
await dataSource.dropDatabase()
```

- `runMigrations` - Runs all pending migrations.

```typescript
await dataSource.runMigrations()
```

- `undoLastMigration` - Reverts last executed migration.

```typescript
await dataSource.undoLastMigration()
```

- `hasMetadata` - Checks if metadata for a given entity is registered.
Learn more about [Entity Metadata](entity-metadata.md).

```typescript
if (dataSource.hasMetadata(User))
const userMetadata = dataSource.getMetadata(User)
```

- `getMetadata` - Gets `EntityMetadata` of the given entity.
You can also specify a table name and if entity metadata with such table name is found it will be returned.
Learn more about [Entity Metadata](entity-metadata.md).

```typescript
const userMetadata = dataSource.getMetadata(User)
// now you can get any information about User entity
```

- `getRepository` - Gets `Repository` of the given entity.
You can also specify a table name and if repository for given table is found it will be returned.
Learn more about [Repositories](working-with-repository.md).

```typescript
const repository = dataSource.getRepository(User)
// now you can call repository methods, for example find:
const users = await repository.find()
```

- `getTreeRepository` - Gets `TreeRepository` of the given entity.
You can also specify a table name and if repository for given table is found it will be returned.
Learn more about [Repositories](working-with-repository.md).

```typescript
const repository = dataSource.getTreeRepository(Category)
// now you can call tree repository methods, for example findTrees:
const categories = await repository.findTrees()
```

- `getMongoRepository` - Gets `MongoRepository` of the given entity.
This repository is used for entities in MongoDB dataSource.
Learn more about [MongoDB support](mongodb.md).

```typescript
const repository = dataSource.getMongoRepository(User)
// now you can call mongodb-specific repository methods, for example createEntityCursor:
const categoryCursor = repository.createEntityCursor()
const category1 = await categoryCursor.next()
const category2 = await categoryCursor.next()
```

- `transaction` - Provides a single transaction where multiple database requests will be executed in a single database transaction.
Learn more about [Transactions](transactions.md).

```typescript
await dataSource.transaction(async (manager) => {
// NOTE: you must perform all database operations using given manager instance
// its a special instance of EntityManager working with this transaction
// and don't forget to await things here
})
```

- `query` - Executes a raw SQL query.

```typescript
const rawData = await dataSource.query(`SELECT * FROM USERS`)
```

- `createQueryBuilder` - Creates a query builder, which can be used to build queries.
Learn more about [QueryBuilder](select-query-builder.md).

```typescript
const users = await dataSource
.createQueryBuilder()
.select()
.from(User, "user")
.where("user.name = :name", { name: "John" })
.getMany()
```

- `createQueryRunner` - Creates a query runner used to manage and work with a single real database dataSource.
Learn more about [QueryRunner](query-runner.md).

```typescript
const queryRunner = dataSource.createQueryRunner()

// you can use its methods only after you call connect
// which performs real database connection
await queryRunner.connect()

// .. now you can work with query runner and call its methods

// very important - don't forget to release query runner once you finished working with it
await queryRunner.release()
```
554 changes: 554 additions & 0 deletions docs/data-source-options.md

Large diffs are not rendered by default.

102 changes: 102 additions & 0 deletions docs/data-source.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Working with DataSource

- [What is `DataSource`](#what-is-datasource)
- [Creating a new DataSource](#creating-a-new-datasource)
- [Working with DataSource](#working-with-datasource)

## What is `DataSource`

Your interaction with the database is only possible once you setup a `DataSource`.
TypeORM's `DataSource` holds your database connection settings and
establishes initial database connection or connection pool depend on RDBMS you use.

In order to establish initial connection / connection pool you must call `initialize` method of your `DataSource` instance.

Disconnection (closing all connections in the pool) is made when `destroy` method is called.

Generally, you call `initialize` method of the `DataSource` instance on application bootstrap,
and `destroy` it after you completely finished working with the database.
In practice, if you are building a backend for your site and your backend server always stays running -
you never `destroy` a DataSource.

## Creating a new DataSource

To create a new `DataSource` instance you must initialize its constructor by calling `new DataSource`
and assigning to a global variable that you'll use across your application:

```typescript
import { DataSource } from "typeorm"

const AppDataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
})

AppDataSource.initialize()
.then(() => {
console.log("Data Source has been initialized!")
})
.catch((err) => {
console.error("Error during Data Source initialization", err)
})
```

It's a good idea to make `AppDataSource` globally available by `export`-ing it, since you'll
use this instance across your application.

`DataSource` accepts `DataSourceOptions` and those options vary depend on database `type` you use.
For different database types there are different options you can specify.

You can define as many data sources as you need in your application, for example:

```typescript
import { DataSource } from "typeorm"

const MysqlDataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
entities: [
// ....
],
})

const PostgresDataSource = new DataSource({
type: "postgres",
host: "localhost",
port: 5432,
username: "test",
password: "test",
database: "test",
entities: [
// ....
],
})
```

## Working with DataSource

Once you set your `DataSource`, you can use it anywhere in your app, for example:

```typescript
import { AppDataSource } from "./app-data-source"
import { User } from "../entity/User"

export class UserController {
@Get("/users")
getAll() {
return AppDataSource.manager.find(User)
}
}
```

Using `DataSource` instance you can execute database operations with your entities,
particularly using `.manager` and `.getRepository()` properties.
For more information about them see [Entity Manager and Repository](working-with-entity-manager.md) documentation.
526 changes: 210 additions & 316 deletions docs/decorator-reference.md

Large diffs are not rendered by default.

40 changes: 8 additions & 32 deletions docs/delete-query-builder.md
Original file line number Diff line number Diff line change
@@ -1,62 +1,38 @@
# Delete using Query Builder

* [Delete using Query Builder](#delete-using-query-builder)
* [`Delete`](#delete)
* [`Soft-Delete`](#soft-delete)
* [`Restore-Soft-Delete`](#restore-soft-delete)
- [Delete using Query Builder](#delete-using-query-builder)
- [`Delete`](#delete)
- [`Soft-Delete`](#soft-delete)
- [`Restore-Soft-Delete`](#restore-soft-delete)

### `Delete`

You can create `DELETE` queries using `QueryBuilder`.
Examples:

```typescript
import {getConnection} from "typeorm";

await getConnection()
await myDataSource
.createQueryBuilder()
.delete()
.from(User)
.where("id = :id", { id: 1 })
.execute();
.execute()
```

This is the most efficient way in terms of performance to delete entities from your database.

---

### `Soft-Delete`

Applying Soft Delete to QueryBuilder

```typescript
import {createConnection} from "typeorm";
import {Entity} from "./entity";

createConnection(/*...*/).then(async connection => {

await connection
.getRepository(Entity)
.createQueryBuilder()
.softDelete()

}).catch(error => console.log(error));
await dataSource.getRepository(Entity).createQueryBuilder().softDelete()
```

### `Restore-Soft-Delete`

Alternatively, You can recover the soft deleted rows by using the `restore()` method:

```typescript
import {createConnection} from "typeorm";
import {Entity} from "./entity";

createConnection(/*...*/).then(async connection => {

await connection
.getRepository(Entity)
.createQueryBuilder()
.restore()

}).catch(error => console.log(error));
await dataSource.getRepository(Entity).createQueryBuilder().restore()
```
124 changes: 64 additions & 60 deletions docs/eager-and-lazy-relations.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,59 @@ Eager relations are loaded automatically each time you load entities from the da
For example:

```typescript
import {Entity, PrimaryGeneratedColumn, Column, ManyToMany} from "typeorm";
import {Question} from "./Question";
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany } from "typeorm"
import { Question } from "./Question"

@Entity()
export class Category {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
name: string;

@ManyToMany(type => Question, question => question.categories)
questions: Question[];

name: string

@ManyToMany((type) => Question, (question) => question.categories)
questions: Question[]
}
```

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

@Entity()
export class Question {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
title: string;
title: string

@Column()
text: string;
@ManyToMany(type => Category, category => category.questions, {
eager: true
text: string

@ManyToMany((type) => Category, (category) => category.questions, {
eager: true,
})
@JoinTable()
categories: Category[];

categories: Category[]
}
```

Now when you load questions you don't need to join or specify relations you want to load.
They will be loaded automatically:

```typescript
const questionRepository = connection.getRepository(Question);
const questionRepository = dataSource.getRepository(Question)

// questions will be loaded with its categories
const questions = await questionRepository.find();
const questions = await questionRepository.find()
```

Eager relations only work when you use `find*` methods.
Expand All @@ -66,78 +68,80 @@ using `eager: true` on both sides of relationship is disallowed.

## Lazy relations

Entities in lazy relations are loaded once you access them.
Entities in lazy relations are loaded once you access them.
Such relations must have `Promise` as type - you store your value in a promise,
and when you load them a promise is returned as well. Example:

```typescript
import {Entity, PrimaryGeneratedColumn, Column, ManyToMany} from "typeorm";
import {Question} from "./Question";
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany } from "typeorm"
import { Question } from "./Question"

@Entity()
export class Category {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
name: string;

@ManyToMany(type => Question, question => question.categories)
questions: Promise<Question[]>;

name: string

@ManyToMany((type) => Question, (question) => question.categories)
questions: Promise<Question[]>
}
```

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

@Entity()
export class Question {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
title: string;
title: string

@Column()
text: string;
@ManyToMany(type => Category, category => category.questions)
text: string

@ManyToMany((type) => Category, (category) => category.questions)
@JoinTable()
categories: Promise<Category[]>;

categories: Promise<Category[]>
}
```

`categories` is a Promise. It means it is lazy and it can store only a promise with a value inside.
Example how to save such relation:

```typescript
const category1 = new Category();
category1.name = "animals";
await connection.manager.save(category1);
const category1 = new Category()
category1.name = "animals"
await dataSource.manager.save(category1)

const category2 = new Category();
category2.name = "zoo";
await connection.manager.save(category2);
const category2 = new Category()
category2.name = "zoo"
await dataSource.manager.save(category2)

const question = new Question();
question.categories = Promise.resolve([category1, category2]);
await connection.manager.save(question);
const question = new Question()
question.categories = Promise.resolve([category1, category2])
await dataSource.manager.save(question)
```

Example how to load objects inside lazy relations:

```typescript
const question = await connection.getRepository(Question).findOne(1);
const categories = await question.categories;
const [question] = await dataSource.getRepository(Question).find()
const categories = await question.categories
// you'll have all question's categories inside "categories" variable now
```

Note: if you came from other languages (Java, PHP, etc.) and are used to use lazy relations everywhere - be careful.
Those languages aren't asynchronous and lazy loading is achieved different way, that's why you don't work with promises there.
In JavaScript and Node.JS you have to use promises if you want to have lazy-loaded relations.
This is non-standard technique and considered experimental in TypeORM.
This is non-standard technique and considered experimental in TypeORM.
119 changes: 52 additions & 67 deletions docs/embedded-entities.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,140 +8,126 @@ Let's say we have `User`, `Employee` and `Student` entities.
All those entities have few things in common - `first name` and `last name` properties

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

@Entity()
export class User {

@PrimaryGeneratedColumn()
id: string;
id: string

@Column()
firstName: string;
firstName: string

@Column()
lastName: string;
lastName: string

@Column()
isActive: boolean;

isActive: boolean
}
```

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

@Entity()
export class Employee {

@PrimaryGeneratedColumn()
id: string;
id: string

@Column()
firstName: string;
firstName: string

@Column()
lastName: string;
lastName: string

@Column()
salary: string;

salary: string
}
```

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

@Entity()
export class Student {

@PrimaryGeneratedColumn()
id: string;
id: string

@Column()
firstName: string;
firstName: string

@Column()
lastName: string;
lastName: string

@Column()
faculty: string;

faculty: string
}
```

What we can do is to reduce `firstName` and `lastName` duplication by creating a new class with those columns:

```typescript
import {Column} from "typeorm";
import { Column } from "typeorm"

export class Name {

@Column()
first: string;
first: string

@Column()
last: string;

last: string
}
```

Then you can "connect" those columns in your entities:
Then you can "connect" those columns in your entities:

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

@Entity()
export class User {

@PrimaryGeneratedColumn()
id: string;
id: string

@Column(() => Name)
name: Name;
name: Name

@Column()
isActive: boolean;

isActive: boolean
}
```

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

@Entity()
export class Employee {

@PrimaryGeneratedColumn()
id: string;
id: string

@Column(() => Name)
name: Name;
name: Name

@Column()
salary: number;

salary: number
}
```

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

@Entity()
export class Student {

@PrimaryGeneratedColumn()
id: string;
id: string

@Column(() => Name)
name: Name;
name: Name

@Column()
faculty: string;

faculty: string
}
```

Expand Down Expand Up @@ -177,6 +163,5 @@ All columns defined in the `Name` entity will be merged into `user`, `employee`
```

This way code duplication in the entity classes is reduced.
You can use as many columns (or relations) in embedded classes as you need.
You even can have nested embedded columns inside embedded classes.

You can use as many columns (or relations) in embedded classes as you need.
You even can have nested embedded columns inside embedded classes.
376 changes: 177 additions & 199 deletions docs/entities.md

Large diffs are not rendered by default.

108 changes: 43 additions & 65 deletions docs/entity-inheritance.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,64 @@
# Entity Inheritance

* [Concrete Table Inheritance](#concrete-table-inheritance)
* [Single Table Inheritance](#single-table-inheritance)
* [Using embeddeds](#using-embeddeds)
- [Concrete Table Inheritance](#concrete-table-inheritance)
- [Single Table Inheritance](#single-table-inheritance)
- [Using embeddeds](#using-embeddeds)

## Concrete Table Inheritance

You can reduce duplication in your code by using entity inheritance patterns.
The simplest and the most effective is concrete table inheritance.

For example, you have `Photo`, `Question`, `Post` entities:

```typescript
@Entity()
export class Photo {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
title: string;
title: string

@Column()
description: string;
description: string

@Column()
size: string;

size: string
}
```

```typescript
@Entity()
export class Question {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
title: string;
title: string

@Column()
description: string;
description: string

@Column()
answersCount: number;

answersCount: number
}
```

```typescript
@Entity()
export class Post {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
title: string;
title: string

@Column()
description: string;
description: string

@Column()
viewCount: number;

viewCount: number
}
```

Expand All @@ -73,46 +67,38 @@ To reduce duplication and produce a better abstraction we can create a base clas

```typescript
export abstract class Content {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
title: string;
title: string

@Column()
description: string;

description: string
}
```

```typescript
@Entity()
export class Photo extends Content {

@Column()
size: string;

size: string
}
```

```typescript
@Entity()
export class Question extends Content {

@Column()
answersCount: number;

answersCount: number
}
```

```typescript
@Entity()
export class Post extends Content {

@Column()
viewCount: number;

viewCount: number
}
```

Expand All @@ -123,58 +109,50 @@ This example will create 3 tables - `photo`, `question` and `post`.

## Single Table Inheritance

TypeORM also supports single table inheritance.
TypeORM also supports single table inheritance.
Single table inheritance is a pattern when you have multiple classes with their own properties,
but in the database they are stored in the same table.

```typescript
@Entity()
@TableInheritance({ column: { type: "varchar", name: "type" } })
export class Content {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
title: string;
title: string

@Column()
description: string;

description: string
}
```

```typescript
@ChildEntity()
export class Photo extends Content {

@Column()
size: string;

size: string
}
```

```typescript
@ChildEntity()
export class Question extends Content {

@Column()
answersCount: number;

answersCount: number
}
```

```typescript
@ChildEntity()
export class Post extends Content {

@Column()
viewCount: number;

viewCount: number
}
```

This will create a single table called `content` and all instances of photos, questions and posts
This will create a single table called `content` and all instances of photos, questions and posts
will be saved into this table.

## Using embeddeds
Expand Down
294 changes: 172 additions & 122 deletions docs/entity-manager-api.md

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions docs/entity-metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@
Entity metadata and all related metadata classes contain information about entities,
their columns, indices, relations and other entity-related information you can use
to create more complex applications or extensions for TypeORM.

TBD.
229 changes: 108 additions & 121 deletions docs/example-with-express.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Example using TypeORM with Express

* [Initial setup](#initial-setup)
* [Adding Express to the application](#adding-express-to-the-application)
* [Adding TypeORM to the application](#adding-typeorm-to-the-application)
- [Initial setup](#initial-setup)
- [Adding Express to the application](#adding-express-to-the-application)
- [Adding TypeORM to the application](#adding-typeorm-to-the-application)

## Initial setup

Expand Down Expand Up @@ -36,14 +36,14 @@ compile and run. Create it using your favorite editor and put the following conf

```json
{
"compilerOptions": {
"lib": ["es5", "es6", "dom"],
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true
}
"compilerOptions": {
"lib": ["es5", "es6", "dom"],
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true
}
}
```

Expand All @@ -58,7 +58,7 @@ touch app.ts
Let's add a simple `console.log` inside it:

```typescript
console.log("Application is up and running");
console.log("Application is up and running")
```

Now it's time to run our application.
Expand All @@ -78,7 +78,7 @@ node src/app.js
You should see the, "Application is up and running" message in your console right after you run the application.

You must compile your files each time you make a change.
Alternatively, you can setup watcher or install [ts-node](https://github.com/TypeStrong/ts-node) to avoid manual compilation each time.
Alternatively, you can set up watcher or install [ts-node](https://github.com/TypeStrong/ts-node) to avoid manual compilation each time.

## Adding Express to the application

Expand All @@ -88,43 +88,43 @@ Let's add Express to our application. First, let's install the packages we need:
npm i express @types/express --save
```

* `express` is the express engine itself. It allows us to create a web api
* `@types/express` is used to have a type information when using express
- `express` is the express engine itself. It allows us to create a web api
- `@types/express` is used to have a type information when using express

Let's edit the `src/app.ts` file and add express-related logic:

```typescript
import * as express from "express";
import {Request, Response} from "express";
import * as express from "express"
import { Request, Response } from "express"

// create and setup express app
const app = express();
app.use(express.json());
const app = express()
app.use(express.json())

// register routes

app.get("/users", function(req: Request, res: Response) {
app.get("/users", function (req: Request, res: Response) {
// here we will have logic to return all users
});
})

app.get("/users/:id", function(req: Request, res: Response) {
app.get("/users/:id", function (req: Request, res: Response) {
// here we will have logic to return user by id
});
})

app.post("/users", function(req: Request, res: Response) {
app.post("/users", function (req: Request, res: Response) {
// here we will have logic to save a user
});
})

app.put("/users/:id", function(req: Request, res: Response) {
app.put("/users/:id", function (req: Request, res: Response) {
// here we will have logic to update a user by a given user id
});
})

app.delete("/users/:id", function(req: Request, res: Response) {
app.delete("/users/:id", function (req: Request, res: Response) {
// here we will have logic to delete a user by a given user id
});
})

// start express server
app.listen(3000);
app.listen(3000)
```

Now you can compile and run your project.
Expand All @@ -143,120 +143,107 @@ Let's install the required packages first:
npm i typeorm mysql reflect-metadata --save
```

* `typeorm` is the typeorm package itself
* `mysql` is the underlying database driver.
If you are using a different database system, you must install the appropriate package
* `reflect-metadata` is required to make decorators to work properly
- `typeorm` is the typeorm package itself
- `mysql` is the underlying database driver.
If you are using a different database system, you must install the appropriate package
- `reflect-metadata` is required to make decorators to work properly

Now let's create `ormconfig.json` with the database connection configuration we will use.
Let's create `app-data-source.ts` where we set up initial database connection options:

```json
{
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "test",
"password": "test",
"database": "test",
"entities": ["src/entity/*.js"],
"logging": true,
"synchronize": true
}
```ts
import { DataSource } from "typeorm"

const myDataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
entities: ["src/entity/*.js"],
logging: true,
synchronize: true,
})
```

Configure each option as you need.
Learn more about [connection options](./connection-options.md).
Learn more about options [here](./data-source-options.md).

Let's create a `User` entity inside `src/entity`:
Let's create a `user.entity.ts` entity inside `src/entity`:

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

@Entity()
export class User {

@PrimaryGeneratedColumn()
id: number;
id: number

@Column()
firstName: string;
firstName: string

@Column()
lastName: string;

lastName: string
}
```

Let's change `src/app.ts`:
Let's change `src/app.ts` to establish database connection and start using `myDataSource`:

```typescript
import * as express from "express";
import {Request, Response} from "express";
import {createConnection} from "typeorm";
import {User} from "./entity/User";

// create typeorm connection
createConnection().then(connection => {
const userRepository = connection.getRepository(User);

// create and setup express app
const app = express();
app.use(express.json());

// register routes

app.get("/users", async function(req: Request, res: Response) {
const users = await userRepository.find();
res.json(users);
});

app.get("/users/:id", async function(req: Request, res: Response) {
const results = await userRepository.findOne(req.params.id);
return res.send(results);
});

app.post("/users", async function(req: Request, res: Response) {
const user = await userRepository.create(req.body);
const results = await userRepository.save(user);
return res.send(results);
});

app.put("/users/:id", async function(req: Request, res: Response) {
const user = await userRepository.findOne(req.params.id);
userRepository.merge(user, req.body);
const results = await userRepository.save(user);
return res.send(results);
});

app.delete("/users/:id", async function(req: Request, res: Response) {
const results = await userRepository.delete(req.params.id);
return res.send(results);
});

// start express server
app.listen(3000);
});
```
import * as express from "express"
import { Request, Response } from "express"
import { User } from "./entity/User"
import { myDataSource } from "./app-data-source.ts"

// establish database connection
myDataSource
.initialize()
.then(() => {
console.log("Data Source has been initialized!")
})
.catch((err) => {
console.error("Error during Data Source initialization:", err)
})

If you want to extract action callbacks into separate files and you need the `connection` instance,
you can simply use `getConnection`:
// create and setup express app
const app = express()
app.use(express.json())

```typescript
import {getConnection} from "typeorm";
import {User} from "./entity/User";
// register routes
app.get("/users", async function (req: Request, res: Response) {
const users = await myDataSource.getRepository(User).find()
res.json(users)
})

app.get("/users/:id", async function (req: Request, res: Response) {
const results = await myDataSource.getRepository(User).findOneBy({
id: req.params.id,
})
return res.send(results)
})

app.post("/users", async function (req: Request, res: Response) {
const user = await myDataSource.getRepository(User).create(req.body)
const results = await myDataSource.getRepository(User).save(user)
return res.send(results)
})

app.put("/users/:id", async function (req: Request, res: Response) {
const user = await myDataSource.getRepository(User).findOneBy({
id: req.params.id,
})
myDataSource.getRepository(User).merge(user, req.body)
const results = await myDataSource.getRepository(User).save(user)
return res.send(results)
})

app.delete("/users/:id", async function (req: Request, res: Response) {
const results = await myDataSource.getRepository(User).delete(req.params.id)
return res.send(results)
})

export function UsersListAction(req: Request, res: Response) {
return getConnection().getRepository(User).find();
}
// start express server
app.listen(3000)
```

You don't even need `getConnection` in this example - you can directly use the `getRepository` function:

```typescript
import {getRepository} from "typeorm";
import {User} from "./entity/User";

export function UsersListAction(req: Request, res: Response) {
return getRepository(User).find();
}
```
Now you should have a basic express application connected to MySQL database up and running.
224 changes: 102 additions & 122 deletions docs/faq.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,45 @@
# FAQ

* [How do I change a column name in the database?](#how-do-i-change-a-column-name-in-the-database)
* [How can I set value of default some function, for example `NOW()`?](#how-can-i-set-the-default-value-to-some-function-for-example-now)
* [How to do validation?](#how-to-do-validation)
* [What does "owner side" in relations mean or why we need to put `@JoinColumn` and `@JoinTable` decorators?](#what-does-owner-side-in-a-relations-mean-or-why-we-need-to-use-joincolumn-and-jointable)
* [How do I add extra columns into many-to-many (junction) table?](#how-do-i-add-extra-columns-into-many-to-many-junction-table)
* [How to use TypeORM with dependency injection tool?](#how-to-use-typeorm-with-a-dependency-injection-tool)
* [How to handle outDir TypeScript compiler option?](#how-to-handle-outdir-typescript-compiler-option)
* [How to use TypeORM with ts-node?](#how-to-use-typeorm-with-ts-node)
* [How to use Webpack for the backend](#how-to-use-webpack-for-the-backend)
* [How to use TypeORM in ESM projects?](#how-to-use-typeorm-in-esm-projects)

- [How do I change a column name in the database?](#how-do-i-change-a-column-name-in-the-database)
- [How can I set value of default some function, for example `NOW()`?](#how-can-i-set-the-default-value-to-some-function-for-example-now)
- [How to do validation?](#how-to-do-validation)
- [What does "owner side" in relations mean or why we need to put `@JoinColumn` and `@JoinTable` decorators?](#what-does-owner-side-in-a-relations-mean-or-why-we-need-to-use-joincolumn-and-jointable)
- [How do I add extra columns into many-to-many (junction) table?](#how-do-i-add-extra-columns-into-many-to-many-junction-table)
- [How to use TypeORM with dependency injection tool?](#how-to-use-typeorm-with-a-dependency-injection-tool)
- [How to handle outDir TypeScript compiler option?](#how-to-handle-outdir-typescript-compiler-option)
- [How to use TypeORM with ts-node?](#how-to-use-typeorm-with-ts-node)
- [How to use Webpack for the backend](#how-to-use-webpack-for-the-backend)
- [How to use TypeORM in ESM projects?](#how-to-use-typeorm-in-esm-projects)

## How do I update a database schema?

One of the main responsibilities of TypeORM is to keep your database tables in sync with your entities.
There are two ways that help you achieve this:

* Use `synchronize: true` in your connection options:
- Use `synchronize: true` in data source options:

```typescript
import {createConnection} from "typeorm";

createConnection({
synchronize: true
});
import { DataSource } from "typeorm"

const myDataSource = new DataSource({
// ...
synchronize: true,
})
```

This option automatically syncs your database tables with the given entities each time you run this code.
This option automatically syncs your database tables with the given entities each time you run this code.
This option is perfect during development, but in production you may not want this option to be enabled.

* Use command line tools and run schema sync manually in the command line:
- Use command line tools and run schema sync manually in the command line:

```
typeorm schema:sync
```

This command will execute schema synchronization.
Note, to make command line tools work, you must create an ormconfig.json file.

Schema sync is extremely fast.
If you are considering the disable synchronize option during development because of performance issues,
This command will execute schema synchronization.

Schema sync is extremely fast.
If you are considering to disable synchronize option during development because of performance issues,
first check how fast it is.

## How do I change a column name in the database?
Expand All @@ -55,10 +54,10 @@ isActive: boolean;

## How can I set the default value to some function, for example `NOW()`?

`default` column option supports a function.
`default` column option supports a function.
If you are passing a function which returns a string,
it will use that string as a default value without escaping it.
For example:
For example:

```typescript
@Column({ default: () => "NOW()" })
Expand All @@ -79,40 +78,36 @@ Let's say we have two entities: `User` and `Photo`:
```typescript
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
id: number
@Column()
name: string;
name: string
@OneToOne()
photo: Photo;
photo: Photo
}
```

```typescript
@Entity()
export class Photo {
@PrimaryGeneratedColumn()
id: number;
id: number
@Column()
url: string;
url: string
@OneToOne()
user: User;
user: User
}
```

This example does not have a `@JoinColumn` which is incorrect.
Why? Because to make a real relation, we need to create a column in the database.
We need to create a column `userId` in `photo` or `photoId` in `user`.
But which column should be created - `userId` or `photoId`?
TypeORM cannot decide for you.
TypeORM cannot decide for you.
To make a decision, you must use `@JoinColumn` on one of the sides.
If you put `@JoinColumn` in `Photo` then a column called `userId` will be created in the `photo` table.
If you put `@JoinColumn` in `User` then a column called `photoId` will be created in the `user` table.
Expand All @@ -121,34 +116,19 @@ The other side of the relation, without `@JoinColumn`, is called the "inverse (n

It is the same in a `@ManyToMany` relation. You use `@JoinTable` to show the owner side of the relation.

In `@ManyToOne` or `@OneToMany` relations, `@JoinColumn` is not necessary because
both decorators are different, and the table where you put the `@ManyToOne` decorator will have the relational column.
In `@ManyToOne` or `@OneToMany` relations, `@JoinColumn` is not necessary because
both decorators are different, and the table where you put the `@ManyToOne` decorator will have the relational column.

`@JoinColumn` and `@JoinTable` decorators can also be used to specify additional
join column / junction table settings, like join column name or junction table name.
join column / junction table settings, like join column name or junction table name.

## How do I add extra columns into many-to-many (junction) table?

It's not possible to add extra columns into a table created by a many-to-many relation.
You'll need to create a separate entity and bind it using two many-to-one relations with the target entities
(the effect will be same as creating a many-to-many table),
(the effect will be same as creating a many-to-many table),
and add extra columns in there. You can read more about this in [Many-to-Many relations](./many-to-many-relations.md#many-to-many-relations-with-custom-properties).

## How to use TypeORM with a dependency injection tool?

In TypeORM you can use service containers. Service containers allow you to inject custom services in some places, like in subscribers or custom naming strategies. For example, you can get access to ConnectionManager from any place using a service container.

Here is an example for how you can set up typedi service containers with TypeORM. Note: you can setup any service container with TypeORM.

```typescript
import {useContainer, createConnection} from "typeorm";
import {Container} from "typedi";
// its important to setup container before you start to work with TypeORM
useContainer(Container);
createConnection({/* ... */});
```

## How to handle outDir TypeScript compiler option?

When you are using the `outDir` compiler option, don't forget to copy assets and resources your app is using into the output directory.
Expand All @@ -158,13 +138,13 @@ One important thing to know is that when you remove or move entities, the old en
For example, you create a `Post` entity and rename it to `Blog`,
you no longer have `Post.ts` in your project. However, `Post.js` is left inside the output directory.
Now, when TypeORM reads entities from your output directory, it sees two entities - `Post` and `Blog`.
This may be a source of bugs.
That's why when you remove and move entities with `outDir` enabled, it's strongly recommended to remove your output directory and recompile the project again.
This may be a source of bugs.
That's why when you remove and move entities with `outDir` enabled, it's strongly recommended to remove your output directory and recompile the project again.

## How to use TypeORM with ts-node?

You can prevent compiling files each time using [ts-node](https://github.com/TypeStrong/ts-node).
If you are using ts-node, you can specify `ts` entities inside your connection options:
If you are using ts-node, you can specify `ts` entities inside data source options:

```
{
Expand All @@ -173,9 +153,9 @@ If you are using ts-node, you can specify `ts` entities inside your connection o
}
```

Also, if you are compiling js files into the same folder where your typescript files are,
make sure to use the `outDir` compiler option to prevent
[this issue](https://github.com/TypeStrong/ts-node/issues/432).
Also, if you are compiling js files into the same folder where your typescript files are,
make sure to use the `outDir` compiler option to prevent
[this issue](https://github.com/TypeStrong/ts-node/issues/432).

Also, if you want to use the ts-node CLI, you can execute TypeORM the following way:

Expand Down Expand Up @@ -212,77 +192,79 @@ module.exports = {
By default Webpack tries to bundle everything into one file. This can be problematic when your project has migration files which are meant to be executed after bundled code is deployed to production. To make sure all your migrations can be recognized and executed by TypeORM, you may need to use "Object Syntax" for the `entry` configuration for the migration files only.

```js
const glob = require('glob');
const path = require('path');
const glob = require("glob")
const path = require("path")
module.exports = {
// ... your webpack configurations here...
// Dynamically generate a `{ [name]: sourceFileName }` map for the `entry` option
// change `src/db/migrations` to the relative path to your migration folder
entry: glob.sync(path.resolve('src/db/migrations/*.ts')).reduce((entries, filename) => {
const migrationName = path.basename(filename, '.ts');
return Object.assign({}, entries, {
[migrationName]: filename,
});
}, {}),
resolve: {
// assuming all your migration files are written in TypeScript
extensions: ['.ts']
},
output: {
// change `path` to where you want to put transpiled migration files.
path: __dirname + '/dist/db/migrations',
// this is important - we want UMD (Universal Module Definition) for migration files.
libraryTarget: 'umd',
filename: '[name].js',
},
};
// ... your webpack configurations here...
// Dynamically generate a `{ [name]: sourceFileName }` map for the `entry` option
// change `src/db/migrations` to the relative path to your migration folder
entry: glob
.sync(path.resolve("src/db/migrations/*.ts"))
.reduce((entries, filename) => {
const migrationName = path.basename(filename, ".ts")
return Object.assign({}, entries, {
[migrationName]: filename,
})
}, {}),
resolve: {
// assuming all your migration files are written in TypeScript
extensions: [".ts"],
},
output: {
// change `path` to where you want to put transpiled migration files.
path: __dirname + "/dist/db/migrations",
// this is important - we want UMD (Universal Module Definition) for migration files.
libraryTarget: "umd",
filename: "[name].js",
},
}
```

Also, since Webpack 4, when using `mode: 'production'`, files are optimized by default which includes mangling your code in order to minimize file sizes. This breaks the migrations because TypeORM relies on their names to determine which has already been executed. You may disable minimization completely by adding:

```js
module.exports = {
// ... other Webpack configurations here
optimization: {
minimize: false,
},
};
// ... other Webpack configurations here
optimization: {
minimize: false,
},
}
```

Alternatively, if you are using the `UglifyJsPlugin`, you can tell it to not change class or function names like so:

```js
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin")

module.exports = {
// ... other Webpack configurations here
optimization: {
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
keep_classnames: true,
keep_fnames: true
}
})
],
},
};
// ... other Webpack configurations here
optimization: {
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
keep_classnames: true,
keep_fnames: true,
},
}),
],
},
}
```
Lastly, make sure in your `ormconfig` file, the transpiled migration files are included:
Lastly, make sure in your data source options, the transpiled migration files are included:
```js
// TypeORM Configurations
module.exports = {
// ...
migrations: [
// this is the relative path to the transpiled migration files in production
'db/migrations/**/*.js',
// your source migration files, used in development mode
'src/db/migrations/**/*.ts',
],
};
// ...
migrations: [
// this is the relative path to the transpiled migration files in production
"db/migrations/**/*.js",
// your source migration files, used in development mode
"src/db/migrations/**/*.ts",
],
}
```
## How to use TypeORM in ESM projects?
Expand All @@ -294,10 +276,8 @@ To avoid circular dependency import issues use the `Relation` wrapper type for r
```typescript
@Entity()
export class User {

@OneToOne(() => Profile, profile => profile.user)
profile: Relation<Profile>;

@OneToOne(() => Profile, (profile) => profile.user)
profile: Relation<Profile>
}
```
Expand Down
Loading