Skip to content

E2E Scenario: Transaction With Models

This guide is derived from apps/fedaco-e2e/src/test/transaction/transaction-with-models.spec.ts.

Setup Pattern

ts
import { Column, DatabaseConfig, Model, PrimaryColumn, Table } from '@gradii/fedaco';
import { sqliteDriver } from '@gradii/fedaco-sqlite-driver';

@Table({ tableName: 'users' })
class User extends Model {
  _timestamps = false;

  @PrimaryColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  email: string;
}

Use a connection and create tables before each scenario.

Pattern 1: .withConnection(tx)

ts
await connection.transaction(async (tx) => {
  const user = await User.createQuery()
    .withConnection(tx)
    .create({ name: 'Alice', email: 'alice@example.com' });

  await Post.createQuery()
    .withConnection(tx)
    .create({
      user_id: user.id,
      title: 'First Post',
      content: 'Hello World',
    });
});

Pattern 2: createQuery(tx)

ts
await connection.transaction(async (tx) => {
  const user = await User.createQuery(tx).create({
    name: 'Bob',
    email: 'bob@example.com',
  });

  await Post.createQuery(tx).create({
    user_id: user.id,
    title: 'Second Post',
    content: 'Using createQuery(tx)',
  });
});

Rollback Behavior

Both patterns roll back when an error is thrown:

ts
await connection.transaction(async (tx) => {
  await User.createQuery(tx).create({ name: 'David', email: 'david@example.com' });
  throw new Error('Transaction failed');
});

After rollback, inserted rows are not persisted.

With Transaction Options

ts
await connection.transaction(
  async (tx) => {
    await User.createQuery(tx).create({ name: 'Frank', email: 'frank@example.com' });
  },
  { timeout: 5000, isolationLevel: 'SERIALIZABLE' },
);

Released under the MIT License.