fontcolor_theme
Deepkit ORM

事务

事务是按顺序执行的一组语句、查询或操作(如 select、insert、update 或 delete),它们作为单个工作单元执行,可以提交或回滚。

Deepkit 为所有官方支持的数据库提供事务支持。默认情况下,任何查询或数据库会话都不使用事务。要启用事务,有两种主要方法:会话和回调。

会话事务

你可以为每个创建的会话启动并分配一个新事务。这是与数据库交互的首选方式,因为你可以轻松传递 Session 对象,并且由该会话实例化的所有查询都会自动归入其事务。

一种典型的模式是将所有操作包裹在 try-catch 块中,并在最后一行执行 commit()(仅当之前的所有命令都成功时才会执行),在 catch 块中执行 rollback(),以便一旦发生错误就回滚所有更改。

尽管存在替代的 API(见下文),但所有事务仅适用于数据库会话对象。要将数据库会话中工作单元的未提交更改持久化到数据库,通常调用 commit()。在事务性会话中,commit() 不仅会将所有待处理更改提交到数据库,还会完成(“提交”)事务,从而关闭该事务。或者,你可以调用 session.flush() 在不调用 commit 的情况下提交所有待处理更改,从而不会关闭事务。若要在不刷新工作单元的情况下提交事务,请使用 session.commitTransaction()

const session = database.createSession();

// 这会分配一个新事务,并在下一次数据库操作时启动它。
session.useTransaction();

try {
    // 该查询在事务中执行
    const users = await session.query(User).find();

    await moreDatabaseOperations(session);

    await session.commit();
} catch (error) {
    await session.rollback();
}

一旦 commit()rollback() 在会话中执行,该事务就会被释放。如果你想在新事务中继续,就必须再次调用 useTransaction()

请注意,一旦在事务性会话中执行了第一条数据库操作,分配的数据库连接将固定并独占于当前会话对象(粘性)。因此,所有后续操作都会在同一连接上执行(从而在大多数数据库中,也是在同一数据库服务器上)。只有当事务性会话终止(commit 或 rollback)时,数据库连接才会被再次释放。因此,建议尽可能缩短事务的持续时间。

如果一个会话已经连接到某个事务,调用 session.useTransaction() 将始终返回同一对象。使用 session.isTransaction() 来检查会话是否关联了事务。

不支持嵌套事务。

事务回调

事务性会话的另一种替代方式是 database.transaction(callback)

await database.transaction(async (session) => {
    // 该查询在事务中执行
    const users = await session.query(User).find();

    await moreDatabaseOperations(session);
});

database.transaction(callback) 方法会在一个新的事务性会话中执行异步回调。若回调成功(即未抛出错误),该会话会自动提交(其事务被提交,且所有更改被刷新)。若回调失败,会话会自动执行 rollback(),并将错误向外传播。

隔离级别

许多数据库支持不同类型的事务。要更改事务行为,你可以对 useTransaction() 返回的事务对象调用不同的方法。该事务对象的接口取决于所使用的数据库适配器。例如,来自 MySQL 数据库的事务对象与来自 MongoDB 的事务对象具有不同的选项。使用代码补全或查看数据库适配器的接口以获取可用选项列表。

const database = new Database(new MySQLDatabaseAdapter());

const session = database.createSession();
session.useTransaction().readUncommitted();

try {
    //...操作
    await session.commit();
} catch (error) {
    await session.rollback();
}

// 或者
await database.transaction(async (session) => {
    // 只要尚未执行任何数据库操作,这是可行的。
    session.useTransaction().readUncommitted();

    //...操作
});

虽然 MySQL、PostgreSQL 和 SQLite 的事务默认即可使用,但对 MongoDB,你必须先将其设置为“副本集”。

要将标准的 MongoDB 实例转换为副本集,请参阅官方文档链接: 将独立部署转换为副本集.

English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)