Sinh khối model cho schema.prisma từ một bản ghi JSON mẫu
Công cụ đọc JSON mẫu rồi dựng một khối model theo cú pháp của file schema.prisma, gợi ý kiểu String, Int, Float, Boolean, DateTime hoặc Json cho từng trường và tự đặt khóa chính khi thấy trường id. Đây là bước gõ lặp đầu tiên khi khai báo model; phần quan hệ giữa các model, index và thuộc tính ánh xạ xuống cột vẫn cần bạn tự viết thêm.
Tính năng nổi bật
- Dựng khối model đúng cú pháp Prisma từ danh sách trường của một object JSON
- Suy kiểu vô hướng: chuỗi ra String, số nguyên ra Int, số thập phân ra Float, true/false ra Boolean
- Nhận diện chuỗi bắt đầu bằng dạng ngày YYYY-MM-DD và gợi ý kiểu DateTime thay vì String
- Trường mảng hoặc object lồng nhau được quy về kiểu Json, kiểu Prisma dùng cho dữ liệu phi cấu trúc
- Thấy trường tên id là tự viết luôn dòng id Int @id @default(autoincrement())
- Trường mang giá trị null trong mẫu được đánh dấu tùy chọn bằng dấu chấm hỏi sau kiểu
- Tên trường tự chuyển sang camelCase theo quy ước đặt tên của Prisma, tên model tự chuyển sang PascalCase
- Dán vào một mảng thì lấy object đầu tiên làm mẫu, JSON hỏng thì hiện đúng thông báo lỗi phân tích
Phần gõ lặp khi khai báo model chiếm nhiều thời gian hơn phần thiết kế
Khi dựng lớp dữ liệu cho một dự án, thứ tốn công không phải là quyết định kiến trúc mà là ngồi gõ từng dòng field cho một bảng ba mươi cột, canh đúng tên, đúng kiểu, đúng dấu chấm hỏi. Trong khi đó bạn thường đã có sẵn một bản ghi JSON: response mẫu của API cần đồng bộ, dữ liệu seed, payload mà phía giao diện đang gửi lên, hoặc một dòng xuất ra từ hệ thống cũ. Bản ghi đó chứa đúng danh sách trường và đủ manh mối để đoán kiểu vô hướng. Công cụ này chuyển bản ghi thành khối model để bạn có ngay khung xương dán vào schema.prisma, sau đó dành thời gian cho phần thật sự cần đầu não: model này quan hệ với model nào, quan hệ một nhiều hay nhiều nhiều, xóa bản ghi cha thì bản ghi con xử lý ra sao, truy vấn nào chạy nhiều đủ để cần index. Cách làm này cũng hữu ích khi cả nhóm đang bàn mô hình dữ liệu: có một bản nháp cụ thể trên màn hình luôn dễ tranh luận hơn là bàn suông, và sửa một khối model có sẵn nhanh hơn viết từ trang trắng.
Lợi ích khi sử dụng
- Có khung model đủ trường trong vài giây thay vì gõ tay từng dòng cho bảng nhiều cột
- Kiểu vô hướng được điền sẵn nên bạn chỉ phải sửa vài trường đặc biệt thay vì điền toàn bộ
- Trường id được đặt khóa chính sẵn theo mẫu thông dụng nhất của Prisma
- Có bản nháp cụ thể để cả nhóm soi và bàn mô hình dữ liệu thay vì bàn suông
- Hữu ích khi phải dựng model theo một API bên ngoài mà tài liệu mô tả sơ sài
- Chạy trong trình duyệt, không cần cài Prisma CLI chỉ để xem thử một model trông ra sao
Từ JSON mẫu tới một model dán được vào schema.prisma
- 1Dán một bản ghi JSON đại diện vào ô bên trái, ưu tiên bản ghi có giá trị ở mọi trường để công cụ không phải đoán từ null.
- 2Gõ tên model vào ô phía trên theo lối số ít như User, Order, Invoice; công cụ tự chuyển về PascalCase đúng quy ước Prisma.
- 3Đối chiếu từng dòng kết quả: kiểm tra kiểu vô hướng có hợp không, trường tiền tệ có đang bị gán Float không, trường ngày có ra DateTime không.
- 4Sao chép khối model rồi dán vào file prisma/schema.prisma của dự án, đặt sau khối datasource và generator đã có sẵn.
- 5Viết thêm phần công cụ không đoán được: quan hệ tới model khác, @unique, @@index, @updatedAt, thuộc tính @map nếu tên cột trong cơ sở dữ liệu khác tên trường.
- 6Chạy prisma format để căn lại cột, rồi prisma validate và tạo migration trên môi trường phát triển trước khi đụng tới dữ liệu thật.
Cách công cụ đoán kiểu và vì sao Float hầu như luôn sai với tiền
Quy tắc suy kiểu ở đây ngắn gọn: chuỗi ra String trừ khi nó bắt đầu bằng dạng ngày YYYY-MM-DD thì thành DateTime; số nguyên ra Int, số có phần thập phân ra Float; true và false ra Boolean; còn mảng, object và mọi thứ còn lại đều quy về Json. Trường nào đang mang giá trị null trong mẫu thì được thêm dấu chấm hỏi để thành tùy chọn. Chỗ cần sửa tay nhiều nhất là Float. Prisma ánh xạ Float xuống kiểu dấu phẩy động của cơ sở dữ liệu, và dấu phẩy động không biểu diễn chính xác được các số thập phân thông thường, nên cộng dồn tiền theo kiểu này sẽ lệch dần từng đồng cho tới lúc báo cáo không khớp. Với tiền, giá, thuế, tỷ lệ chiết khấu, hãy đổi sang Decimal và khai báo độ chính xác qua thuộc tính native, ví dụ Decimal @db.Decimal(12, 2). Điểm thứ hai cần soi là Int: số căn cước, số điện thoại, mã số thuế trông như số nhưng phải để String vì chúng có thể bắt đầu bằng số không và không bao giờ đem ra cộng trừ. Điểm thứ ba là Int có giới hạn khoảng hai tỷ, nên khóa của bảng ghi log lớn hoặc số byte nên dùng BigInt. Cuối cùng, Json chỉ dùng được trên các cơ sở dữ liệu có hỗ trợ như PostgreSQL và MySQL; với SQLite thì Prisma không cho dùng kiểu này, và nếu mảng đó thật sự là danh sách bản ghi thì nó nên trở thành một model riêng có quan hệ chứ không phải một cột Json.
Khóa chính: autoincrement, uuid hay cuid và khi nào đổi
Thấy trường tên id, công cụ viết luôn dòng id Int @id @default(autoincrement()) vì đó là mẫu phổ biến nhất trong tài liệu Prisma. Cơ chế là cơ sở dữ liệu tự cấp số tăng dần, mỗi bản ghi mới lấy số kế tiếp. Ưu điểm là khóa ngắn, index gọn, đọc log dễ. Nhược điểm là khóa đoán được: nếu id lộ ra trên đường dẫn công khai thì người ngoài suy được số lượng bản ghi và thử truy cập bản ghi kế bên. Nhược điểm thứ hai là bản ghi chỉ có id sau khi đã ghi xuống cơ sở dữ liệu, nên phía client không thể tự tạo khóa để làm việc ngoại tuyến rồi đồng bộ sau, và việc gộp dữ liệu từ hai cơ sở dữ liệu độc lập sẽ đụng khóa hàng loạt. Khi gặp các nhu cầu đó, đổi sang String @id @default(uuid()) hoặc @default(cuid()): khóa sinh ngay tại tầng ứng dụng, không đoán được, gộp dữ liệu không đụng nhau, đổi lại tốn chỗ hơn và index cồng kềnh hơn. Còn một trường hợp nữa hay gặp là khóa chính ghép từ hai cột, ví dụ bảng nối giữa người dùng và vai trò: khi đó không có trường id nào cả, bạn khai báo @@id([userId, roleId]) ở cuối model. Điểm quan trọng là quyết định này rất tốn công đổi về sau vì mọi khóa ngoại trỏ tới đều phải đổi theo, nên hãy chốt ngay từ đầu dự án.
Quan hệ giữa các model: phần một bản ghi JSON không bao giờ nói cho bạn biết
Đây là giới hạn cốt lõi và cũng là phần làm nên giá trị của Prisma. Một object JSON đơn lẻ chỉ mô tả các trường phẳng của chính nó, nên công cụ không thể biết trường customerId thật ra trỏ tới model Customer, cũng không biết mảng items lồng bên trong thật ra nên là một model riêng. Vì vậy quan hệ luôn phải viết tay, và cú pháp thì cần nắm ba dạng. Quan hệ một nhiều là dạng phổ biến nhất: phía nhiều khai báo cả trường khóa ngoại lẫn trường quan hệ, ví dụ authorId Int cùng với author User @relation(fields: [authorId], references: [id]), còn phía một chỉ cần khai một mảng posts Post[]. Quan hệ một một viết tương tự nhưng phía kia là một đối tượng đơn và trường khóa ngoại phải có @unique. Quan hệ nhiều nhiều có thể để Prisma tự dựng bảng nối ngầm bằng cách khai mảng ở cả hai phía, hoặc bạn tự tạo model nối khi bảng nối cần thêm cột riêng như thời điểm gán hay vai trò. Đi kèm quan hệ là hành vi khi xóa, khai trong onDelete: Cascade xóa lan sang bản ghi con, Restrict chặn không cho xóa cha khi còn con, SetNull để trống khóa ngoại. Chọn sai hành vi này là nguyên nhân kinh điển của việc mất dữ liệu hoặc để lại bản ghi mồ côi, nên hãy quyết định có ý thức cho từng quan hệ.
Từ model tới bảng thật: prisma migrate, db push và bẫy đổi hoa thường của tên trường
Có khối model rồi vẫn còn hai việc. Thứ nhất, khối này là một mảnh chứ không phải cả file: schema.prisma cần khối datasource khai báo provider và chuỗi kết nối, cùng khối generator khai báo prisma-client-js, nếu thiếu thì mọi lệnh CLI đều báo lỗi ngay. Thứ hai là đưa mô hình xuống cơ sở dữ liệu, và ở đây có hai lệnh dễ nhầm. prisma migrate dev sinh ra file SQL trong thư mục migrations, ghi lại lịch sử thay đổi để cả nhóm và môi trường chạy thật áp dụng theo đúng thứ tự, đây là cách dùng cho mọi dự án nghiêm túc. prisma db push đẩy thẳng mô hình xuống cơ sở dữ liệu và không sinh file lịch sử nào, tiện lúc thử nghiệm nhanh nhưng không dùng cho môi trường chạy thật vì bạn mất khả năng tái lập và quay lui. Bẫy hay gặp thứ ba nằm ở tên trường: công cụ chuyển tên sang camelCase theo quy ước Prisma, nên khóa JSON dạng created_at thành createdAt. Nếu cơ sở dữ liệu của bạn đã tồn tại với cột tên created_at thì phải giữ trường createdAt ở tầng mã và thêm @map("created_at") để ánh xạ về đúng cột thật, tương tự @@map("user_profiles") cho tên bảng. Bỏ qua bước này thì migration sẽ tạo thêm cột mới bên cạnh cột cũ. Với cơ sở dữ liệu đã có sẵn, hướng ngược lại còn nhanh hơn: chạy prisma db pull để Prisma tự đọc cấu trúc hiện có và sinh model.
Ranh giới giữa trang này và các công cụ schema khác trên site
Ba công cụ trên site cùng nhận một JSON mẫu nhưng sinh ra ba thứ ở ba tầng khác nhau. Trang này sinh khối model cho file schema.prisma, tức mô tả dành cho lớp ORM: nó nói bằng ngôn ngữ của Prisma với model, quan hệ, thuộc tính và migration, rồi Prisma mới dịch tiếp xuống cột thật của cơ sở dữ liệu. Trang /vi/tools/sql-create-table-generator bỏ qua lớp trung gian đó và sinh thẳng câu lệnh DDL để chạy trong công cụ quản trị: bạn tự chọn kiểu cột theo hệ quản trị, tự viết khóa ngoại, index và ràng buộc, hợp khi dự án không dùng ORM hoặc khi bạn cần điều khiển chính xác câu lệnh tạo bảng. Trang /vi/tools/zod-schema-generator lại nằm ở đầu kia của luồng dữ liệu: nó sinh schema kiểm tra dữ liệu lúc chạy cho TypeScript, chặn payload xấu ngay tại ranh giới nhận, và không liên quan gì tới việc tạo bảng. Một dự án đầy đủ thường dùng cả hai đầu: Zod ở ngoài, Prisma ở trong. Ngoài ba trang này còn vài công cụ láng giềng: /vi/tools/database-schema-designer để vẽ mô hình nhiều bảng trước khi viết mã, /vi/tools/csv-to-sql-insert khi bạn cần nạp dữ liệu mẫu vào bảng đã tạo, /vi/tools/db-connection-string-parser khi cần đọc hoặc dựng chuỗi kết nối cho khối datasource, và /vi/tools/sql-formatter để căn lại câu lệnh SQL sinh ra từ migration cho dễ đọc.
Câu hỏi thường gặp (FAQ)
Vì sao kết quả chỉ có khối model mà không có datasource và generator?
Công cụ sinh đúng một mảnh để bạn dán vào file schema.prisma đã có. Một file hoàn chỉnh cần thêm khối datasource khai provider và chuỗi kết nối, cùng khối generator khai prisma-client-js; thiếu hai khối đó thì lệnh CLI sẽ báo lỗi.
Trường tiền tệ ra Float, để nguyên có sao không?
Có sao. Float là dấu phẩy động nên không biểu diễn chính xác số thập phân thông thường, cộng dồn lâu ngày sẽ lệch. Với tiền hãy đổi sang Decimal kèm thuộc tính native, ví dụ Decimal @db.Decimal(12, 2).
Vì sao mảng lồng trong JSON lại thành kiểu Json?
Prisma không có kiểu mảng đối tượng lồng nhau, nên công cụ quy về Json là kiểu dành cho dữ liệu phi cấu trúc. Nếu mảng đó thật sự là danh sách bản ghi, cách đúng là tách thành một model riêng và nối bằng quan hệ một nhiều.
Kiểu Json có dùng được với SQLite không?
Không. Prisma chỉ cho dùng kiểu Json trên các cơ sở dữ liệu có hỗ trợ như PostgreSQL, MySQL và MongoDB. Với SQLite bạn phải chuyển sang String rồi tự tuần tự hóa, hoặc tách thành model riêng.
Tên trường bị đổi sang camelCase trong khi cột thật là snake_case thì làm sao?
Giữ tên trường camelCase ở tầng mã cho hợp quy ước Prisma rồi thêm @map("ten_cot_that") để trỏ về đúng cột. Với tên bảng thì dùng @@map ở cuối model. Nếu bỏ qua bước này, migration sẽ tạo cột mới bên cạnh cột cũ.
prisma migrate dev và prisma db push khác nhau thế nào?
migrate dev sinh file SQL lưu trong thư mục migrations để ghi lại lịch sử thay đổi và áp dụng đúng thứ tự ở mọi môi trường. db push đẩy thẳng mô hình xuống cơ sở dữ liệu, không lưu lịch sử, chỉ nên dùng khi thử nghiệm nhanh.
Công cụ có sinh quan hệ giữa các model không?
Không, và cũng không thể. Một object JSON phẳng không chứa thông tin về việc trường nào trỏ tới model nào. Quan hệ phải viết tay bằng @relation kèm trường khóa ngoại, cùng lựa chọn hành vi xóa như Cascade, Restrict hay SetNull.
Muốn khóa chính dạng chuỗi thay vì số tăng dần thì sửa ra sao?
Thay dòng id bằng id String @id @default(uuid()) hoặc @default(cuid()). Khóa dạng này sinh được ở tầng ứng dụng, không đoán được từ bên ngoài và gộp dữ liệu nhiều nguồn không bị đụng, đổi lại tốn chỗ và index lớn hơn.
Trường createdAt và updatedAt nên khai thế nào cho đúng?
createdAt DateTime @default(now()) để cơ sở dữ liệu tự điền lúc tạo, và updatedAt DateTime @updatedAt để Prisma tự cập nhật mỗi lần ghi. Công cụ chỉ gợi ý kiểu DateTime nên hai thuộc tính này bạn thêm tay.
Sau khi dán model vào file thì chạy lệnh gì trước?
Chạy prisma format để căn lại cột và chuẩn hóa cú pháp, rồi prisma validate để bắt lỗi quan hệ hoặc kiểu không hợp lệ. Chỉ khi hai lệnh đó sạch mới tạo migration trên cơ sở dữ liệu phát triển.
Cơ sở dữ liệu đã có sẵn bảng rồi, có nên dùng công cụ này không?
Trường hợp đó nên đi hướng ngược lại: chạy prisma db pull để Prisma đọc cấu trúc thật và sinh model khớp chính xác với cột hiện có. Công cụ này hợp hơn khi bạn bắt đầu từ một bản ghi JSON và chưa có bảng nào.
Một model có thêm được @unique và @@index ở đâu?
@unique viết ngay sau kiểu của trường, ví dụ email String @unique. @@index([field1, field2]) viết thành dòng riêng ở cuối khối model, dùng cho các cột hay xuất hiện trong điều kiện lọc hoặc sắp xếp của truy vấn.
Từ khóa liên quan
- prisma schema generator
- json to prisma
- tạo prisma model từ json
- schema.prisma generator
- prisma model online
- prisma orm tiếng việt
- prisma relation một nhiều
- prisma migrate dev
- prisma db push
- prisma map tên cột
- prisma decimal tiền tệ
- prisma datetime updatedat
- prisma json field
- prisma uuid khóa chính
- prisma db pull introspection
- thiết kế model database
- prisma nextjs postgresql
- sinh model từ json mẫu