DataSource владеет конфигурацией и пулом соединений. EntityManager выполняет операции с сущностями. Их разделяют, чтобы настройки жили в одном месте, а сценарии не создавали собственные пулы.
Инициализация один раз
import { DataSource } from 'typeorm';
import { Product } from './product.entity';
export const dataSource = new DataSource({
type: 'postgres',
url: process.env.DATABASE_URL,
entities: [Product],
migrations: [],
synchronize: false,
});
await dataSource.initialize();
initialize открывает пул и проверяет соединение. Повторный вызов в каждом запросе - ошибка жизненного цикла. В NestJS инициализацией и закрытием управляет TypeOrmModule.forRoot, поэтому второй ручной DataSource не нужен.
DataSource используют для транзакций и специальных операций, dataSource.manager - для обычных вызовов EntityManager. Репозиторий конкретной сущности получают через getRepository(Product).
EntityManager и репозиторий
const product = dataSource.manager.create(Product, {
name: 'Кофемолка',
price: 4990,
});
await dataSource.manager.save(product);
create создает объект в памяти, save записывает его. Для чтения используют find, findOne или QueryBuilder, а не повторное создание соединения.
Пул ограничен. Запросы, которые не завершены, удерживают соединение и мешают остальным. Транзакции заканчивают коммитом или откатом, процесс при остановке закрывает DataSource через lifecycle NestJS.
Коротко
- DataSource инициализируют один раз и закрывают при остановке.
- EntityManager выполняет операции, репозиторий ограничивает их одной сущностью.
createне записывает объект,saveзаписывает.- Пул нельзя создавать на запрос или оставлять транзакции открытыми.
- В NestJS жизненным циклом управляет TypeOrmModule.
Что почитать дальше
- Транзакции и isolation - границы атомарности.
- Репозиторий и Data Mapper - где заканчивается ORM.