日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Prisma.js:JavaScript中的代碼優(yōu)先ORM

譯者 | 李睿

成都創(chuàng)新互聯(lián)公司是專業(yè)的綠春網(wǎng)站建設(shè)公司,綠春接單;提供成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行綠春網(wǎng)站開發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!

審校 | 重樓

Prisma是一個(gè)流行的對(duì)象關(guān)系映射(ORM)工具,用于服務(wù)器端的JavaScript和TypeScript。其核心目的是簡(jiǎn)化和自動(dòng)化數(shù)據(jù)在存儲(chǔ)和應(yīng)用程序代碼之間的移動(dòng)方式。Prisma支持廣泛的數(shù)據(jù)存儲(chǔ),并為數(shù)據(jù)持久性提供了一個(gè)強(qiáng)大而靈活的抽象層。通過(guò)這個(gè)代碼優(yōu)先之旅,可以了解Prisma及其一些核心功能。

JavaScript的ORM層

對(duì)象關(guān)系映射(ORM)是由Java中的Hibernate框架首創(chuàng)的。對(duì)象-關(guān)系映射的最初目標(biāo)是克服Java類和RDBMS表之間所謂的阻抗不匹配。從這個(gè)想法中產(chǎn)生了更廣泛的應(yīng)用程序通用持久層的概念。Prisma是Java ORM層的一個(gè)基于JavaScript的現(xiàn)代進(jìn)化。

Prisma支持一系列SQL數(shù)據(jù)庫(kù),并已擴(kuò)展到包括NoSQL數(shù)據(jù)存儲(chǔ)MongoDB。無(wú)論數(shù)據(jù)存儲(chǔ)的類型如何,它們的首要目標(biāo)都是:為應(yīng)用程序提供處理數(shù)據(jù)持久性的標(biāo)準(zhǔn)化框架。

域模型

以下將使用一個(gè)簡(jiǎn)單的域模型來(lái)查看數(shù)據(jù)模型中的幾種關(guān)系:多對(duì)一、一對(duì)多和多對(duì)多 (在這里忽略一對(duì)一,因?yàn)榕c多對(duì)一非常相似) 。

Prisma使用模型定義(模式)作為應(yīng)用程序和數(shù)據(jù)存儲(chǔ)之間的樞紐。在構(gòu)建應(yīng)用程序時(shí),將在這里采用的一種方法是從這個(gè)定義開始,然后從中構(gòu)建代碼。Prisma自動(dòng)將模式應(yīng)用于數(shù)據(jù)存儲(chǔ)。

Prisma模型定義格式不難理解,可以使用圖形工具Prismbuilder來(lái)創(chuàng)建一個(gè)模型。而模型將支持協(xié)作的想法開發(fā)應(yīng)用程序,因此將有用戶(User)、想法(Idea)和標(biāo)簽(Tag)模型。一個(gè)用戶可以有多個(gè)想法(一對(duì)多),為一個(gè)想法提供一個(gè)用戶,而所有者(Owner)則有多個(gè)想法(多對(duì)一)。想法和標(biāo)簽形成了多對(duì)多的關(guān)系。清單1顯示了模型定義。

清單1.Prisma中的模型定義

