Managing Transactions with TypeORM and TypeScript

  • 2024/8/22
  • Managing Transactions with TypeORM and TypeScript はコメントを受け付けていません

In this blog post, we will explore how to manage transactions using TypeORM and TypeScript, focusing on the TransactionalEntityManager. Transactions are a crucial aspect of database management systems, ensuring data consistency and integrity. We’ll illustrate the concepts with a practical code example.

What is TypeORM?

TypeORM is an Object-Relational Mapper (ORM) for TypeScript and JavaScript (ES7, ES6, ES5). It supports various SQL-based databases, including PostgreSQL, MySQL, SQLite, and others. TypeORM allows developers to interact with databases using an object-oriented approach, making it easier to manage and query data.

Why Use Transactions?

A transaction is a sequence of operations performed as a single logical unit of work. The key properties of a transaction are encapsulated in the ACID principles:

  • Atomicity: Ensures that all operations within a transaction are completed successfully; otherwise, the transaction is aborted.
  • Consistency: Guarantees that the database remains in a consistent state before and after the transaction.
  • Isolation: Ensures that transactions are executed in isolation from one another.
  • Durability: Guarantees that once a transaction is committed, it remains so, even in the event of a system failure.

Transactions are vital when multiple operations need to be performed on a database, and these operations must either all succeed or all fail to maintain data integrity.

Using TransactionalEntityManager in TypeORM

TypeORM provides the TransactionalEntityManager to manage transactions. This special entity manager is used to execute all operations within a transaction context.

Code Example: Managing Transactions with TypeORM

Let’s consider an example where we have two entities: User and Order. We want to create a new user and an order in a single transaction. If either operation fails, the entire transaction should be rolled back.

Entities

import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm";

 

@Entity()

export class User {

  @PrimaryGeneratedColumn()

  id: number;

 

  @Column()

  name: string;

 

  @Column()

  email: string;

}

 

@Entity()

export class Order {

  @PrimaryGeneratedColumn()

  id: number;

 

  @Column()

  product: string;

 

  @Column("decimal")

  price: number;

 

  @ManyToOne(() => User, (user) => user.id)

  user: User;

}

 

Transaction Service

import { getManager } from "typeorm";

import { User } from "./entities/User";

import { Order } from "./entities/Order";

 

async function createOrderWithUser() {

  await getManager().transaction(async (transactionalEntityManager) => {

    // Create a new user

    const user = new User();

    user.name = "John Doe";

    user.email = "john.doe@example.com";

    await transactionalEntityManager.save(user);

 

    // Create a new order for the user

    const order = new Order();

    order.product = "Laptop";

    order.price = 1200.00;

    order.user = user;

 

    // Save the order

    await transactionalEntityManager.save(order);

  });

}

 

createOrderWithUser()

  .then(() => console.log("User and order created successfully"))

  .catch((error) => console.log("Transaction failed, rolling back", error));

Explanation of the Code

  1. Entities:
    • We define two entities: User and Order. The User entity represents a user in the system, while the Order entity represents a product order linked to a user.
  2. Transaction Service:
    • The createOrderWithUser function encapsulates the transactional logic. We use getManager().transaction() to initiate a transaction.
    • Within the transaction callback, we create and save a new User and then create and save a new Order linked to that user.
    • If any of the operations fail, the transaction will be rolled back, ensuring data consistency.

Benefits of Using Transactions with TypeORM

  1. Data Integrity: Transactions ensure that all operations within a transaction either complete successfully or are rolled back, maintaining the integrity of the database.
  2. Error Handling: By using transactions, we can handle errors more effectively. If an error occurs, we can roll back all changes made during the transaction.
  3. Concurrency Control: Transactions help manage concurrent operations, preventing data corruption and ensuring that each transaction is isolated.
  4. Simplicity: TypeORM’s TransactionalEntityManager provides a straightforward way to manage transactions, making it easy for developers to implement complex transaction logic without boilerplate code.

Conclusion

Using TypeORM and TypeScript together provides a robust and efficient way to manage transactions in your application. By leveraging the TransactionalEntityManager, you can ensure that your data operations are consistent and reliable. This approach is crucial for applications that require a high level of data integrity and consistency. Whether you’re working on a small project or a large-scale system, understanding and implementing transactions correctly is vital for maintaining a healthy and robust application.

関連記事

カテゴリー:

ブログ

情シス求人

  1. チームメンバーで作字やってみた#1

ページ上部へ戻る