事务

未匹配的标注

Lucid 对事务和保存点具有一流的支持。您可以通过调用 Database.transaction 方法来创建新事务。

import Database from '@ioc:Adonis/Lucid/Database'

// 创建事务
const trx = await Database.transaction()

就像 Database 模块一样,您还可以使用 trx 对象来创建查询构建器实例。

// title: 插入
await trx
  .insertQuery()
  .table('users')
  .insert({ username: 'virk' })
// title: 查询
await trx
  .query()
  .select('*')
  .from('users')

执行完查询后,您必须 commit 或者 rollback 事务。否则,查询将挂起直到超时。

以下是使用带有插入查询的事务的完整示例。

const trx = await Database.transaction()

try {
  await trx
    .insertQuery()
    .table('users')
    .insert({ username: 'virk' })

  await trx.commit()
} catch (error) {
  await trx.rollback()
}

事务托管

上面的示例要求您必须通过将代码包装在 try/catch 块中来手动 commitrollback 事务。事务托管会自动为您执行此操作。

您可以通过将回调传递给 transaction 方法来创建事务托管。

  • 执行回调后事务自动提交。
  • 如果回调引发异常,事务将自动回滚并重新引发异常。
await Database.transaction(async (trx) => {
  await trx
    .insertQuery()
    .table('users')
    .insert({ username: 'virk' })
})

您还可以从回调中返回一个值,然后在顶级范围内访问它。例如:

const userId = await Database.transaction(async (trx) => {
  const response = await trx
    .insertQuery()
    .table('users')
    .insert({ username: 'virk' })

  return response[0] // 👈 返回值
})

隔离级别

您可以在调用 Database.transaction 方法时定义事务的隔离级别。

await Database.transaction({
  isolationLevel: 'read uncommitted'
})

以下是使用事务托管定义隔离级别的示例。

await Database.transaction(async (trx) => {
  // 这里使用 trx
}, {
  isolationLevel: 'read committed'
})

以下是可用隔离级别的列表。

  • "read uncommitted"
  • "read committed"
  • "snapshot"
  • "repeatable read"
  • "serializable"

事务传递

事务 API 不仅限于从事务对象创建查询构建器实例。您还可以将其传递给现有的查询构建器实例或模型。

import Database from '@ioc:Adonis/Lucid/Database'
const trx = await Database.transaction()

Database
  .insertQuery({ client: trx }) 👈
  .table('users')
  .insert({ username: 'virk' })

或者在稍后阶段使用 useTransaction 方法传递它。

import Database from '@ioc:Adonis/Lucid/Database'
const trx = await Database.transaction()

Database
  .insertQuery()
  .table('users')
  .useTransaction(trx) 👈
  .insert({ username: 'virk' })

保存点

每次创建嵌套事务时,Lucid 在幕后创建一个新的 [savepoint] (en.wikipedia.org/wiki/Savepoint)。
由于事务需要专用连接,因此使用保存点可以减少所需连接的数量。

import Database from '@ioc:Adonis/Lucid/Database'

// 创建事务
const trx = await Database.transaction()

// 这次创建了一个保存点
const savepoint = await trx.transaction()

 // 也可以回滚保存点
await trx.rollback()

使用带有 Lucid 模型的事务

您可以使用 useTransaction 方法将事务传递给模型实例。

在模型类中,您可以使用 this.$trx 属性访问事务对象。该属性仅在事务执行期间可用。在 commitrollback 之后,它将被重置为 undefined

import User from 'App/Models/User'
import Database from '@ioc:Adonis/Lucid/Database'

// 高亮开始
await Database.transaction(async (trx) => {
  const user = new User()
  user.username = 'virk'

  user.useTransaction(trx)
  await user.save()
})
// 高亮结束

模型查询构建器

就像标准查询构建器一样,您也可以将事务传递给模型查询构建器。

import Database from '@ioc:Adonis/Lucid/Database'
import User from 'App/Models/User'

const trx = await Database.transaction()

const users = await User
  .query({ client: trx }) 👈
  .where('is_active', true)

在事务中保持关系

事务最常见的例子是保持关系。考虑以下通过将它们包装在单个事务中来 创建新用户他们的个人资料 的示例。

import Database from '@ioc:Adonis/Lucid/Database'
import User from 'App/Models/User'

// 高亮开始
await Database.transaction(async (trx) => {
  const user = new User()
  user.username = 'virk'

  user.useTransaction(trx)
  await user.save()

  /**
   * 该关系将隐式引用来自用户实例的事务
   */
  await user.related('profile').create({
    fullName: 'Harminder Virk',
    avatar: 'some-url.jpg',
  })
})
// 高亮结束

在下面的示例中,我们获取一个现有用户并为他们创建一个新的配置文件。

import Database from '@ioc:Adonis/Lucid/Database'
import User from 'App/Models/User'

// 高亮开始
await Database.transaction(async (trx) => {
  const user = await User.findOrFail(1, { client: trx })

  /**
   * 该关系将隐式引用来自用户实例的事务
   */
  await user.related('profile').create({
    fullName: 'Harminder Virk',
    avatar: 'some-url.jpg',
  })
})
// 高亮结束

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/adonisjs/5.x/da...

译文地址:https://learnku.com/docs/adonisjs/5.x/da...

上一篇 下一篇
贡献者:4
讨论数量: 0
发起讨论 只看当前版本


暂无话题~