# entgo 特性开关
---
此框架提供了一系列代码生成特性,可以自行选择使用。
## 用法
特性开关可以通过 CLI 标志或作为参数提供给 gen 包。
### CLI
```shell
go run entgo.io/ent/cmd/ent generate --feature privacy,entql,schema/snapshot,sql/schemaconfig,sql/lock,upsert ./ent/schema
```
### Go
```golang
// +build ignore
package main
import (
"log"
"text/template"
"entgo.io/ent/entc"
"entgo.io/ent/entc/gen"
)
func main() {
err := entc.Generate("./schema", &gen.Config{
Features: []gen.Feature{
gen.FeaturePrivacy,
gen.FeatureEntQL,
},
Templates: []*gen.Template{
gen.MustParse(gen.NewTemplate("static").
Funcs(template.FuncMap{"title": strings.ToTitle}).
ParseFiles("template/static.tmpl")),
},
})
if err != nil {
log.Fatalf("running ent codegen: %v", err)
}
}
```
## 特性列表
### 隐私层
- 隐私层允许为数据库中实体的查询和更变操作配置隐私政策(通俗来讲就是设定角色与权限,让每个人只能给看到属于自己的东西)。
### EntQL过滤器
- entql配置项在运行时为不同的查询构造器提供了通用的动态筛选功能。
### 自动解决合并冲突
- schema/snapshot配置项告诉entc (ent 代码生成) ,对最新结构 (schema) 生成一个快照,当用户的 结构 (schema) 不能构建时,自动使用生成的快照解决合并冲突。
### Schema配置
- 使用sql/schemaconfig 配置项,你能给关系数据库中的对象定义别名,并将其映射到模型上。 当你的模型并不都生活在一个数据库下,而是根据 Schema 而有所不同,这很有用。
在生成代码之后,你就可以使用新的配置项,比如:
```golang
c, err := ent.Open(dialect, conn,
ent.AlternateSchema(
ent.SchemaConfig{
User: "usersdb",
Car: "carsdb",
}))
c.User.Query().All(ctx) // SELECT * FROM `usersdb`.`users`
c.Car.Query().All(ctx) // SELECT * FROM `carsdb`.`cars`
```
### 行级锁定
sql/lock 选项允许使用 SQL SELECT ... FOR {UPDATE OR SHARE } 配置行级锁定语法 。
<table><tr><td bgcolor=yellow>背景色yellow</td></tr></table>
```golang
tx, err := client.Tx(ctx)
if err != nil {
log.Fatal(err)
}
tx.Pet.Query().
Where(pet.Name(name)).
ForUpdate().
Only(ctx)
tx.Pet.Query().
Where(pet.ID(id)).
ForShare(
sql.WithLockTables(pet.Table),
sql.WithLockAction(sql.NoWait),
).
Only(ctx)
```
### 自定义 SQL 修饰符
- sql/modifier 选项允许将自定义 SQL 修饰符添加到构建器并在执行语句之前对其进行变异。
```golang
// SELECT SUM(LENGTH(name)) FROM `pet`;
client.Pet.
Query().
Modify(func(s *sql.Selector) {
s.Select("SUM(LENGTH(name))")
}).IntX(ctx)
// SELECT `pet`.*, LENGTH(name) FROM `pet` ORDER BY `pet`.`id` ASC;
var p1 []struct {
ent.Pet
NameLength int `sql:"length"`
}
client.Pet.Query().
Order(ent.Asc(pet.FieldID)).
Modify(func(s *sql.Selector) {
s.AppendSelect("LENGTH(name)")
}).
ScanX(ctx, &p1)
/*
SELECT
COUNT(*) AS `count`,
SUM(`price`) AS `price`,
DATE(created_at) AS `created_at`
FROM
`users`
WHERE
`created_at` > x AND `created_at` < y
GROUP BY
DATE(created_at)
ORDER BY
DATE(created_at) DESC;
*/
var v []struct {
Count int `json:"count"`
Price int `json:"price"`
CreatedAt time.Time `json:"created_at"`
}
client.User.
Query().
Where(
user.CreatedAtGT(x),
user.CreatedAtLT(y),
).
Modify(func(s *sql.Selector) {
s.Select(
sql.As(sql.Count("*"), "count"),
sql.As(sql.Sum("price"), "price"),
sql.As("DATE(created_at)", "created_at"),
).
GroupBy("DATE(created_at)").
OrderBy(sql.Desc("DATE(created_at)"))
}).
ScanX(ctx, &v)
/*
SELECT
`groups`.*,
COUNT(`t1`.`group_id`) AS `users_count`
FROM
`groups` LEFT JOIN `user_groups` AS `t1`
ON
`groups`.`id` = `t1`.`group_id`
GROUP BY
`groups`.`id`
ORDER BY
`groups`.`id` ASC;
*/
var gs []struct {
ent.Group
UsersCount int `sql:"users_count"`
}
client.Group.Query().
Order(ent.Asc(group.FieldID)).
Modify(func(s *sql.Selector) {
t := sql.Table(group.UsersTable)
s.LeftJoin(t).
On(
s.C(group.FieldID),
t.C(group.UsersPrimaryKey[1]),
).
// Append the "users_count" column to the selected columns.
AppendSelect(
sql.As(sql.Count(t.C(group.UsersPrimaryKey[1])), "users_count"),
).
GroupBy(s.C(group.FieldID))
}).
ScanX(ctx, &gs)
```
### Upsert
- sql/upsert 选项允许使用 SQL ON CONFLICT / ON DUPLICATE KEY 语法配置 upsert 和 bulk-upsert 逻辑。 如需完整文档,请访问 Upsert API。
-
```golang
// Use the new values that were set on create.
id, err := client.User.
Create().
SetAge(30).
SetName("Ariel").
OnConflict().
UpdateNewValues().
ID(ctx)
// In PostgreSQL, the conflict target is required.
err := client.User.
Create().
SetAge(30).
SetName("Ariel").
OnConflictColumns(user.FieldName).
UpdateNewValues().
Exec(ctx)
// Bulk upsert is also supported.
client.User.
CreateBulk(builders...).
OnConflict(
sql.ConflictWhere(...),
sql.UpdateWhere(...),
).
UpdateNewValues().
Exec(ctx)
// INSERT INTO "users" (...) VALUES ... ON CONFLICT WHERE ... DO UPDATE SET ... WHERE ..
```
###### tags: `Golang` `entgo`