模型
的Prisma Schema数据模型定义部分定义了你的应用程序模型(也称为Prisma 模型)。模型
- 代表你的应用程序领域的实体
- 映射到数据库中的表(如 PostgreSQL 等关系型数据库)或集合(MongoDB)
- 构成生成的Prisma Client API中可用查询的基础
- 与 TypeScript 一起使用时,Prisma Client 为你的模型及其任何变体提供生成的类型定义,使数据库访问完全类型安全。
以下 Schema 描述了一个博客平台 - 数据模型定义被高亮显示
- 关系型数据库
- MongoDB
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
bio String
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
categories Category[]
}
model Category {
id Int @id @default(autoincrement())
name String
posts Post[]
}
enum Role {
USER
ADMIN
}
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
}
model Profile {
id String @id @default(auto()) @map("_id") @db.ObjectId
bio String
user User @relation(fields: [userId], references: [id])
userId String @unique @db.ObjectId
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
createdAt DateTime @default(now())
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
categoryIDs String[] @db.ObjectId
categories Category[] @relation(fields: [categoryIDs], references: [id])
}
model Category {
id String @id @default(auto()) @map("_id") @db.ObjectId
name String
postIDs String[] @db.ObjectId
posts Post[] @relation(fields: [postIDs], references: [id])
}
enum Role {
USER
ADMIN
}
数据模型定义由以下部分组成
相应的数据库结构如下所示
模型映射到底层数据源的结构。
- 在 PostgreSQL 和 MySQL 等关系型数据库中,
model
映射到表 - 在 MongoDB 中,
model
映射到集合
注意:未来可能支持非关系型数据库和其他数据源的连接器。例如,对于 REST API,它将映射到资源。
以下查询使用从该数据模型生成的 Prisma Client 来创建
- 一条
User
记录 - 两条嵌套的
Post
记录 - 三条嵌套的
Category
记录
- 查询示例
- 复制粘贴示例
const user = await prisma.user.create({
data: {
email: 'ariadne@prisma.io',
name: 'Ariadne',
posts: {
create: [
{
title: 'My first day at Prisma',
categories: {
create: {
name: 'Office',
},
},
},
{
title: 'How to connect to a SQLite database',
categories: {
create: [{ name: 'Databases' }, { name: 'Tutorials' }],
},
},
],
},
},
})
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient({})
// A `main` function so that you can use async/await
async function main() {
// Create user, posts, and categories
const user = await prisma.user.create({
data: {
email: 'ariadne@prisma.io',
name: 'Ariadne',
posts: {
create: [
{
title: 'My first day at Prisma',
categories: {
create: {
name: 'Office',
},
},
},
{
title: 'How to connect to a SQLite database',
categories: {
create: [{ name: 'Databases' }, { name: 'Tutorials' }],
},
},
],
},
},
})
// Return user, and posts, and categories
const returnUser = await prisma.user.findUnique({
where: {
id: user.id,
},
include: {
posts: {
include: {
categories: true,
},
},
},
})
console.log(returnUser)
}
main()
你的数据模型反映了你的应用程序领域。例如
- 在电子商务应用程序中,你可能拥有
Customer
、Order
、Item
和Invoice
等模型。 - 在社交媒体应用程序中,你可能拥有
User
、Post
、Photo
和Message
等模型。
内省与迁移
有两种方法来定义数据模型
- 手动编写数据模型并使用 Prisma Migrate:你可以手动编写数据模型,并使用Prisma Migrate将其映射到数据库。在这种情况下,数据模型是应用程序模型的单一事实来源。
- 通过内省生成数据模型:当你拥有现有数据库或偏好使用 SQL 迁移数据库 Schema 时,你可以通过内省数据库来生成数据模型。在这种情况下,数据库 Schema 是应用程序模型的单一事实来源。
定义模型
模型代表你的应用程序领域的实体。模型由model
块表示,并定义了许多字段。在上面的示例数据模型中,User
、Profile
、Post
和 Category
都是模型。
博客平台可以使用以下模型进行扩展
model Comment {
// Fields
}
model Tag {
// Fields
}
将模型名称映射到表或集合
Prisma 模型命名约定(单数形式,PascalCase)并非总是与数据库中的表名匹配。数据库中表/集合的常见命名方法是使用复数形式和snake_case表示法 - 例如:comments
。当你内省一个名为 comments
的表时,结果的 Prisma 模型将如下所示
model comments {
// Fields
}
但是,你可以通过使用@@map
属性,在不重命名底层数据库中的 comments
表的情况下,仍然遵循命名约定
model Comment {
// Fields
@@map("comments")
}
使用这个模型定义,Prisma ORM 会自动将 Comment
模型映射到底层数据库中的 comments
表。
注意:你还可以使用
@map
映射列名或枚举值,以及使用@@map
映射枚举名称。
@map
和 @@map
允许你通过将模型和字段名与底层数据库中的表和列名解耦,来调整你的 Prisma Client API 的形态。
定义字段
模型的属性称为字段,它由以下部分组成
字段的类型决定其结构,并属于以下两类之一
- 标量类型(包括枚举),它们映射到数据库中的列(关系型数据库)或文档字段(MongoDB) - 例如,
String
或Int
- 模型类型(此时字段称为关系字段) - 例如
Post
或Comment[]
。
下表描述了示例 Schema 中 User
模型的字段
展开查看表格
名称 | 类型 | 标量 vs 关系 | 类型修饰符 | 属性 |
---|---|---|---|---|
id | Int | 标量 | - | @id and @default(autoincrement()) |
email | String | 标量 | - | @unique |
name | String | 标量 | ? | - |
role | Role | 标量 (enum ) | - | @default(USER) |
posts | Post | 关系(Prisma 级别的字段) | [] | - |
profile | Profile | 关系(Prisma 级别的字段) | ? | - |
标量字段
以下示例使用几种标量类型扩展了 Comment
和 Tag
模型。一些字段包含属性
- 关系型数据库
- MongoDB
model Comment {
id Int @id @default(autoincrement())
title String
content String
}
model Tag {
name String @id
}
model Comment {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
content String
}
model Tag {
name String @id @map("_id")
}
参阅完整的标量字段类型列表。
关系字段
关系字段的类型是另一个模型 - 例如,一篇帖子(Post
)可以有多个评论(Comment[]
)
- 关系型数据库
- MongoDB
model Post {
id Int @id @default(autoincrement())
// Other fields
comments Comment[] // A post can have many comments
}
model Comment {
id Int
// Other fields
post Post? @relation(fields: [postId], references: [id]) // A comment can have one post
postId Int?
}
model Post {
id String @id @default(auto()) @map("_id") @db.Objectid
// Other fields
comments Comment[] // A post can have many comments
}
model Comment {
id String @id @default(auto()) @map("_id") @db.Objectid
// Other fields
post Post? @relation(fields: [postId], references: [id]) // A comment can have one post
postId String? @db.ObjectId
}
请参阅关系文档,了解更多关于模型之间关系的示例和信息。
原生类型映射
版本2.17.0及更高版本支持描述底层数据库类型的原生数据库类型属性(类型属性)
model Post {
id Int @id
title String @db.VarChar(200)
content String
}
类型属性具有以下特点
- 特定于底层 provider - 例如,PostgreSQL 为
Boolean
使用@db.Boolean
,而 MySQL 使用@db.TinyInt(1)
- 以 PascalCase 编写(例如,
VarChar
或Text
) - 以
@db
为前缀,其中db
是你的 Schema 中datasource
块的名称
此外,在内省过程中,类型属性仅在底层原生类型不是默认类型时才会添加到 Schema 中。例如,如果你使用的是 PostgreSQL provider,底层原生类型为 text
的 String
字段将不会有类型属性。
参阅每个标量类型和 provider 的原生数据库类型属性完整列表。
好处与工作流程
- 控制 Prisma Migrate 在数据库中创建的确切原生类型 - 例如,一个
String
可以是@db.VarChar(200)
或@db.Char(50)
- 内省时看到一个丰富的 Schema
类型修饰符
可以通过附加以下两种修饰符之一来修改字段的类型
注意:你不能组合类型修饰符 - 不支持可选列表。
列表
以下示例包含一个标量列表和一个相关模型列表
- 关系型数据库
- MongoDB
model Post {
id Int @id @default(autoincrement())
// Other fields
comments Comment[] // A list of comments
keywords String[] // A scalar list
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
// Other fields
comments Comment[] // A list of comments
keywords String[] // A scalar list
}
注意:标量列表仅在数据库连接器原生或在 Prisma ORM 级别支持标量列表时才受支持。
可选字段和必填字段
- 关系型数据库
- MongoDB
model Comment {
id Int @id @default(autoincrement())
title String
content String?
}
model Tag {
name String @id
}
model Comment {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
content String?
}
model Tag {
name String @id @map("_id")
}
当不使用 ?
类型修饰符标注字段时,该字段在模型的每条记录中都将是必填的。这在两个层面产生影响
- 数据库
- 关系型数据库:必填字段在底层数据库中通过
NOT NULL
约束表示。 - MongoDB:必填字段在 MongoDB 数据库层面没有概念。
- 关系型数据库:必填字段在底层数据库中通过
- Prisma Client:Prisma Client 生成的TypeScript 类型,代表应用程序代码中的模型,也会将这些字段定义为必填,以确保它们在运行时始终带有值。
注意:可选字段的默认值是
null
。
不支持的类型
当你内省关系型数据库时,不支持的数据类型会作为Unsupported
添加
location Unsupported("POLYGON")?
Unsupported
类型允许你在 Prisma schema 中为 Prisma ORM 尚不支持的数据库类型定义字段。例如,Prisma ORM 目前不支持 MySQL 的 POLYGON
类型,但现在可以使用 Unsupported("POLYGON")
类型将其添加到 Prisma schema 中。
类型为 Unsupported
的字段不会出现在生成的 Prisma Client API 中,但你仍然可以使用 Prisma ORM 的原生数据库访问特性来查询这些字段。
注意:如果模型有必填的
Unsupported
字段,生成的 client 将不会包含该模型的create
或update
方法。
注意:MongoDB 连接器不支持也不需要
Unsupported
类型,因为它支持所有标量类型。
定义属性
属性修改字段或模型块的行为。以下示例包含三个字段属性(@id
、@default
和 @unique
)和一个块属性(@@unique
)
- 关系型数据库
- MongoDB
model User {
id Int @id @default(autoincrement())
firstName String
lastName String
email String @unique
isAdmin Boolean @default(false)
@@unique([firstName, lastName])
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
firstName String
lastName String
email String @unique
isAdmin Boolean @default(false)
@@unique([firstName, lastName])
}
一些属性接受参数 - 例如,@default
接受 true
或 false
isAdmin Boolean @default(false) // short form of @default(value: false)
定义 ID 字段
ID 唯一标识模型的单个记录。一个模型只能有一个 ID
- 在关系型数据库中,ID 可以是单个字段或基于多个字段。如果模型没有
@id
或@@id
,你必须定义一个必填的@unique
字段或@@unique
块代替。 - 在MongoDB中,ID 必须是定义了
@id
属性和@map("_id")
属性的单个字段。
在关系型数据库中定义 ID
在关系型数据库中,可以使用@id
属性定义单个字段的 ID,或者使用@@id
属性定义多个字段的 ID。
单字段 ID
在以下示例中,User
的 ID 由 id
整数字段表示
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
}
复合 ID
在以下示例中,User
的 ID 由 firstName
和 lastName
字段组合表示
model User {
firstName String
lastName String
email String @unique
isAdmin Boolean @default(false)
@@id([firstName, lastName])
}
默认情况下,此字段在 Prisma Client 查询中的名称将是 firstName_lastName
。
你还可以使用@@id
属性的 name
字段为复合 ID 提供自己的名称
model User {
firstName String
lastName String
email String @unique
isAdmin Boolean @default(false)
@@id(name: "fullName", fields: [firstName, lastName])
}
firstName_lastName
字段现在将改名为 fullName
。
请参阅使用复合 ID 的文档,了解如何在 Prisma Client 中与复合 ID 交互。
使用 @unique
字段作为唯一标识符
在以下示例中,用户通过 @unique
字段唯一标识。因为 email
字段作为模型的唯一标识符(这是必需的),所以它必须是必填的
model User {
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
}
关系型数据库中的约束名称
你可以在底层数据库中选择定义一个自定义主键约束名称。
在 MongoDB 中定义 ID
MongoDB 连接器有定义 ID 字段的特定规则,这与关系型数据库不同。ID 必须由一个使用@id
属性定义的单个字段组成,并且必须包含 @map("_id")
。
在以下示例中,User
的 ID 由接受自动生成 ObjectId
的 id
字符串字段表示
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
}
在以下示例中,User
的 ID 由接受 ObjectId
以外内容的 id
字符串字段表示 - 例如,唯一的用户名
model User {
id String @id @map("_id")
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
}
MongoDB 不支持 @@id
MongoDB 不支持复合 ID,这意味着你不能使用 @@id
块来标识模型。
定义默认值
你可以使用@default
属性为模型的标量字段定义默认值
- 关系型数据库
- MongoDB
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
title String
published Boolean @default(false)
data Json @default("{ \"hello\": \"world\" }")
author User @relation(fields: [authorId], references: [id])
authorId Int
categories Category[] @relation(references: [id])
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
createdAt DateTime @default(now())
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
categories Category[] @relation(references: [id])
}
@default
属性要么
- 表示底层数据库中的
DEFAULT
值(仅限关系型数据库)或 - 使用 Prisma ORM 级别的函数。例如,
cuid()
和uuid()
由 Prisma Client 的查询引擎为所有连接器提供。
默认值可以是
- 与字段类型对应的静态值,例如
5
(Int
)、Hello
(String
) 或false
(Boolean
) - 静态值的列表,例如
[5, 6, 8]
(Int[]
) 或["Hello", "Goodbye"]
(String
[])。这些在 Prisma ORM 版本4.0.0
及更高版本中可用,并且在使用支持的数据库(PostgreSQL、CockroachDB 和 MongoDB)时。 - 函数,例如
now()
或uuid()
- JSON 数据。注意 JSON 需要在
@default
属性内用双引号括起来,例如:@default("[]")
。如果你想提供一个 JSON 对象,你需要用双引号括起来,然后使用反斜杠转义任何内部双引号,例如:@default("{ \"hello\": \"world\" }")
。
请参阅属性函数参考文档,了解连接器对函数的支持信息。
定义唯一字段
你可以为模型添加 unique 属性,以便唯一标识该模型的单个记录。Unique 属性可以通过@unique
属性定义在单个字段上,或者使用@@unique
属性定义在多个字段上(也称为复合或组合唯一约束)。
在以下示例中,email
字段的值必须唯一
- 关系型数据库
- MongoDB
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique
name String?
}
在以下示例中,authorId
和 title
的组合必须唯一
- 关系型数据库
- MongoDB
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
categories Category[] @relation(references: [id])
@@unique([authorId, title])
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
createdAt DateTime @default(now())
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
categories Category[] @relation(references: [id])
@@unique([authorId, title])
}
关系型数据库中的约束名称
你可以在底层数据库中选择定义一个自定义唯一约束名称。
默认情况下,此字段在 Prisma Client 查询中的名称将是 authorId_title
。
你还可以使用@@unique
属性的 name
字段为复合唯一约束提供自己的名称
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
createdAt DateTime @default(now())
title String
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
categories Category[] @relation(references: [id])
@@unique(name: "authorTitle", [authorId, title])
}
authorId_title
字段现在将改名为 authorTitle
。
请参阅使用复合唯一标识符的文档,了解如何在 Prisma Client 中与复合唯一约束交互。
复合类型唯一约束
在使用 3.12.0
及更高版本的 MongoDB provider 时,你可以使用语法 @@unique([compositeType.field])
在复合类型的字段上定义唯一约束。与其它字段一样,复合类型字段可以作为多列唯一约束的一部分使用。
以下示例定义了一个基于 User
模型的 email
字段和 Address
复合类型的 number
字段的多列唯一约束,Address
复合类型在 User.address
中使用
type Address {
street String
number Int
}
model User {
id Int @id
email String
address Address
@@unique([email, address.number])
}
如果存在多个嵌套的复合类型,这种表示法可以进行链式调用
type City {
name String
}
type Address {
number Int
city City
}
model User {
id Int @id
address Address[]
@@unique([address.city.name])
}
定义索引
你可以通过模型上的@@index
定义模型一个或多个字段上的索引。以下示例定义了一个基于 title
和 content
字段的多列索引
model Post {
id Int @id @default(autoincrement())
title String
content String?
@@index([title, content])
}
关系型数据库中的索引名称
你可以在底层数据库中选择定义一个自定义索引名称。
定义复合类型索引
在使用 3.12.0
及更高版本的 MongoDB provider 时,你可以使用语法 @@index([compositeType.field])
在复合类型的字段上定义索引。与其它字段一样,复合类型字段可以作为多列索引的一部分使用。
以下示例定义了一个基于 User
模型的 email
字段和 Address
复合类型的 number
字段的多列索引
type Address {
street String
number Int
}
model User {
id Int @id
email String
address Address
@@index([email, address.number])
}
如果存在多个嵌套的复合类型,这种表示法可以进行链式调用
type City {
name String
}
type Address {
number Int
city City
}
model User {
id Int @id
address Address[]
@@index([address.city.name])
}
定义枚举
如果你的数据库连接器原生或在 Prisma ORM 级别支持枚举,你可以在数据模型中定义枚举。
在 Prisma schema 数据模型中,枚举被视为标量类型。因此,它们默认情况下作为返回值包含在Prisma Client 查询中。
枚举通过enum
块定义。例如,一个 User
有一个 Role
- 关系型数据库
- MongoDB
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
role Role @default(USER)
}
enum Role {
USER
ADMIN
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique
name String?
role Role @default(USER)
}
enum Role {
USER
ADMIN
}
定义复合类型
复合类型在 3.10.0
版本中作为 mongodb
预览特性标志添加,并在 3.12.0
版本中达到通用可用性。
复合类型目前仅在 MongoDB 上可用。
复合类型(在 MongoDB 中称为嵌入式文档)通过允许你定义新的对象类型,支持在记录内嵌入其他记录。复合类型的结构和类型化方式与模型类似。
要定义复合类型,请使用 type
块。例如,请看以下 Schema
model Product {
id String @id @default(auto()) @map("_id") @db.ObjectId
name String
photos Photo[]
}
type Photo {
height Int
width Int
url String
}
在此示例中,Product
模型有一个存储在 photos
中的 Photo
复合类型列表。
使用复合类型时的注意事项
复合类型仅支持有限的属性集。支持以下属性
@default
@map
- 原生类型,例如
@db.ObjectId
复合类型内部不支持以下属性
@unique
@id
@relation
@ignore
@updatedAt
但是,仍然可以在使用复合类型的模型级别上使用 @@unique
属性定义唯一约束。有关更多详细信息,请参阅复合类型唯一约束。
可以通过在使用复合类型的模型级别上使用 @@index
属性来定义索引。有关更多详细信息,请参阅复合类型索引。
使用函数
Prisma schema 支持多种函数。这些函数可用于指定模型字段的默认值。
例如,createdAt
的默认值是 now()
- 关系型数据库
- MongoDB
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
}
model Post {
id String @default(auto()) @map("_id") @db.ObjectId
createdAt DateTime @default(now())
}
cuid()
和 uuid()
由 Prisma ORM 实现,因此在底层数据库 Schema 中不可见。在使用内省时,你仍然可以通过手动修改你的 Prisma schema 和生成 Prisma Client 来使用它们,在这种情况下,这些值将由 Prisma Client 的查询引擎生成
对 autoincrement()
、now()
和 dbgenerated(...)
的支持在不同数据库之间有所不同。
关系型数据库连接器在数据库级别实现 autoincrement()
、dbgenerated(...)
和 now()
。MongoDB 连接器不支持 autoincrement()
或 dbgenerated(...)
,并且 now()
在 Prisma ORM 级别实现。auto()
函数用于生成 ObjectId
。
关系
请参阅关系文档,了解更多关于模型之间关系的示例和信息。
Prisma Client 中的模型
查询 (CRUD)
数据模型定义中的每个模型都会在生成的Prisma Client API中产生一系列 CRUD 查询
findMany()
findFirst()
findFirstOrThrow()
findUnique()
findUniqueOrThrow()
create()
update()
upsert()
delete()
createMany()
createManyAndReturn()
updateMany()
updateManyAndReturn()
deleteMany()
这些操作可以通过 Prisma Client 实例上的生成属性访问。默认情况下,属性的名称是模型名称的小写形式,例如 User
模型对应 user
,Post
模型对应 post
。
以下是一个示例,说明如何使用 Prisma Client API 中的 user
属性
const newUser = await prisma.user.create({
data: {
name: 'Alice',
},
})
const allUsers = await prisma.user.findMany()
类型定义
Prisma Client 还生成反映模型结构的类型定义。这些是生成的 @prisma/client
Node 模块的一部分。
使用 TypeScript 时,这些类型定义确保你的所有数据库查询都是完全类型安全的,并在编译时得到验证(即使是使用 select
或 include
的部分查询)。
即使使用纯 JavaScript,类型定义仍然包含在 @prisma/client
Node 模块中,可以在编辑器中启用智能感知(IntelliSense)/自动补全等功能。
注意:实际的类型存储在
.prisma/client
文件夹中。@prisma/client/index.d.ts
导出此文件夹的内容。
例如,上面 User
模型的类型定义如下所示
export type User = {
id: number
email: string
name: string | null
role: string
}
请注意,关系字段 posts
和 profile
默认不包含在类型定义中。但是,如果您需要 User
类型的变体,您仍然可以使用 Prisma Client 生成的一些辅助类型来定义它们(在这种情况下,这些辅助类型将被称为 UserGetIncludePayload
和 UserGetSelectPayload
)。
限制
记录必须唯一可识别
Prisma ORM 目前仅支持至少有一个唯一字段或字段组合的模型。实际上,这意味着每个 Prisma 模型都必须至少具有以下属性之一
@id
或@@id
用于单字段或多字段主键约束(每个模型最多一个)@unique
或@@unique
用于单字段或多字段唯一约束