#postgresql #nestjs #typeorm
#postgresql #nestjs #typeorm
Вопрос:
Я использую Nest.js с помощью TypeORM и Postgres.
То, что я пытаюсь сделать, это создать и экземпляр моей User
сущности. В нем есть Membership
и File
поля, которые также являются объектами. Они имеют отношение один к одному User
, поэтому создаются при User
создании. Если что-то пойдет не так, я хочу все откатить, поэтому я использую транзакцию.
Это то, что я делаю:
async create(userProcessed: UserProcessed): Promise<UserResponse> {
const response: UserResponse = {
message: 'User not created',
success: false,
user: undefined,
};
const queryRunner = this.connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const membership = new Membership();
membership.membershipState = userProcessed.membershipState;
membership.membershipType = userProcessed.membershipType;
const membershipSaved = await queryRunner.manager.save(membership);
if (!membershipSaved) throw Error();
const file = new File();
file.weight = userProcessed.file.weight;
file.height = userProcessed.file.height;
const fileSaved = await queryRunner.manager.save(file);
if (!fileSaved) throw Error(response.message);
const user = new User();
user.email = userProcessed.email;
user.firstName = userProcessed.firstName;
user.lastName = userProcessed.lastName;
user.gender = userProcessed.gender;
user.file = fileSaved;
user.membership = membershipSaved;
user.role = userProcessed.role;
user.birthday = new Date(userProcessed.birthday);
user.setPassword(userProcessed.password);
const userSaved = await this.userRepository.save(user);
console.log(userSaved);
if (!userSaved) throw Error(response.message);
response.success = true;
response.message = 'User created';
response.user = userSaved;
await queryRunner.commitTransaction();
return response;
} catch (e) {
await queryRunner.rollbackTransaction();
throw Error(response.message);
} finally {
await queryRunner.release();
}
}
Проблема возникает при создании пользователя. Поскольку я использую транзакцию, ничего не сохраняется в БД, пока я не вызову await queryRunner.commitTransaction();
(как и должно быть). В результате membership
и file
, которые я пытаюсь использовать в качестве внешнего ключа, на самом деле не существует.
Есть ли способ, которым я могу решить эту проблему в той же транзакции?
Ответ №1:
Это было проще, чем я думал.
Я только что обнаружил, что могу установить { cascade: ['insert'] }
@OneToOne
аннотацию в User
. При этом нет необходимости сохранять File
или Membership
раньше User
, сохраняются при User
сохранении.
В user.entity.ts
:
...
@OneToOne(type => Membership, { cascade: ['insert'] })
@JoinColumn({ name: 'membership_id' })
membership: Membership;
@OneToOne(type => File, { cascade: ['insert'] })
@JoinColumn({ name: 'file_id' })
file: File;
...
В user.service.ts
async create(userProcessed: UserProcessed): Promise<UserResponse> {
const response: UserResponse = {
message: 'User not created',
success: false,
user: undefined,
};
const queryRunner = this.connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const membership = new Membership();
membership.membershipState = userProcessed.membershipState;
membership.membershipType = userProcessed.membershipType;
const file = new File();
file.weight = userProcessed.file.weight;
file.height = userProcessed.file.height;
const user = new User();
user.email = userProcessed.email;
user.firstName = userProcessed.firstName;
user.lastName = userProcessed.lastName;
user.gender = userProcessed.gender;
user.file = file;
user.membership = membership;
user.role = userProcessed.role;
user.birthday = new Date(userProcessed.birthday);
user.setPassword(userProcessed.password);
const userSaved = await this.userRepository.save(user);
console.log(userSaved);
if (!userSaved) throw Error(response.message);
response.success = true;
response.message = 'User created';
response.user = userSaved;
await queryRunner.commitTransaction();
return response;
} catch (e) {
await queryRunner.rollbackTransaction();
throw Error(response.message);
} finally {
await queryRunner.release();
}
}
И с этим все работает как шарм!