datasource db {
 provider = "sqlite"
 url = "file:./dev.db"
}
generator client {
 provider = "prisma-client-js"
}
model User {
 id Int @id @default(autoincrement())
 name String
 email String @unique
 ideas Idea[]
}
model Idea {
 id Int @id @default(autoincrement())
 name String
 description String
 owner User @relation(fields: [ownerId], references: [id])
 ownerId Int
 tags Tag[]
}
model Tag {
 id Int @id @default(autoincrement())
 name String @unique
 ideas Idea[]

清單1包括一個(gè)數(shù)據(jù)源定義(一個(gè)簡(jiǎn)單的SQLite數(shù)據(jù)庫(kù),Prisma為了開發(fā)目的將其包含在內(nèi))和一個(gè)客戶端定義,“生成器客戶端”設(shè)置為Prisma-client-js。后者意味著Prisma將生成一個(gè)JavaScript客戶端,應(yīng)用程序可以使用它與定義創(chuàng)建的映射進(jìn)行交互。

至于模型定義,需要注意每個(gè)模型都有一個(gè)id字段,并且正在使用Prisma @default(autoincrement())注釋來(lái)獲得一個(gè)自動(dòng)遞增的整數(shù)id。

為了創(chuàng)建從用戶(User)到想法(Idea)的關(guān)系,采用數(shù)組括號(hào)引用Idea類型:Idea[]。這句話的意思是:給一些用戶的想法。在關(guān)系的另一端,為想法(Idea)提供一個(gè)用戶(User): owner User @relation(字段:[ownerId],引用:[id])。

除了關(guān)系和鍵ID字段之外,字段定義也很簡(jiǎn)單;字符串對(duì)應(yīng)字符串,等等。

創(chuàng)建項(xiàng)目

在這里將使用一個(gè)簡(jiǎn)單的項(xiàng)目來(lái)使用Prisma的功能。第一步是創(chuàng)建一個(gè)新的Node.js項(xiàng)目并向其添加依賴項(xiàng)。之后,可以添加清單1中的定義,并使用它來(lái)處理Prisma內(nèi)置SQLite數(shù)據(jù)庫(kù)的數(shù)據(jù)持久性。

要啟動(dòng)應(yīng)用程序,將創(chuàng)建一個(gè)新目錄,初始化一個(gè)npm項(xiàng)目,并安裝依賴項(xiàng),如清單2所示。

清單2.創(chuàng)建應(yīng)用程序

mkdir iw-prisma
cd iw-prisma
npm init -y
npm install express @prisma/client body-parser
mkdir prisma
touch prisma/schema.prisma

現(xiàn)在,在prisma/schema上創(chuàng)建一個(gè)文件。并添加清單1中的定義。接下來(lái),告訴Prisma為SQLite準(zhǔn)備一個(gè)模式,如清單3所示。

清單3.設(shè)置數(shù)據(jù)庫(kù)

npx prisma migrate dev --name init
npx prisma migrate deploy

清單3告訴Prisma“遷移”數(shù)據(jù)庫(kù),這意味著將模式更改從Prisma定義應(yīng)用到數(shù)據(jù)庫(kù)本身。dev標(biāo)志告訴Prisma使用開發(fā)概要文件,而--name為更改提供了一個(gè)任意名稱。deploy標(biāo)志告訴prisma應(yīng)用更改。

使用數(shù)據(jù)

現(xiàn)在,允許在Express.js中使用RESTful端點(diǎn)創(chuàng)建用戶??梢栽谇鍐?中看到服務(wù)器的代碼,它位于inw -prisma/server.js文件中。清單4是普通的Express代碼,但是由于有了Prisma,可以用最少的精力對(duì)數(shù)據(jù)庫(kù)做很多工作。

清單4.Express代碼

const express = require('express');
const bodyParser = require('body-parser');
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
const app = express();
app.use(bodyParser.json());
const port = 3000;
app.listen(port, () => {
 console.log(`Server is listening on port ${port}`);
});
// Fetch all users
app.get('/users', async (req, res) => {
 const users = await prisma.user.findMany();
 res.json(users);
});
// Create a new user
app.post('/users', async (req, res) => {
 const { name, email } = req.body;
 const newUser = await prisma.user.create({ data: { name, email } });
 res.status(201).json(newUser);
});

目前,只有兩個(gè)端點(diǎn),/usersGET用于獲取所有用戶的列表,/userPOST用于添加它們。通過(guò)分別調(diào)用Prisma.user.findMany()和Prisma.uuser.create(),可以看到可以多么容易地使用Prisma客戶端來(lái)處理這些用例。

不帶任何參數(shù)的findMany()方法將返回?cái)?shù)據(jù)庫(kù)中的所有行。create()方法接受一個(gè)對(duì)象,該對(duì)象帶有一個(gè)數(shù)據(jù)字段,其中包含新行的值(在本例中是名稱和電子郵件—記住Prisma將自動(dòng)創(chuàng)建一個(gè)唯一的ID)。

現(xiàn)在可以使用:node server.js運(yùn)行服務(wù)器。

使用CURL進(jìn)行測(cè)試

以下使用CURL測(cè)試端點(diǎn),如清單5所示。

清單5.使用CURL嘗試端點(diǎn)

$ curl http://localhost:3000/users
[]
$ curl -X POST -H "Content-Type: application/json" -d '{"name":"George Harrison","email":"george.harrison@example.com"}' http://localhost:3000/users
{"id":2,"name":"John Doe","email":"john.doe@example.com"}{"id":3,"name":"John Lennon","email":"john.lennon@example.com"}{"id":4,"name":"George Harrison","email":"george.harrison@example.com"}
$ curl http://localhost:3000/users
[{"id":2,"name":"John Doe","email":"john.doe@example.com"},{"id":3,"name":"John Lennon","email":"john.lennon@example.com"},{"id":4,"name":"George Harrison","email":"george.harrison@example.com"}]

清單5顯示了獲取所有用戶并找到一個(gè)空集,然后添加用戶,再獲取填充的集。

接下來(lái)添加一個(gè)端點(diǎn),它允許創(chuàng)建想法并將它們與用戶關(guān)聯(lián)起來(lái),如清單6所示。

清單6. User ideas POST endpoint

app.post('/users/:userId/ideas', async (req, res) => {
 const { userId } = req.params;
 const { name, description } = req.body;
 try {
 const user = await prisma.user.findUnique({ where: { id: parseInt(userId) } });
 if (!user) {
 return res.status(404).json({ error: 'User not found' });
 }
 const idea = await prisma.idea.create({
 data: {
 name,
 description,
 owner: { connect: { id: user.id } },
 },
 });
 res.json(idea);
 } catch (error) {
 console.error('Error adding idea:', error);
 res.status(500).json({ error: 'An error occurred while adding the idea' });
 }
});
app.get('/userideas/:id', async (req, res) => {
 const { id } = req.params;
 const user = await prisma.user.findUnique({
 where: { id: parseInt(id) },
 include: {
 ideas: true,
 },
 });
 if (!user) {
 return res.status(404).json({ message: 'User not found' });
 }
 res.json(user);
});

在清單6中有兩個(gè)端點(diǎn)。第一個(gè)允許使用POST在/users/:userId/ideas添加一個(gè)想法。它需要做的第一件事是使用prism .user. findunique()通過(guò)ID恢復(fù)用戶。這個(gè)方法用于根據(jù)傳入的標(biāo)準(zhǔn)在數(shù)據(jù)庫(kù)中查找單個(gè)實(shí)體。在本例中,希望用戶具有來(lái)自請(qǐng)求的ID,因此使用:{where:{ID:prseInt(userId)}}。

一旦有了用戶,就使用prisma.idea.create來(lái)創(chuàng)建一個(gè)新的想法。這就像創(chuàng)建用戶時(shí)一樣,但現(xiàn)在有了一個(gè)關(guān)系字段。Prisma可以創(chuàng)建新想法和用戶之間的關(guān)聯(lián):owner:{connect:{id:user.id}}。

第二個(gè)端點(diǎn)是/userideas/:id的GET。這個(gè)端點(diǎn)的目的是獲取用戶ID并返回用戶,包括他們的想法??梢钥吹脚cfindUnique調(diào)用一起使用的where子句,以及include修飾符。這里使用修飾符來(lái)告訴Prisma包含相關(guān)的想法。如果沒(méi)有這一點(diǎn),就不會(huì)包含這些想法,因?yàn)镻risma默認(rèn)使用延遲加載關(guān)聯(lián)獲取策略。

要測(cè)試新的端點(diǎn),可以使用清單7中所示的CURL命令。

清單7.用于測(cè)試端點(diǎn)的CURL

$ curl -X POST -H "Content-Type: application/json" -d '{"name":"New Idea", "description":"Idea description"}' http://localhost:3000/users/3/ideas
$ curl http://localhost:3000/userideas/3
{"id":3,"name":"John Lennon","email":"john.lennon@example.com","ideas":[{"id":1,"name":"New Idea","description":"Idea description","ownerId":3},{"id":2,"name":"New Idea","description":"Idea description","ownerId":3}]}

能夠添加想法并用它們恢復(fù)用戶。

帶標(biāo)簽的多對(duì)多

現(xiàn)在添加端點(diǎn)來(lái)處理多對(duì)多關(guān)系中的標(biāo)簽。在清單8中,處理標(biāo)簽的創(chuàng)建,并將標(biāo)簽(Tag)和想法(Ideas)關(guān)聯(lián)起來(lái)。

清單8.添加和顯示標(biāo)簽

// create a tag
app.post('/tags', async (req, res) => {
 const { name } = req.body;
 try {
 const tag = await prisma.tag.create({
 data: {
 name,
 },
 });
 res.json(tag);
 } catch (error) {
 console.error('Error adding tag:', error);
 res.status(500).json({ error: 'An error occurred while adding the tag' });
 }
});
// Associate a tag with an idea
app.post('/ideas/:ideaId/tags/:tagId', async (req, res) => {
 const { ideaId, tagId } = req.params;
 try {
 const idea = await prisma.idea.findUnique({ where: { id: parseInt(ideaId) } });
 if (!idea) {
 return res.status(404).json({ error: 'Idea not found' });
 }
 const tag = await prisma.tag.findUnique({ where: { id: parseInt(tagId) } });
 if (!tag) {
 return res.status(404).json({ error: 'Tag not found' });
 }
 const updatedIdea = await prisma.idea.update({
 where: { id: parseInt(ideaId) },
 data: {
 tags: {
 connect: { id: tag.id },
 },
 },
 });
 res.json(updatedIdea);
 } catch (error) {
 console.error('Error associating tag with idea:', error);
 res.status(500).json({ error: 'An error occurred while associating the tag with the idea' });
 }
});

在這里增加了兩個(gè)端點(diǎn)。用于添加標(biāo)簽的POST端點(diǎn)與前面的示例很相似。在清單8中,還添加了POST端點(diǎn),用于將想法與標(biāo)簽關(guān)聯(lián)起來(lái)。

