ããã¯ããªã«ãããããŠæžãããã®ïŒ
Node.jsïŒTypeScriptç°å¢ã§ã®ORMã¯ã©ãã䜿ã£ããããã®ããªïŒãšããããšã§ã
ãã®ãããã¿ããã§ãã
- Sequelize | Sequelize ORM
- v5以éãTypeScriptããµããŒã
- TypeORM - Amazing ORM for TypeScript and JavaScript (ES7, ES6, ES5). Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, WebSQL databases. Works in NodeJS, Browser, Ionic, Cordova and Electron platforms.
- Prisma - Next-generation Node.js and TypeScript ORM for Databases
- Knex.js - A SQL Query Builder for Javascript
æ å ±ãèŠãŠãããšãNode.jsç°å¢ã§ã¯Sequelizeãæåã ãšæããŸãããTypeScriptã§äœ¿ãå Žåã¯TypeORMãPrismaãéžã¶ããã§ãã
ä»åã¯ãPrismaã䜿ã£ãŠã¿ãããšæããŸãã
Prisma
Prismaã¯ã次äžä»£ã®Node.jsãšTypeScriptã®ORMãšè¬³ã£ãŠããŸãã
Prisma - Next-generation Node.js and TypeScript ORM for Databases
ãµããŒãããŠããããŒã¿ããŒã¹ã¯ã以äžã§ãã
- MySQL
- PostgreSQL
- Microsoft SQL Server
- SQLite
- MongoDBïŒPreviewïŒ
Prismaãšã¯ãªã«ãïŒãšããã®ã¯ããã¡ãã«æžãããŠããŸãã
What is Prisma? (Overview) | Prisma Docs
äž»ã«ä»¥äžã®3ã€ã§æ§æãããŠããã¿ããã§ãã
- ã¿ã€ãã»ãŒããªã¯ã©ã€ã¢ã³ãïŒPrisma ClientïŒ
- ãã€ã°ã¬ãŒã·ã§ã³ïŒPrisma MigrateïŒ
- ããŒã¿ããŒã¹ãã©ãŠã¶ïŒPrisma StudioïŒ
ãŸãããã¬ãã¥ãŒã§ããPrisma Data Platformãšãããã®ãããããã¡ãã¯æåéããã©ãããã©ãŒã ãµãŒãã¹ã®
ããã§ãäžèšãšã¯ãŸãæ§æ Œãç°ãªãããã§ãã
Prismaã®ãããã®ããŒã«ããPrisma schemaãšãããã®ãèµ·ç¹ã«ãªãããã§ãã
Prisma schema (Reference) | Prisma Docs
Prisma schemaã«ã¯ã以äžãå®çŸ©ãããŸãã
- ããŒã¿ãœãŒã¹ïŒããŒã¿ããŒã¹æ¥ç¶èšå®ïŒ
- ãžã§ãã¬ãŒã¿ãŒïŒPrisma Clientã®çæïŒ
- ããŒã¿ã¢ãã«ïŒã¢ããªã±ãŒã·ã§ã³ã¢ãã«ïŒã®å®çŸ©
ãã®Prisma schemaã®ååšããä»ã®ORMãšå€§ããç°ãªããã®ã¿ããã§ããããšãã°ãTypeORMã§ã¯ããŒã¿ã¢ãã«ã®å®çŸ©ã«TypeScriptã®
ãã³ã¬ãŒã¿ãŒã䜿çšããŸãã
Prismaèªèº«ã®ããã¥ã¡ã³ãããã§ããããªãPrismaãè¯ãã®ãïŒãšããã®ã¯ãã¡ããèŠããšããã¿ããã§ãã
Why Prisma? Comparison with SQL query builders & ORMs | Prisma Docs
Should you use Prisma as a Node.js/TypeScript ORM? | Prisma Docs
Prismaèªèº«ã«ãããä»ã®ORMãšã®æ¯èŒã¯ãã¡ãã«èšèŒãããŠããŸãã
Comparing Prisma to other ORMs and ODMs. | Prisma Docs
Best 11 ORMs for Node.js, Query Builders & Database Libraries in 2021
ä»åã¯ããŸãã¯Prisma Clientãäžå¿ã«èŠãŠãããããªãšæããŸãã
Prisma Client
Prisma Clientã¯ãèªåçæããããåå®å šãªã¯ãšãªãŒãã«ããŒã§ãã
Prisma Client - Auto-generated query builder for your data
Goåãã®ãã®ããããŸãããããã¡ã³ããã³ã¹ãããªãããã§ããã
æ©èœã¯ïŒãšãããšãããã¥ã¡ã³ãã®é ç®ãèŠãæ¹ãæ©ããã§ããã
Prisma Client (Reference) | Prisma Docs
ãŸãã¯ããã¡ãã®ã¹ã¯ã©ããã§å§ããGetting Startedã§è©ŠããŠãããããšæããŸãã
Start from scratch with relational databases (15 min) | Prisma Docs
ãªãQuick Startã¯ãGitHubãªããžããªãããŒã¹ã«é²ããŠããããã§ãã
Quickstart: Getting started with TypeScript & SQLite | Prisma Docs
GitHub - prisma/quickstart: 🏁 Starter templates for the 5min Quickstart in the Prisma docs.
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã§ãã
$ node --version v16.13.2 $ npm --version 8.1.2
ããŒã¿ããŒã¹ã¯MySQLã䜿çšããŸãã
ããŒãžã§ã³ã¯8.0.27ã§ã172.17.0.2ã§åäœããŠãããã®ãšããŸãã
ã¡ãªã¿ã«ãäŸåé¢ä¿ã«ã€ããŠã¯æçµçã«ã¯ãããªããŸããã
"devDependencies": { "@types/jest": "^27.4.0", "@types/node": "^16.11.20", "esbuild": "^0.14.11", "esbuild-jest": "^0.5.0", "jest": "^27.4.7", "prettier": "2.5.1", "prisma": "^3.8.1", "ts-node": "^10.4.0", "typescript": "^4.5.4" }, "dependencies": { "@prisma/client": "^3.8.1" }
ã»ããã¢ãã
ãŸãã¯ããã¡ãã®æé ã«åŸã£ãŠãããžã§ã¯ããã»ããã¢ããããŠãããŸãããã
Start from scratch with relational databases (15 min) | Prisma Docs
$ npm init -y $ npm i -D prisma typescript ts-node @types/node@v16
ããã§ã€ã³ã¹ããŒã«ããprisma
ãšããããã±ãŒãžã¯ãPrisma CLIã§ããã
$ npx prisma --version prisma : 3.8.1 @prisma/client : Not found Current platform : debian-openssl-1.1.x Query Engine (Node-API) : libquery-engine 34df67547cf5598f5a6cd3eb45f14ee70c3fb86f (at node_modules/@prisma/engines/libquery_engine-debian-openssl-1.1.x.so.node) Migration Engine : migration-engine-cli 34df67547cf5598f5a6cd3eb45f14ee70c3fb86f (at node_modules/@prisma/engines/migration-engine-debian-openssl-1.1.x) Introspection Engine : introspection-core 34df67547cf5598f5a6cd3eb45f14ee70c3fb86f (at node_modules/@prisma/engines/introspection-engine-debian-openssl-1.1.x) Format Binary : prisma-fmt 34df67547cf5598f5a6cd3eb45f14ee70c3fb86f (at node_modules/@prisma/engines/prisma-fmt-debian-openssl-1.1.x) Default Engines Hash : 34df67547cf5598f5a6cd3eb45f14ee70c3fb86f Studio : 0.452.0
tsconfig.json
ã¯ããã®ããã«èšå®ã
tsconfig.json
{ "compilerOptions": { "target": "esnext", "module": "commonjs", "lib": ["esnext"], "baseUrl": "./src", "outDir": "dist", "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "noImplicitOverride": true, "noImplicitReturns": true, "noPropertyAccessFromIndexSignature": true, "esModuleInterop": true }, "include": [ "src" ] }
prisma init
ãå®è¡ããŠã¿ãŸãã
$ npx prisma init
prisma/schema.prisma
ãšãããã¡ã€ã«ãã§ããããã§ãã
â Your Prisma schema was created at prisma/schema.prisma You can now open it in your favorite editor. Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started 2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlite, sqlserver or mongodb (Preview). 3. Run prisma db pull to turn your database schema into a Prisma schema. 4. Run prisma generate to generate the Prisma Client. You can then start querying your database. More information in our documentation: https://pris.ly/d/getting-started
ãã®ãããªãã¡ã€ã«ãçæãããŸãã
prisma/schema.prisma
// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") }
PostgreSQLåãã®èšå®ãåºåãããŠããŸãã
schema.prismaãä¿®æ£ãã
ããã¥ã¡ã³ãã«æ²¿ã£ãŠãçæãããschema.prisma
ãä¿®æ£ããŠãããŸãã
Connect your database | Prisma Docs
ãŸãã¯provider
ãä¿®æ£ã
datasource db { provider = "mysql" url = env("DATABASE_URL") }
env
ãšããã®ã¯ç°å¢å€æ°ãåç
§ããä»çµã¿ã®ããã§ãã
Environment variables | Prisma Docs
OSåŽã®ç°å¢å€æ°ãåç
§ããŸããã.env
ãšãããã¡ã€ã«ãããã«ãã¯ã¢ããã§ããŸãããã®ãã¡ã€ã«ã¯ãå®ã¯prisma init
ã®æç¹ã§ãããžã§ã¯ãã®
ã«ãŒããã£ã¬ã¯ããªã«çæãããŠããŸãã
.env
# Environment variables declared in this file are automatically made available to Prisma. # See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server and MongoDB (Preview). # See the documentation for all the connection string options: https://pris.ly/d/connection-strings DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
.env
ãã¡ã€ã«ã¯ãããã€ãæ¢çŽ¢ããã«ãŒã«ããããŸãã
Environment variables / Using .env files
ãã ã.env
ãã¡ã€ã«ã¯ããŒãžã§ã³ç®¡çã·ã¹ãã ã«ã³ãããããŠã¯ãªããªããšãããŠããŠã以äžã®å
容ã®.gitignore
ãã¡ã€ã«ãåæã«çæ
ãããŠããŸãã
.gitignore
node_modules # Keep environment variables out of version control .env
ã§ã¯ãçšæããMySQLã«æ¥ç¶ã§ããããã«DATABASE_URL
ãä¿®æ£ããŸãã
.env
# Environment variables declared in this file are automatically made available to Prisma. # See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server and MongoDB (Preview). # See the documentation for all the connection string options: https://pris.ly/d/connection-strings DATABASE_URL="mysql://appuser:password@172.17.0.2:3306/example"
Connection URLã®èšè¿°ã«ã€ããŠã¯ããã¡ããåç §ã
Connection URLs (Reference) | Prisma Docs
次ã«ããã¡ããåç §ããªããããŒã¿ã¢ãã«ãæžããŠãããŸãã
Prisma schema (Reference) | Prisma Docs
Data model (Reference) | Prisma Docs
Relations (Reference) | Prisma Docs
Names in the underlying database | Prisma Docs
ã€ã³ããã¯ã¹ã®å®çŸ©ã«ã€ããŠã¯ããã¬ãã¥ãŒæ©èœã®ããã§ãã
æçµçã«ã§ãããã£ããã¡ã€ã«ã¯ããã¡ãã
prisma/schema.prisma
// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = env("DATABASE_URL") } model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) url String @unique user User @relation(fields: [userId], references: [id]) userId Int @map("user_id") @@map("post") } model User { id Int @id @default(autoincrement()) name String @db.VarChar(30) age Int posts Post[] @@map("user") }
@
ã®éšåã¯å±æ§ã§ãã ãããæå³ã¯äºæ³ãã€ãæ°ã¯ããŸããã詳ããã¯ãªãã¡ã¬ã³ã¹ã«æžãããŠããŸãã
Prisma schema API (Reference) | Prisma Docs
ããã§Prisma Migrateã䜿ã£ãŠãã€ã°ã¬ãŒã·ã§ã³ããŸãã
$ npx prisma migrate dev --name init
Prisma Migrateã®ããã¥ã¡ã³ãã¯ããã¡ãã
Prisma Migrate | Database, Schema, SQL Migration Tool | Prisma Docs
dev
ãšããã®ã¯éçºã³ãã³ãã®ããšã§ãæ¬çªç°å¢ã§ã®å©çšã¯æ³å®ããŠããŸããã--name
ã®åŸã«ã¯ä»»æã®ååãæå®ãããã€ã°ã¬ãŒã·ã§ã³ã®ååã«
åæ ãããããã§ãã--name
ã®å€ã¯ãŠããŒã¯ã§ããå¿
èŠã¯ãªãããã§ãã
â»æ¬çªç°å¢åãã«ã¯deploy
ãšããã³ãã³ãã䜿ãããã§ã
ã¡ãªã¿ã«ãprisma migrate dev
ã®æç¹ã§ããŒã¿ããŒã¹ã«æ¥ç¶ãããããªã®ã§ããããããã管çè
æš©éã®ãªããŠãŒã¶ãŒã ãšãšã©ãŒã«
ãªããŸãããã°ããŒãã«ã«ããŒã¿ããŒã¹ãæäœã§ããå¿
èŠãããããã§ãã
Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma Datasource "db": MySQL database "example" at "172.17.0.2:3306" Error: P3014 Prisma Migrate could not create the shadow database. Please make sure the database user has permission to create databases. Read more about the shadow database (and workarounds) at https://pris.ly/d/migrate-shadow Original error: Error code: P1010 User `appuser` was denied access on the database `example`
æš©éèšå®ãããªãããŠããã1床å®è¡ã
$ npx prisma migrate dev --name init Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma Datasource "db": MySQL database "example" at "172.17.0.2:3306" MySQL database example created at 172.17.0.2:3306 Applying migration `20220118133834_init` The following migration(s) have been created and applied from new schema changes: migrations/ ââ 20220118133834_init/ ââ migration.sql Your database is now in sync with your schema. â Generated Prisma Client (3.8.1 | library) to ./node_modules/@prisma/client in 615ms
察象ã®ããŒã¿ããŒã¹ãååšããªãå Žåã¯ãäœæããããã§ãã
ä»åºŠã¯ããŸãããã以äžã®ãããªãã¡ã€ã«ãçæãããŸããã
$ tree prisma prisma âââ migrations â  âââ 20220118133834_init â  â  âââ migration.sql â  âââ migration_lock.toml âââ schema.prisma 2 directories, 3 files
çæãããSQLãã¡ã€ã«ã
prisma/migrations/20220118133834_init/migration.sql
-- CreateTable CREATE TABLE `post` ( `id` INTEGER NOT NULL AUTO_INCREMENT, `title` VARCHAR(255) NOT NULL, `url` VARCHAR(191) NOT NULL, `user_id` INTEGER NOT NULL, UNIQUE INDEX `post_url_key`(`url`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `user` ( `id` INTEGER NOT NULL AUTO_INCREMENT, `name` VARCHAR(30) NOT NULL, `age` INTEGER NOT NULL, PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- AddForeignKey ALTER TABLE `post` ADD CONSTRAINT `post_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
Collationãutf8mb4_unicode_ci
åºå®ã«ãªã£ãŠããã®ãæ°ã«ãªãã®ã§ããïŒäœ¿ã£ãŠãããµãŒããŒã®èšå®ã¯å¥ã®CollationïŒãããã¯Prismaã§ã¯
å€æŽã§ããªãããã§ãã
å
éšã§äœ¿ã£ãŠããMariaDBã®ãã©ã€ããŒã®ããã©ã«ãããutf8mb4_unicode_ci
ã§ããããšã«èµ·å ããŠããã§ããã
ããã²ãšã€ã®ãã¡ã€ã«ã«ã¯ãProviderã®æ å ±ãæžãããŠããŸããã
prisma/migrations/migration_lock.toml
# Please do not edit this file manually # It should be added in your version-control system (i.e. Git) provider = "mysql"
ãŸããnode_modules/.prisma
ãã£ã¬ã¯ããªã«ã¯ãå宣èšãªã©ãçæããããã¡ããããã°ã©ã ã®äœæã«å©çšã§ããŸãã
$ tree node_modules/.prisma node_modules/.prisma âââ client âââ index-browser.js âââ index.d.ts âââ index.js âââ libquery_engine-debian-openssl-1.1.x.so.node âââ package.json âââ schema.prisma 1 directory, 6 files
ãããŠãããŒãã«ããã®æç¹ã§äœæãããŠããŸãã
mysql> use example; Database changed mysql> show tables; +--------------------+ | Tables_in_example | +--------------------+ | _prisma_migrations | | post | | user | +--------------------+ 3 rows in set (0.00 sec)
_prisma_migrations
ãšããããŒãã«ã¯ããã€ã°ã¬ãŒã·ã§ã³ã®å±¥æŽã®ããã§ãã
mysql> select * from _prisma_migrations; +--------------------------------------+------------------------------------------------------------------+-------------------------+---------------------+------+----------------+-------------------------+---------------------+ | id | checksum | finished_at | migration_name | logs | rolled_back_at | started_at | applied_steps_count | +--------------------------------------+------------------------------------------------------------------+-------------------------+---------------------+------+----------------+-------------------------+---------------------+ | f9c4ddb8-cc8e-4353-a550-3684530697b0 | 11b11399bfa8bbd1c555a1548b87ea473d8eac9aa23aaee3c12cb6e14fcb3e83 | 2022-01-18 13:38:35.440 | 20220118133834_init | NULL | NULL | 2022-01-18 13:38:34.679 | 1 | +--------------------------------------+------------------------------------------------------------------+-------------------------+---------------------+------+----------------+-------------------------+---------------------+ 1 row in set (0.00 sec)
ããæžããšPrismaã䜿ããšãæ°èŠã«ããŒã¿ããŒã¹ãäœãå Žåã§ãªããšäœ¿ããªãã®ããªïŒãšãæãã®ã§ãããæ¢åã®ãããžã§ã¯ãã«å¯ŸããŠã
é©çšã§ããããã§ãããã®ãã¿ãŒã³ã¯ããã¡ããåç
§ã
Add Prisma to an existing project that uses a relational database (15 min) | Prisma Docs
Prisma Clientã䜿ã
ã§ã¯ãçæãããå宣èšã䜿ã£ãŠããã°ã©ã ãæžããŠãããŸããããããã¥ã¡ã³ãã¯ããã¡ãã足ãããã«ã
Install Prisma Client | Prisma Docs
Prisma Clientãã€ã³ã¹ããŒã«ããŸãã
$ npm i @prisma/client
確èªã¯ããã¹ãã³ãŒãã§è¡ãããšã«ããŸããJestãã€ã³ã¹ããŒã«ãããšãPrettierãã
$ npm i -D jest @types/jest esbuild-jest esbuild $ npm i -D -E prettier
èšå®ã¯ãããªæãã§ãã
jest.config.js
module.exports = { testEnvironment: 'node', transform: { "^.+\\.tsx?$": "esbuild-jest" } };
.prettierrc.json
{ "singleQuote": true }
ããšã¯ããã¹ãçšã®ãã£ã¬ã¯ããªã«ãã¹ããäœæããŠãããŸãã
$ mkdir test
ãŸãã¯ã宣èšéšåã ãã
test/prisma.test.ts
import { Prisma, PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); // ããã«ããã¹ããæžãïŒ
ããšã¯Getting Startedãš
Querying the database | Prisma Docs
Prisma Clientã®ããã¥ã¡ã³ããèŠãªãããã¹ãã³ãŒããæžããŠãããŸãã
Prisma Client (Reference) | Prisma Docs
ããŒã¿ã®ç»é²ã
CRUD (Reference) | Prisma Docs
test('insert data', async () => { const katsuo = await prisma.user.create({ data: { name: '磯é ã«ããª', age: 11, posts: { create: [ { title: 'ã¯ãããŠã®TypeScriptïŒïŒTypeScript ESLintãPrettierãEmacs lsp-modeïŒ', url: 'https://kazuhira-r.hatenablog.com/entry/2021/10/30/222106', }, { title: 'Jestã§TypeScriptã®ãã¹ããæžã', url: 'https://kazuhira-r.hatenablog.com/entry/2021/10/31/173852', }, { title: 'TypeScriptã§Express', url: 'https://kazuhira-r.hatenablog.com/entry/2021/11/20/184345', }, ], }, }, }); expect(katsuo.name).toBe('磯é ã«ããª'); expect(katsuo.age).toBe(11); const wakame = await prisma.user.create({ data: { name: '磯é ã¯ã«ã¡', age: 9, }, }); expect(wakame.name).toBe('磯é ã¯ã«ã¡'); expect(wakame.age).toBe(9); const createdPosts = await prisma.post.createMany({ data: [ { title: 'Node.jsã®ç®¡çããŒã«ãnvmãã€ã³ã¹ããŒã«ãã', url: 'https://kazuhira-r.hatenablog.com/entry/2021/03/22/223042', userId: wakame.id, }, { title: 'Node.jsã¢ããªã±ãŒã·ã§ã³ã®ãã°åºåã«ãwinstonã䜿ã£ãŠã¿ã', url: 'https://kazuhira-r.hatenablog.com/entry/2019/05/21/235843', userId: wakame.id, }, ], }); expect(createdPosts.count).toBe(2); }); test('search single data', async () => { const katsuo = await prisma.user.findFirst({ where: { name: '磯é ã«ããª' }, }); expect(katsuo?.age).toBe(11); const katsuo2 = await prisma.user.findUnique({ where: { id: katsuo?.id } }); expect(katsuo2).not.toBeNull(); });
䜿ããšã¡ãã£ãšé©ãã®ã§ãããfindUnique
ã¯è£å®åè£ã«ãŠããŒã¯ãªãã®ïŒäž»ããŒãªã©ïŒããçŸããªãããã«ãªã£ãŠããŸãã
ãããã§ããã
ãªã¬ãŒã·ã§ã³ã®ããã¬ã³ãŒããåŸããè¿œå ãããã¿ãŒã³ãè¡ã£ãŠããŸãããæ°èŠããŒã¿ãç»é²ããéã«connect
ããã°é¢é£ä»ããã§ããããã§ãã
â»ä»åã¯æå³çã«post
ãå
ã«äœã£ãŠããŸã£ãã®ã§connect
ã¯è¡ã£ãŠããŸããããuser
ããäœæããã°OKã§ã
Relation queries (Concepts) | Prisma Docs
1件æ€çŽ¢ã
test('search single data', async () => { const katsuo = await prisma.user.findFirst({ where: { name: '磯é ã«ããª' }, }); expect(katsuo?.age).toBe(11); const katsuo2 = await prisma.user.findUnique({ where: { id: katsuo?.id } }); expect(katsuo2).not.toBeNull(); });
ãªã¬ãŒã·ã§ã³ã®ããæ€çŽ¢ããœãŒããå ¥ããŠããŸãã
Relation queries (Concepts) | Prisma Docs
Filtering and sorting (Concepts) | Prisma Docs
test('search related data', async () => { const katsuo = await prisma.user.findFirst({ where: { name: '磯é ã«ããª' }, include: { posts: true }, }); expect(katsuo?.age).toBe(11); const katsuoIncludePosts = await prisma.user.findUnique({ where: { id: katsuo?.id }, include: { posts: { orderBy: { url: 'desc' } } }, }); expect(katsuoIncludePosts?.posts).toHaveLength(3); expect(katsuoIncludePosts?.posts[0].title).toBe('TypeScriptã§Express'); expect(katsuoIncludePosts?.posts[0].url).toBe( 'https://kazuhira-r.hatenablog.com/entry/2021/11/20/184345' ); });
ãã©ã³ã¶ã¯ã·ã§ã³ã¯ãxxxMany
ããããæŽæ°çãªæ±ãã«ãªãããã§ããã$transaction
ã䜿ãããšã§Promiseããã©ã³ã¶ã¯ã·ã§ã³ãšããŠ
ãŸãšããããšãã§ããããã§ãã
Transactions and batch queries (Reference) | Prisma Docs
$transaction
ã䜿ãå Žåã¯ã倱æããPromiseããããšããŒã«ããã¯ããããã§ãã
ããŒã«ããã¯ãããã¿ãŒã³ãçæ¹ã®Promiseã¯ããŠããŒã¯ããŒãéè€ãããã¬ã³ãŒããç»é²ããŠå€±æãããŸãã
test('transaction rollback', async () => { const katsuo = await prisma.user.findFirst({ where: { name: '磯é ã«ããª' }, }); if (katsuo) { const currentCount = await prisma.post.count(); expect(currentCount).toBe(5); try { const [post1, post2] = await prisma.$transaction([ prisma.post.create({ data: { title: 'TypeScriptïŒNode.jsã§ãEcho ServerïŒClientãæžããŠã¿ã', url: 'https://kazuhira-r.hatenablog.com/entry/2021/11/20/222927', userId: katsuo.id, }, }), prisma.post.create({ data: { title: 'TypeScriptã§Express', url: 'https://kazuhira-r.hatenablog.com/entry/2021/11/20/184345', userId: katsuo.id, }, }), ]); const rollbackedCount = await prisma.post.count(); expect(rollbackedCount).toBe(5); } catch (e) { expect((e as Error).message).toContain( 'Unique constraint failed on the constraint: `post_url_key`' ); } } else { throw new Error('katsuo is null'); } });
ã³ããããããã¿ãŒã³ã
test('transaction commit', async () => { const katsuo = await prisma.user.findFirst({ where: { name: '磯é ã«ããª' }, }); if (katsuo) { const currentCount = await prisma.post.count(); expect(currentCount).toBe(5); const [post1, post2] = await prisma.$transaction([ prisma.post.create({ data: { title: 'TypeScriptïŒNode.jsã§ãEcho ServerïŒClientãæžããŠã¿ã', url: 'https://kazuhira-r.hatenablog.com/entry/2021/11/20/222927', userId: katsuo.id, }, }), prisma.post.create({ data: { title: 'TypeScriptïŒNode.jsãããžã§ã¯ããèªåãã«ãããïŒ--watchãnodemonïŒts-nodeïŒ', url: 'https://kazuhira-r.hatenablog.com/entry/2021/11/28/221448', userId: katsuo.id, }, }), ]); const committedCount = await prisma.post.count(); expect(committedCount).toBe(7); } else { throw new Error('katsuo is null'); } });
æåŸã«ãããŒã¿ãåé€ã
test('delete data', async () => { const deletedPosts = await prisma.post.deleteMany(); const deletedUsers = await prisma.user.deleteMany(); expect(deletedPosts.count).toBe(7); expect(deletedUsers.count).toBe(2); });
ãšããããããããªãšããã§ããããã
ãŸãšã
TypeScriptã®ORMã§ãããPrismaãè©ŠããŠã¿ãŸããã
è£å®ãããªã匷åã§ãå宣èšãschema.prisma
ããçæããŠããããããã¯ãšãªãŒã®ãã©ã¡ãŒã¿ã«æå®ãããªããžã§ã¯ãã®å
容ãã»ãŒè£å®ã§ããŸãã
ããã«ã¯é©ããŸããã
äžæ¹ã§ãschema.prisma
ããšã£ã€ãã«ãããšãããããã€ãã£ããªSQLããã¯ã§ããªããªã£ãŠããããšããã£ããããã®ã§ãã¡ãã£ãšåŸ®åŠãª
æããããŸãâŠã
ã¡ãã£ãšç¬èªã®äžç芳ã匷ããããªå°è±¡ãªã®ã§ãããã©ããªã®ã§ãããã䜿ãã®ãPrismaã ããªããåé¡ãªãã®ããªããšãã
æè¿ã¯Prismaã人æ°ãããã®ã§ãPrismaãæ±ã£ããçµããã«ãããããšæã£ãŠããã®ã§ããã1床TypeORMãè©ŠããŠæèŠãæŽãã§ã¿ããããªïŒ
ãšããæ°åã«ãªããŸããã