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) }
|