4

rem:复古的Golang ORM

 8 months ago
source link: https://www.jdon.com/67846.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

rem:复古的Golang ORM

rem是Retro Entity Mapper三个字母简写。一种新的Golang ORM。

  • PostgreSQL 和 MySQL 方言。SQLite 即将推出。
  • 使用相同模型语法的数据和架构迁移。
  • 优化外键和一对多预取。
  • 接口可扩展查询生成器。可用于特定于数据库的功能。
  • 与直接使用数据库/sql 的性能差异可以忽略不计。
  • 与数据库/sql 连接和驱动程序解耦。
  • 根据需要部分或完全回退到安全参数化的 SQL 格式。
  • 零代码生成 模型只是可能具有您自己的字段和方法的结构。
  • 具有显式 null 和非 null 类型的标准化安全性。
  • 事务和 golang 上下文支持。
  • 子查询、连接、选择性获取、地图扫描等。

模型是定义表模式的结构:

type Accounts struct {
    Id   int64  `db:"id" primary_key:"true"`
    Name string `db:"name" db_max_length:"100"`
    Junk string
}

在上述结构定义中,Id 和 Name 是账户中的列。它们的列由 db 字段标记定义。Id 也是自动递增主键。Name 的最大字符长度为 100。REM 会忽略 Junk 字段。

定义模型后,在应用程序启动时注册一次,然后查询数据库。

// rem.Register[To]() 会缓存模型的计算结构。
rem.Register[Accounts]()

// rem.Use[To]() 返回模型的查询创建器.
rows, err := rem.Use[Accounts]().All(db)

// 您还可以重复使用 rem.Register[To]() 和 rem.Use[To]() 返回的 Model[To] 实例。
accounts := rem.Use[Accounts]()
rows1, err1 := accounts.Filter("name", "=", "foo").All(db)
rows2, err2 := accounts.Filter("name", "=", "bar").All(db)

// 注册并使用同一型号的不同台面。
rem.Register[Accounts](rem.Config{Table: "groups"})
groups := rem.Use[Accounts](rem.Config{Table: "groups"})

一对多关系表

type Accounts struct {
    Group rem.NullForeignKey[Groups] `db:"group_id"`
    Id    int64                      `db:"id" primary_key:"true"`
    Name  string                     `db:"name"`
}

type Groups struct {
    Accounts rem.OneToMany[Accounts] `related_column:"group_id"`
    Id       int64                   `db:"id" primary_key:"true"`
    Name     string                  `db:"name" db_max_length:"100"`
}
// 只需执行一次额外查询即可获取所有相关account。
groups, err := rem.Use[Groups]().
    FetchRelated("Accounts").
    Filter("id", "IN", interface{}{10, 20, 30}).
    Sort("name", "-id").
    All(db)

if err != nil {
    panic(err)
}
for _, group := range groups {
    // group *Groups
    // group.Accounts.Rows *Accounts
}

REM 可以优化外键和一对多记录查找。这是通过 FetchRelated 方法实现的,该方法可以获取任意数量的字符串,这些字符串代表要预取的关系字段。

无论从关系的哪一边开始,也无论最初要获取多少条记录,REM 都只会执行一次额外的查询来进行预获取。

事务
REM 通过 Transaction(*sql.Tx) 方法支持事务。

tx, _ := db.Begin()

_, err := rem.Use[Accounts]().
    Filter("id", "=", 100).
    Transaction(tx).
    Delete(db)

if err != nil {
    tx.Rollback()
    panic(err)
}

err = tx.Commit()
if err != nil {
    panic(err)
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK