特性开关

此框架提供了一系列代码生成特性,可以自行选择使用。

用法

特性开关可以通过 CLI 标志或作为参数提供给 gen 包。

CLI

  1. go run entgo.io/ent/cmd/ent generate --feature privacy,entql ./ent/schema

Go

  1. // +build ignore
  2. package main
  3. import (
  4. "log"
  5. "text/template"
  6. "entgo.io/ent/entc"
  7. "entgo.io/ent/entc/gen"
  8. )
  9. func main() {
  10. err := entc.Generate("./schema", &gen.Config{
  11. Features: []gen.Feature{
  12. gen.FeaturePrivacy,
  13. gen.FeatureEntQL,
  14. },
  15. Templates: []*gen.Template{
  16. gen.MustParse(gen.NewTemplate("static").
  17. Funcs(template.FuncMap{"title": strings.ToTitle}).
  18. ParseFiles("template/static.tmpl")),
  19. },
  20. })
  21. if err != nil {
  22. log.Fatalf("running ent codegen: %v", err)
  23. }
  24. }

特性列表

隐私层

隐私层允许为数据库中实体的查询和变更操作配置隐私政策(通俗的来讲,就是希望不同权限的人只能看到属于自己的内容)。

This option can added to a project using the --feature privacy flag, and its full documentation exists in the privacy page.

EntQL过滤器

entql配置项在运行时为不同的查询构造器提供了通用的动态筛选功能。

This option can be added to a project using the --feature entql flag, and more information about it exists in the privacy page.

自动解决合并冲突

schema/snapshot配置项告诉entc (ent 代码生成) ,对最新结构 (schema) 生成一个快照,当用户的 结构 (schema) 不能构建时,自动使用生成的快照解决合并冲突。

This option can be added to a project using the --feature schema/snapshot flag, but please see ent/ent/issues/852 to get more context about it.

Schema配置

使用sql/schemaconfig 配置项,你能给关系数据库中的对象定义别名,并将其映射到模型上。 当你的模型并不都生活在一个数据库下,而是根据 Schema 而有所不同,这很有用。

This option can be added to a project using the --feature sql/schemaconfig flag. 在生成代码之后,你就可以使用新的配置项,比如:

  1. c, err := ent.Open(dialect, conn, ent.AlternateSchema(ent.SchemaConfig{
  2. User: "usersdb",
  3. Car: "carsdb",
  4. }))
  5. c.User.Query().All(ctx) // SELECT * FROM `usersdb`.`users`
  6. c.Car.Query().All(ctx) // SELECT * FROM `carsdb`.`cars`

Row-level Locks

The sql/lock option lets configure row-level locking using the SQL SELECT ... FOR {UPDATE | SHARE} syntax.

This option can be added to a project using the --feature sql/lock flag.

  1. tx, err := client.Tx(ctx)
  2. if err != nil {
  3. log.Fatal(err)
  4. }
  5. tx.Pet.Query().
  6. Where(pet.Name(name)).
  7. ForUpdate().
  8. Only(ctx)
  9. tx.Pet.Query().
  10. Where(pet.ID(id)).
  11. ForShare(
  12. sql.WithLockTables(pet.Table),
  13. sql.WithLockAction(sql.NoWait),
  14. ).
  15. Only(ctx)

Custom SQL Modifiers

The sql/modifier option lets add custom SQL modifiers to the builders and mutate the statements before they are executed.

This option can be added to a project using the --feature sql/modifier flag.

Example 1

  1. client.Pet.
  2. Query().
  3. Modify(func(s *sql.Selector) {
  4. s.Select("SUM(LENGTH(name))")
  5. }).
  6. IntX(ctx)

The above code will produce the following SQL query:

  1. SELECT SUM(LENGTH(name)) FROM `pet`

