OOro

快速开始

打开数据库、同步模型,并运行泛型 CRUD。

Oro 围绕三个入口设计:

db.Use[Product]()      // 模型查询
db.Table("products")   // 裸表查询
db.Raw("select ...")   // 原生 SQL

模型查询返回结构体。裸表和 Raw 查询默认返回 oro.Map,也可以通过 MapTo[T]() 映射成 DTO。

安装

go get github.com/duxweb/oro

开发阶段当前目标是 go1.27rc1

source ~/.gvm/scripts/gvm && gvm use go1.27rc1

定义模型

package main

import oro "github.com/duxweb/oro"

type Product struct {
    oro.Model
    Code  string
    Price uint
    Stock oro.Null[int]
}

func (Product) Define(s *oro.SchemaBuilder) {
    s.Table("products")
    s.Field("Code").String().Size(64).Unique()
    s.Field("Price").Uint().Default(0)
    s.Field("Stock").Int().Nullable()
}

Define 是结构定义的唯一来源。结构体保持干净,数据库细节不散落在 tag 里。

打开连接并同步

ctx := context.Background()

db, err := oro.Open(oro.Config{
    Connections: map[string]oro.ConnectionConfig{
        "default": {Driver: sqlite.Open("app.db")},
    },
})
if err != nil {
    log.Fatal(err)
}
defer db.Close(ctx)

if err := db.Register(Product{}); err != nil {
    log.Fatal(err)
}
if err := db.Sync(ctx); err != nil {
    log.Fatal(err)
}

Register 接收实现了 Define 的模型。Sync 会创建缺失表、字段和索引;破坏性变更不会静默执行。

创建和查询

created, err := db.Use[Product]().Create(ctx, &Product{
    Code:  "P001",
    Price: 100,
    Stock: oro.NullOf(10),
})

found, err := db.Use[Product]().Where("Code", "P001").First(ctx)
rows, err := db.Use[Product]().Where("Price", ">=", 100).OrderBy("ID").Get(ctx)

返回规则保持简单:

方法 查不到
First(ctx) nil, nil
Find(ctx, id) nil, nil
Get(ctx) 空切片
Count(ctx) 0, nil

更新和删除

_, err = db.Use[Product]().Where("Code", "P001").Update(ctx, oro.Map{
    "Price": 120,
    "Stock": oro.NullZero[int](),
})

_, err = db.Use[Product]().Where("Code", "P001").Delete(ctx)

UpdateDelete 必须带条件,避免误操作整张表。

直接查表

row, err := db.Table("products").Create(ctx, oro.Map{
    "code":  "P002",
    "price": 200,
})

rows, err := db.Table("products").Where("price", ">=", 100).Get(ctx)

裸表查询使用数据库列名,并返回 oro.Map

type ProductView struct {
    ID    uint64
    Code  string
    Price uint
}

view, err := db.Table("products").
    Select("id", "code", "price").
    MapTo[ProductView]().
    First(ctx)
编辑此页