飞哥(fizzday) b2055e17f0 upsert
2024-04-02 15:39:02 +08:00
2024-04-02 15:39:02 +08:00
2018-01-25 04:46:23 +08:00
2024-03-02 14:59:16 +08:00
2024-03-02 14:59:16 +08:00
2024-03-27 09:25:13 +08:00
2024-04-02 15:39:02 +08:00
2024-03-29 10:56:30 +08:00
2024-03-16 15:05:28 +08:00
2024-03-27 09:25:13 +08:00
2024-03-27 09:25:13 +08:00
2024-03-14 18:29:37 +08:00
2024-03-05 14:27:51 +08:00
2024-03-05 14:27:51 +08:00
orm
2024-03-04 11:08:55 +08:00
2018-01-23 22:38:40 +08:00
2024-03-05 14:27:51 +08:00
2024-03-04 16:35:28 +08:00
2024-03-29 10:56:30 +08:00
2024-03-02 14:59:16 +08:00
2024-03-21 09:16:48 +08:00
2024-03-27 09:25:13 +08:00
2024-03-16 11:12:17 +08:00
2024-04-02 15:39:02 +08:00
2024-03-21 09:16:48 +08:00
2024-03-27 09:25:13 +08:00
2024-03-27 09:25:13 +08:00

GoRose ORM V3

PHP Laravel ORM 的 go 实现, 与 laravel 官方文档保持一致 https://laravel.com/docs/10.x/queries .
分为 go 风格 (struct 结构绑定用法) 和 php 风格 (map 结构用法).
php 风格用法, 完全可以使用 laravel query builder 的文档做参考, 尽量做到 1:1 还原.

安装

目前还处于beta阶段, 请谨慎使用. 由于没有打 tag, 只能使用 go mod 的方式引入

# go.mod

require github.com/gohouse/gorose/v3 master

概览

go风格用法

package main

import (
    gorose "github.com/gohouse/gorose/v3"
    // 引入驱动,这里可以将驱动独立出去,避免多驱动的不必要引入,只要实现了 gorose.IDriver 接口即可,理论上可以支持任意数据库
    _ "github.com/gohouse/gorose/v3/drivers/mysql"
)

type User struct {
	Id    int64  `db:"id,pk"`   // 这里的 pk 是指主键
	Name  string `db:"name"`
	Email string `db:"email"`
    
    // 定义表名字,等同于 func (User) TableName() string {return "users"}, 二选一即可
	// TableName string `db:"users" json:"-"` 
}
func (User) TableName() string {
    return "users"
}

var gr = gorose.Open("mysql", "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true")

func db() *gorose.Database {
	return gr.NewDatabase()
}
func main() {
    // select id,name,email from users limit 1;
    var user User
    db().To(&user)

    // insert into users (name,email) values ("test","test@test.com");
    var user = User{Name: "test", Email: "test@test.com"}}
    db().Insert(&user)

    // update users set name="test2" where id=1;
    var user = User{Id: 1, Name: "test2"}
    db().Update(&user)

    // delete from users where id=1;
    var user = User{Id: 1}
    db().Delete(&user) 
}

php风格用法

// select id,name,email from users where id=1 or name="test" group by id having id>1 order by id desc limit 2 offset 2
db().Table("users").
    Select("id","name","email").
    Where("id", "=", 1).OrWhere("name", "test").
    GroupBy("id").Having("id", ">", 1).
    Limit(2).Offset(2).OrderBy("id", "desc").
    Get()
// 等同于
var users []User
db().Where("id", "=", 1).OrWhere("name", "test").
    GroupBy("id").Having("id", ">", 1).
    Limit(2).Offset(2).OrderBy("id", "desc").
    To(&users)

由此可以看出, 除了对 表 模型的绑定区别, 其他方法通用

配置

单数据库连接, 可以直接同官方接口一样用法

var gr = gorose.Open("mysql", "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true")

也可以用

var conf1 = gorose.Config{
    Driver:          "mysql",
    DSN:             "root:123456@tcp(localhost:3306)/test?charset=utf8mb4&parseTime=true",
    Prefix:          "tb_",
    Weight:          0,
    MaxIdleConns:    0,
    MaxOpenConns:    0,
    ConnMaxLifetime: 0,
    ConnMaxIdleTime: 0,
}
var gr = gorose.Open(conf)

