中介軟體
已廢棄:中介軟體在版本 4.16.0 中已廢棄。
我們建議使用 Prisma Client 擴充套件的 `query` 元件型別 作為中介軟體的替代方案。Prisma Client 擴充套件於版本 4.7.0 首次作為預覽版引入,並於 4.16.0 版本正式釋出。
Prisma Client 擴充套件允許你建立獨立的 Prisma Client 例項,並將每個客戶端繫結到特定的過濾器或使用者。例如,你可以將客戶端繫結到特定使用者以提供使用者隔離。Prisma Client 擴充套件還提供端到端的型別安全。
中介軟體充當查詢級別的生命週期鉤子,允許你在查詢執行之前或之後執行操作。使用 `prisma.$use` 方法新增中介軟體,如下所示:
const prisma = new PrismaClient()
// Middleware 1
prisma.$use(async (params, next) => {
// Manipulate params here
const result = await next(params)
// See results here
return result
})
// Middleware 2
prisma.$use(async (params, next) => {
// Manipulate params here
const result = await next(params)
// See results here
return result
})
// Queries here
使用 批次事務 時,請勿在中介軟體中多次呼叫 `next`。這會導致你跳出事務並導致意外結果。
`params` 表示中介軟體中可用的引數,例如查詢名稱,而 `next` 表示 棧中的下一個中介軟體或原始的 Prisma Client 查詢。
中介軟體的可能用例包括:
- 設定或覆蓋欄位值 - 例如,設定部落格文章評論的上下文語言
- 驗證輸入資料 - 例如,透過外部服務檢查使用者輸入是否包含不當語言
- 攔截 `delete` 查詢並將其更改為 `update` 以執行 軟刪除
- 記錄執行查詢所花費的時間
中介軟體還有許多其他用例——此列表旨在為中介軟體旨在解決的問題型別提供靈感。
示例
以下示例場景展示瞭如何在實踐中使用中介軟體:
中介軟體示例:軟刪除
以下示例使用中介軟體執行軟刪除。軟刪除意味著透過更改欄位(例如將 deleted 設定為 true)將記錄標記為已刪除,而不是實際從資料庫中刪除。使用軟刪除的原因包括:
中介軟體示例:日誌記錄
以下示例記錄 Prisma Client 查詢執行所花費的時間
中介軟體示例:會話資料
以下示例將每個 Post 的語言欄位設定為上下文語言(例如,取自會話狀態)
新增中介軟體的位置
將 Prisma Client 中介軟體新增到請求處理程式上下文之外,否則每個請求都會向棧中新增一個新的中介軟體例項。以下示例演示了在 Express 應用程式上下文中新增 Prisma Client 中介軟體的位置:
import express from 'express'
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
prisma.$use(async (params, next) => {
// Manipulate params here
const result = await next(params)
// See results here
return result
})
const app = express()
app.get('/feed', async (req, res) => {
// NO MIDDLEWARE HERE
const posts = await prisma.post.findMany({
where: { published: true },
include: { author: true },
})
res.json(posts)
})
執行順序和中介軟體棧
如果你有多箇中間件,則每個獨立查詢的執行順序是:
- 每個中介軟體中 `await next(params)` 之前的所有邏輯,按降序排列
- 每個中介軟體中 `await next(params)` 之後的所有邏輯,按升序排列
根據你在棧中的位置,`await next(params)` 會:
- 執行下一個中介軟體(在示例中的中介軟體 #1 和 #2 中)或
- 執行原始的 Prisma Client 查詢(在中介軟體 #3 中)
const prisma = new PrismaClient()
// Middleware 1
prisma.$use(async (params, next) => {
console.log(params.args.data.title)
console.log('1')
const result = await next(params)
console.log('6')
return result
})
// Middleware 2
prisma.$use(async (params, next) => {
console.log('2')
const result = await next(params)
console.log('5')
return result
})
// Middleware 3
prisma.$use(async (params, next) => {
console.log('3')
const result = await next(params)
console.log('4')
return result
})
const create = await prisma.post.create({
data: {
title: 'Welcome to Prisma Day 2020',
},
})
const create2 = await prisma.post.create({
data: {
title: 'How to Prisma!',
},
})
輸出
Welcome to Prisma Day 2020
1
2
3
4
5
6
How to Prisma!
1
2
3
4
5
6
效能和合適的用例
中介軟體對每個查詢都執行,這意味著過度使用可能會對效能產生負面影響。為避免增加效能開銷:
-
在中介軟體中儘早檢查 `params.model` 和 `params.action` 屬性,以避免不必要地執行邏輯
prisma.$use(async (params, next) => {
if (params.model == 'Post' && params.action == 'delete') {
// Logic only runs for delete action and Post model
}
return next(params)
}) -
考慮中介軟體是否是你的場景的合適解決方案。例如:
- 如果你需要填充欄位,可以使用 `@default` 屬性嗎?
- 如果你需要設定 `DateTime` 欄位的值,可以使用 `now()` 函式或 `@updatedAt` 屬性嗎?
- 如果你需要執行更復雜的驗證,可以在資料庫本身使用 `CHECK` 約束嗎?