為了將一個(gè)想法(Idea)和一個(gè)標(biāo)簽(Tag)關(guān)聯(lián)起來(lái),利用了模型定義中的多對(duì)多映射。通過(guò)ID抓取想法和標(biāo)簽,并使用關(guān)聯(lián)(Connect)字段將它們相互聯(lián)系起來(lái)。現(xiàn)在,想法在它的標(biāo)簽集合中有標(biāo)簽ID,反之亦然。多對(duì)多關(guān)聯(lián)允許最多兩個(gè)一對(duì)多關(guān)系,每個(gè)實(shí)體指向另一個(gè)實(shí)體。在數(shù)據(jù)存儲(chǔ)中,這需要?jiǎng)?chuàng)建一個(gè)“查找表”(或交叉引用表),但Prisma會(huì)處理這個(gè)問(wèn)題,只需要與實(shí)體本身交互。

多對(duì)多特性的最后一步是允許通過(guò)標(biāo)簽找到想法,并在想法上找到標(biāo)簽。可以在清單9中看到模型的這一部分。(需要注意的是,為了簡(jiǎn)潔起見,刪除了一些錯(cuò)誤。)

清單9.通過(guò)想法找到標(biāo)簽,通過(guò)標(biāo)簽找到想法

// Display ideas with a given tag
app.get('/ideas/tag/:tagId', async (req, res) => {
 const { tagId } = req.params;
 try {
 const tag = await prisma.tag.findUnique({
 where: {
 id: parseInt(tagId)
 }
 });
 const ideas = await prisma.idea.findMany({
 where: {
 tags: {
 some: {
 id: tag.id
 }
 }
 }
 });
 res.json(ideas);
 } catch (error) {
 console.error('Error retrieving ideas with tag:', error);
 res.status(500).json({
 error: 'An error occurred while retrieving the ideas with the tag'
 });
 }
});
// tags on an idea:
app.get('/ideatags/:ideaId', async (req, res) => {
 const { ideaId } = req.params;
 try {
 const idea = await prisma.idea.findUnique({
 where: {
 id: parseInt(ideaId)
 }
 });
 const tags = await prisma.tag.findMany({
 where: {
 ideas: {
 some: {
 id: idea.id
 }
 }
 }
 });
 res.json(tags);
 } catch (error) {
 console.error('Error retrieving tags for idea:', error);
 res.status(500).json({
 error: 'An error occurred while retrieving the tags for the idea'
 });
 }
});

這里有兩個(gè)端點(diǎn):/ideas/tag/:tagId和/ideatags/:ideaId。它們的工作原理非常相似,可以為給定的標(biāo)簽ID找到想法。從本質(zhì)上來(lái)說(shuō),查詢就像一對(duì)多關(guān)系中的查詢一樣,Prisma處理查找表的遍歷。例如,為了找到一個(gè)想法的標(biāo)簽,可以使用tag.findMany 方法,其中有一個(gè)where子句查找具有相關(guān)ID的想法,如清單10所示。

清單10.測(cè)試標(biāo)簽概念的多對(duì)多關(guān)系

$ curl -X POST -H "Content-Type: application/json" -d '{"name":"Funny Stuff"}' http://localhost:3000/tags
$ curl -X POST http://localhost:3000/ideas/1/tags/2
{"idea":{"id":1,"name":"New Idea","description":"Idea description","ownerId":3},"tag":{"id":2,"name":"Funny Stuff"}}
$ curl localhost:3000/ideas/tag/2
[{"id":1,"name":"New Idea","description":"Idea description","ownerId":3}]
$ curl localhost:3000/ideatags/1
[{"id":1,"name":"New Tag"},{"id":2,"name":"Funny Stuff"}]

結(jié)論

雖然在這里涉及一些CRUD和關(guān)系基礎(chǔ)知識(shí),但Prisma的能力遠(yuǎn)不止于此。它提供了級(jí)聯(lián)操作(如級(jí)聯(lián)刪除)、獲取策略(允許微調(diào)從數(shù)據(jù)庫(kù)返回對(duì)象的方式)、事務(wù)、查詢和篩選API等功能。Prisma還允許根據(jù)模型遷移數(shù)據(jù)庫(kù)模式。此外,它通過(guò)在框架中抽象所有數(shù)據(jù)庫(kù)客戶機(jī)工作,使應(yīng)用程序與數(shù)據(jù)庫(kù)無(wú)關(guān)。

Prisma以定義和維護(hù)模型定義為代價(jià),為用戶提供了許多便利和功能。因此人們很容易理解這個(gè)用于JavaScript的ORM工具是開發(fā)人員一個(gè)熱門選擇的原因。

原文標(biāo)題:Prisma.js:Code-first ORM in JavaScript,作者:Matthew Tyson


分享名稱:Prisma.js:JavaScript中的代碼優(yōu)先ORM
URL分享:http://m.5511xx.com/article/dhchcgi.html