Example 2

  1. var p1 []struct {
  2. ent.Pet
  3. NameLength int `sql:"length"`
  4. }
  5. client.Pet.Query().
  6. Order(ent.Asc(pet.FieldID)).
  7. Modify(func(s *sql.Selector) {
  8. s.AppendSelect("LENGTH(name)")
  9. }).
  10. ScanX(ctx, &p1)

The above code will produce the following SQL query:

  1. SELECT `pet`.*, LENGTH(name) FROM `pet` ORDER BY `pet`.`id` ASC

Example 3

  1. var v []struct {
  2. Count int `json:"count"`
  3. Price int `json:"price"`
  4. CreatedAt time.Time `json:"created_at"`
  5. }
  6. client.User.
  7. Query().
  8. Where(
  9. user.CreatedAtGT(x),
  10. user.CreatedAtLT(y),
  11. ).
  12. Modify(func(s *sql.Selector) {
  13. s.Select(
  14. sql.As(sql.Count("*"), "count"),
  15. sql.As(sql.Sum("price"), "price"),
  16. sql.As("DATE(created_at)", "created_at"),
  17. ).
  18. GroupBy("DATE(created_at)").
  19. OrderBy(sql.Desc("DATE(created_at)"))
  20. }).
  21. ScanX(ctx, &v)

The above code will produce the following SQL query:

  1. SELECT
  2. COUNT(*) AS `count`,
  3. SUM(`price`) AS `price`,
  4. DATE(created_at) AS `created_at`
  5. FROM
  6. `users`
  7. WHERE
  8. `created_at` > x AND `created_at` < y
  9. GROUP BY
  10. DATE(created_at)
  11. ORDER BY
  12. DATE(created_at) DESC

Example 4

  1. var gs []struct {
  2. ent.Group
  3. UsersCount int `sql:"users_count"`
  4. }
  5. client.Group.Query().
  6. Order(ent.Asc(group.FieldID)).
  7. Modify(func(s *sql.Selector) {
  8. t := sql.Table(group.UsersTable)
  9. s.LeftJoin(t).
  10. On(
  11. s.C(group.FieldID),
  12. t.C(group.UsersPrimaryKey[1]),
  13. ).
  14. // Append the "users_count" column to the selected columns.
  15. AppendSelect(
  16. sql.As(sql.Count(t.C(group.UsersPrimaryKey[1])), "users_count"),
  17. ).
  18. GroupBy(s.C(group.FieldID))
  19. }).
  20. ScanX(ctx, &gs)

The above code will produce the following SQL query:

  1. SELECT
  2. `groups`.*,
  3. COUNT(`t1`.`group_id`) AS `users_count`
  4. FROM
  5. `groups` LEFT JOIN `user_groups` AS `t1`
  6. ON
  7. `groups`.`id` = `t1`.`group_id`
  8. GROUP BY
  9. `groups`.`id`
  10. ORDER BY
  11. `groups`.`id` ASC

Upsert

The sql/upsert option lets configure upsert and bulk-upsert logic using the SQL ON CONFLICT / ON DUPLICATE KEY syntax. For full documentation, go to the Upsert API.

This option can be added to a project using the --feature sql/upsert flag.

  1. // Use the new values that were set on create.
  2. id, err := client.User.
  3. Create().
  4. SetAge(30).
  5. SetName("Ariel").
  6. OnConflict().
  7. UpdateNewValues().
  8. ID(ctx)
  9. // In PostgreSQL, the conflict target is required.
  10. err := client.User.
  11. Create().
  12. SetAge(30).
  13. SetName("Ariel").
  14. OnConflictColumns(user.FieldName).
  15. UpdateNewValues().
  16. Exec(ctx)
  17. // Bulk upsert is also supported.
  18. client.User.
  19. CreateBulk(builders...).
  20. OnConflict(
  21. sql.ConflictWhere(...),
  22. sql.UpdateWhere(...),
  23. ).
  24. UpdateNewValues().
  25. Exec(ctx)
  26. // INSERT INTO "users" (...) VALUES ... ON CONFLICT WHERE ... DO UPDATE SET ... WHERE ...