Reputation: 1145
I have some question with TypeORM
transaction.
So my code is like below:
public createOrderTransaction = async (
data: CreateOrderInputDTO,
): Promise<Order> => {
const queryRunner = this.connection.createQueryRunner();
await queryRunner.startTransaction();
try {
const order = await this.createOrder(data);
await this.createOrderRecord(order.id, data);
await queryRunner.commitTransaction();
return order;
} catch (error) {
this.logger.error(
"Transaction Error: 'createOrderTransaction' is failed: ",
error,
);
if (queryRunner.isTransactionActive) {
await queryRunner.rollbackTransaction();
}
}
};
And one function like createOrder
use query builder:
private createOrder = async (data: CreateOrderInputDTO): Promise<Order> => {
const { identifiers } = await this.orderRepository
.createQueryBuilder('order')
.insert()
.into(Order)
.values([data])
.execute();
await this.saveOrderDetail(identifiers[0].id, data.orderDetails);
await this.orderRepository
.createQueryBuilder('order')
.relation(Order, 'orderDetails')
.of(identifiers[0].id)
.add(data.orderDetails);
return this.getOrder(identifiers[0].id);
};
But when I try it, and if it fire some error middle of logic, rollback doesn't work.
The way I see it, It seem that query builder
doesn't support transaction.
So Is there any way to use quert builder
with transaction
?
Upvotes: 4
Views: 10689
Reputation: 3239
I don't know if this helps help anyone facing this question, but instead of doing in above answer, we can use dataSource, as suggested in this official TypeOrm transaction document, and instead of adding Entity in queryBuilder, add it to .from()
await myDataSource.manager.transaction(async (transactionalEntityManager) => {
// We can use 'transactionalEntityManager' to create queryBuilder here:
await transactionalEntityManager.createQueryBuilder()
.from(Order, 'order')
.insert()
.into(OrderRecord)
.values([
{
...data,
orderId,
createdAt: new Date(),
},
])
.execute();
// And of course similar with relation table:
await transactionalEntityManager
.createQueryBuilder()
.from(Order, 'order')
.relation(OrderRecord, 'orderDetails')
.of(orderId)
.add(data.orderDetails);
})
Upvotes: 0
Reputation: 1145
Self Answer...
After I am looking into TypeORM index.d.ts
, I take it that there are some parameter in createQueryBuilder
named queryRunner
so. If you input there your own query runner for transaction you can use queryBuilder
with queryRunner
As like:
public createOrderTransaction = async (
data: CreateOrderInputDTO,
): Promise<Order> => {
const queryRunner = this.connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const order = await this.createOrder(data, queryRunner);
await this.createOrderRecord(order.id, data, queryRunner);
await queryRunner.commitTransaction();
return order;
} catch (error) {
this.logger.error(
"Transaction Error: 'createOrderTransaction' is failed: ",
error,
);
if (queryRunner.isTransactionActive) {
await queryRunner.rollbackTransaction();
}
}
};
createOrder
as like:
private createOrderRecord = async (
orderId: string,
data: CreateOrderInputDTO,
queryRunner?: QueryRunner,
): Promise<void> => {
await this.orderRecordRepository
.createQueryBuilder('order_record', queryRunner)
.insert()
.into(OrderRecord)
.values([
{
...data,
orderId,
createdAt: new Date(),
},
])
.execute();
await this.orderRecordRepository
.createQueryBuilder('order_record', queryRunner)
.relation(OrderRecord, 'orderDetails')
.of(orderId)
.add(data.orderDetails);
};
Upvotes: 3