快速开始
简介
ent 是一个简单而强大的Go语言实体框架,它使得构建和维护大型数据模型的应用程序变得容易,同时ent遵循以下原则:
- 轻松地将数据库模式建模为图形结构
- 将模式定义为可编程的Go语言代码
- 基于代码生成的静态类型
- 易于编写的数据库查询和图遍历
- 简单地扩展和使用Go模版进行自定义
设置Go环境
如果你的项目目录在GOPATH之外,或者你不熟悉GOPATH,可通过如下的命令进行Go module设置
go mod init entdemo
创建第一个模式(Schema)
在项目的根目录运行以下命令:
go run -mod=mod entgo.io/ent/cmd/ent new <Schema-name>
该命令会在指定目录:<project>/ent/schema/下生成指定<Schema-name>的模式(示例中Schema为User):
package schema
import "entgo.io/ent"
// User holds the schema definition for the User entity.
type User struct {
ent.Schema
}
// Fields of the User.
func (User) Fields() []ent.Field {
return nil
}
// Edges of the User.
func (User) Edges() []ent.Edge {
return nil
}
向Schema中添加2个字段:
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema/field"
)
// Fields of the User.
func (User) Fields() []ent.Field {
return []ent.Field{
field.Int("age").
Positive(),
field.String("nickname").
Default("unknown"),
}
}
在项目的根目录运行go generate
命令生成文件:
go generate ./ent
生成文件如下:
ent
├── client.go
├── config.go
├── context.go
├── ent.go
├── generate.go
├── mutation.go
... truncated
├── schema
│ └── user.go
├── tx.go
├── user
│ ├── user.go
│ └── where.go
├── user.go
├── user_create.go
├── user_delete.go
├── user_query.go
└── user_update.go
创建第一个实体(Entity)
首先,创建一个新的ent.Client,示例中将使用MySQL
package main
import (
"context"
"log"
"entdemo/ent"
_ "github.com/go-sql-driver/mysql"
)
func main() {
client, err := ent.Open("mysql", "<user>:<pass>@tcp(<host>:<port>)/<database>?parseTime=True")
if err != nil {
log.Fatalf("failed opening connection to mysql: %v", err)
}
defer client.Close()
// Run the auto migration tool.
if err := client.Schema.Create(context.Background()); err != nil {
log.Fatalf("failed creating schema resources: %v", err)
}
}
然后我们,准备创建user,示例中通过调用CreateerUser函数进行创建:
func CreateUser(ctx context.Context, client *ent.Client) (*ent.User, error) {
u, err := client.User.Create().
SetAge(18).
SetNickname("tester").
Save(ctx)
if err != nil {
return nil, fmt.Errorf("failed creating user: %w", err)
}
log.Println("user was created: ", u)
return u, nil
}
查询实体
ent为每一个实体模式生成了一个包含断言、默认值、校验器以及存储元素(列名、主键等)的额外信息的包
package main
import (
"log"
"entdemo/ent"
"entdemo/ent/user"
)
func QueryUser(ctx context.Context, client *ent.CLient) (*ent.User, error) {
u, err := client.User.Query().
Where(user.Nickname).
// `Only` fails if no user found,
// or more than 1 user returned.
Only(ctx)
if err != nil {
return nil, fmt.Errorf("failed quering user: %w", err)
}
log.Println("user returned: ", u)
return u, nil
}
添加第一个条边(关系)
在教程的这个部分,我们在该模式中想要声明一条到另一个实体的边
首先创建2个额外的实体:Car和Group
同样地,通过ent cli进行模式的初始化:
go run -mod=mod entgo.io/ent/cmd/ent new Car Group
然后手动增加一些字段:
//Fieids of the Car.
func (Car) Fields() []ent.Field {
return []ent.Field{
field.String("model"),
field.Time("registered_at"),
}
}
// Fields of the Group.
func (Group) Fields() []ent.Field {
return []ent.Field{
field.String("name").
Match(regexp.MustCompile("[a-zA-Z_]+$")),
}
}
让我们来定义第一个关系,从User到Car的边意味着user可拥有一或多个car,但car只能属于一个user(一对多的关系)
添加“cars”边到User模式中,然后运行go generate ./ent
命令:
// Edges of the User.
func (User) Edges() []ent.Edge {
return []ent.Edge{
edge.To("cars", Car.Type),
}
}
在示例中继续创建2个car然后添加到user中:
import (
"entdemo/ent"
"entdemo/ent/car"
"entdemo/ent/user"
)
func CreateCars(ctx context.Context, client *ent.Client) (*ent.User, error) {
// Create a new car with model "Tesla".
tesla, err := client.Car.Create().
SetModel("Tesla").
SetRegisteredAt(time.Now()).
Save(ctx)
if err != nil {
return nil, fmt.Errorf("failed creating car: %w", err)
}
log.Println("car was created: ", tesla)
// Create a new car with model "Ford".
ford, err := client.Car.Create().
SetModel("Ford").
SetRegisteredAt(time.Now()).
Save(ctx)
if err != nil {
return nil, fmt.Errorf("failed creating car: %w", err)
}
// Create a new user, and add it the 2 cars.
tester, err := client.User.Create().
SetAge(18).
SetNickname("tester").
AddCars(tesla, ford).
Save(ctx)
if err != nil {
return nil, fmt.Errorf("failed creating user: %w", err)
}
log.Println("user was created: ", tester)
return tester, nil
}
查询cars边(关系):
import (
"log"
"entdemo/ent"
"entdemo/ent/car"
)
func QueryCars(ctx context.Context, tester *ent.Client) error {
cars, err := tester.QueryCars().All(ctx)
if err != nil {
return fmt.Errorf("failed querying user cars: %w", err)
}
log.Println("returned cars: ", cars)
// What about filtering specific cars.
ford, err := tester.QueryCars().
Where(car.Model("Ford")).
Only(ctx)
if err != nil {
return fmt.Errorf("failed querying user cars: %w", err)
}
log.Println(ford)
return nil
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。