或者使用读写分离集群,事务内,自动强制从写库读数据

var gr = gorose.Open(
    gorose.ConfigCluster{
        WriteConf: []gorose.Config{
            conf1,
            conf2,
        },
        ReadConf: []gorose.Config{
            conf3,
            conf4,
        }
    },
)

事务

// 全自动事务, 有错误会自动回滚, 无错误会自动提交
// Transaction 方法可以接收多个操作, 同用一个 tx, 方便在不同方法内处理同一个事务
db().Transaction(func(tx gorose.TxHandler) error {
    tx().Insert(&user)
    tx().Update(&user)
    tx().To(&user)
}

// 手动事务
tx = db().Begin()
tx().Insert(&user)
tx().Update(&user)
tx().To(&user)
tx().Rollback()
tx().Commit()

// 全自动嵌套事务
db().Transaction(func(tx gorose.TxHandler) error {
    tx().Insert(&user)
    ...
    // 自动子事务
    tx().Transaction(func(tx2 gorose.TxHandler) error {
        tx2().Update(&user)
        ...
    }
}

// 手动嵌套事务
var tx = db().Begin()
// 自动子事务
tx().Begin() // 自动 savepoint 子事务
...
tx().Rollback()   // 自动回滚到上一个 savepoint
...
// 手动子事务
tx().SavePoint("savepoint1")    // 手动 savepoint 到 savepoint1(自定义名字)
...
tx().RollbackTo("savepoint1") // 手动回滚到自定义的 savepoint
tx().Commit()

update

在插入和更新数据时,如果使用 struct 模型作为数据对象的时候, 默认忽略类型零值,如果想强制写入,则可以从第二个参数开始传入需要强制写入的字段即可,如:

var user = User{Id: 1, Name: "test"}
// 这里不会对 sex 做任何操作, 
//update user set name="test" where id=1
db().Update(&user)
// 这里会强制将sex更改为0
//update user set name="test", sex=0 where id=1
db().Update(&user, "sex")
// 等同于
db().Table(&user).Where("id", 1).Update(map[string]any{"name": "test", "sex": 0}))

如果没有where条件,则会自动添加tag中指定了pk的字段作为条件,如: db:"id,pk", 因为指定了 pk,如果 id 的值不为0值, 则 id 会作为主键条件更新

insert

参考 update

delete

var user = User{Id: 1}
db().Delete(&user)
// 等同于
db().Table(&user).Where("id", 1).Delete()
// 要加上字段0值条件,只需要传入第二个字段,如:
// delete from users where id=1 and sex=0 and name=""
db().Delete(&user, "sex", "name")

table

  • 参数
    table 参数, 可以是字符串, 也可以是 User 结构体
db().Table(User{})
db().Table("users")
  • 取别名
db().Table(User{}, "u")
db().Table("users", "u")
  • 结果集查询
sub := db().Table("users").Select("id", "name")
db().Table(sub).Where("id", ">", 1).Get()

join

  • 简单用法
db().Table("users").Join(UserInfo{}, "user.id", "=", "user_info.user_id").Get()
  • 取别名
type UserInfo struct {
    UserId      int64   `db:"user_id"`
    TableName   string  `db:"user_info"`
}
// select * from users a inner join user_info b on a.id=b.user_id
db().Table("users", "u").Join(gorose.As(UserInfo{}, "b"), "u.id", "=", "b.user_id").Get()
// 等同于
db().Table(User{}, "u").Join(gorose.As("user_info", "b"), "u.id", "=", "b.user_id").Get()

gorose.As(UserInfo{}, "b") 中, user_info 取别名 b

  • 复杂用法
db().Table("users").Join(UserInfo{}, func(wh gorose.IJoinOn) {
    wh.On("a.id", "b.user_id").OrOn("a.sex", "b.sex")
}).Get()

where

  • sub query
// where id in (select user_id from user_info)
sub := db().Table("user_info").Select("user_id")
xxx.Where("id", "in", sub).Get()
  • where nested
// where id>1 and (sex=1 or sex=2)
xxx.Where("id",">", 1).Where(func(wh gorose.IWhere) {
    wh.Where("sex", 1).OrWhere("sex", 2)
})

Pluck

返回两列数据到一个map中,第一列为value,第二列为key

// select id,name from users
db().Table("users").Pluck("name", "id")
// 返回 map[<id>]<name>
// 得到 map[int64]string{1: "张三", 2: "李四"}

List

返回一列数据到一个数组中

// select id,name from users
db().Table("users").List("id")
// 返回 []<id>
// 得到 []int64{1,2,3}

To 查询结果绑定到对象

使用结构体字段作为 select 字段
使用结构体字段值作为 where 条件
查询结果绑定到结构体,支持一条或多条

// 查询一条数据
var user User
db().To(&user)

// 查询条件,一条数据
// select id,name,email from users where id=1
var user = User{Id: 1}
db().To(&user)

// 查询多条数据
var users []User
db().To(&users)

// 查询条件,多条数据
var users []User
db().Where("id", ">", 1).To(&users)

Bind 查询结果绑定到对象

仅仅用作查询结果的绑定
结构体字段,不作为查询字段和条件
常用作join或者手动指定字段查询绑定

type Result struct {
    Id    int64  `db:"id"`
    Aname string `db:"aname"`
    Bname string `db:"bname"`
}
var res Result
// select a.id, a.name aname, b.name bname from a inner join b on a.id=b.id where a.id>1
db().Table("a").Join("b", "a.id","b.aid").Select("a.id", "a.name aname","b.name bname").Where("a.id", ">", 1).Bind(&res)

查询字段的显示名字一定要跟 结构体的字段 tag(db) 名字相同, 否则不会被赋值
字段数量可以不一样

ListTo,PluckTo,ValueTo

var list []int
db().Table("users").ListTo("age", &list)
var pluck map[int64]string
db().Table("users").PluckTo("name","id", &pluck)
var value int
db().Table("users").ValueTo("age", &value)

SumTo,MaxTo,MinTo

var sum int
db().Table("users").SumTo("age", &sum)
var max int
db().Table("users").MaxTo("age", &max)
var min int
db().Table("users").MinTo("age", &min)

已经支持的 laravel query builder 方法

  • Table

  • Select

  • SelectRaw

  • AddSelect

  • Join

  • GroupBy

  • Having

  • HavingRaw

  • OrHaving

  • OrHavingRaw

  • OrderBy

  • Limit

  • Offset

  • Where

  • WhereRaw

  • OrWhere

  • OrWhereRaw

  • WhereBetween

  • OrWhereBetween

  • WhereNotBetween

  • OrWhereNotBetween

  • WhereIn

  • OrWhereIn

  • WhereNotIn

  • OrWhereNotIn

  • WhereNull

  • OrWhereNull

  • WhereNotNull

  • OrWhereNotNull

  • WhereLike

  • OrWhereLike

  • WhereNotLike

  • OrWhereNotLike

  • WhereExists

  • WhereNotExists

  • WhereNot

  • Get

  • First

  • Find

  • Insert

  • Update

  • Delete

  • Max

  • Min

  • Sum

  • Avg

  • Count

  • InsertGetId

  • Upsert

  • InsertOrIgnore

  • Exists

  • DoesntExist

  • Pluck

  • List

  • Value

  • Increment

  • Decrement

  • IncrementEach

  • DecrementEach

  • Truncate

  • Union

  • UnionAll

  • SharedLock

  • LockForUpdate

额外增加的 api

  • Replace
  • Page
  • LastSql
  • To
  • Bind
  • ListTo
  • PluckTo
  • ValueTo
  • SumTo
  • MaxTo
  • MinTo
Description
GoRose(go orm), a mini database ORM for golang, which inspired by the famous php framwork laravle's eloquent. It will be friendly for php developer and python or ruby developer. Currently provides six major database drivers: mysql,sqlite3,postgres,oracle,mssql, Clickhouse.
Readme MIT 15 MiB
Languages
Go 100%