美文网首页
go orm 库 xorm

go orm 库 xorm

作者: wayyyy | 来源:发表于2022-04-29 00:00 被阅读0次

原文转载自:Go 每日一库之 xorm

Get

Get 用于查询单条数据:

type User struct {
    Id      int64
    Name    string
    Salt    string
    Age     int
    Passwd  string    `xorm:"varchar(200)"`
    Created time.Time `xorm:"created"`
    Updated time.Time `xorm:"updated"`
}

func main() {
    engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")

    user1 := &User{}
    has, _ := engine.ID(1).Get(user1)
    if has {
        fmt.Printf("user1:%v\n", user1)
    }

    user2 := &User{}
    has, _ = engine.Where("name=?", "dj").Get(user2)
    if has {
        fmt.Printf("user2:%v\n", user2)
    }

    user3 := &User{Id: 5}
    has, _ = engine.Get(user3)
    if has {
        fmt.Printf("user3:%v\n", user3)
    }

    user4 := &User{Name: "pipi"}
    has, _ = engine.Get(user4)
    if has {
        fmt.Printf("user4:%v\n", user4)
    }
}

上面演示了 3 种使用Get()的方式:

  • 使用主键engine.ID(1)查询主键(即id)为 1 的用户。
  • 使用条件语句:engine.Where("name=?", "dj")查询name = "dj"的用户。
  • 使用对象中的非空字段:user3设置了Id字段为 5,engine.Get(user3)查询id = 5的用户;user4设置了字段Name"pipi"engine.Get(user4)查询name = "pipi"的用户。

查询条件的使用不区分调用顺序,但是必须在Get()方法之前调用。后面介绍的查询,统计方法也是如此,可以在调用实际的方法前添加一些过滤条件。

除此之外xorm支持只返回指定的列(xorm.Cols())或忽略特定的列(xorm.Omit()):

func main() {
    engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")

    user1 := &User{}
    engine.ID(1).Cols("id", "name", "age").Get(user1)
    fmt.Printf("user1:%v\n", user1)

    user2 := &User{Name: "pipi"}
    engine.Omit("created", "updated").Get(user2)
    fmt.Printf("user2:%v\n", user2)
}

第一个查询使用Cols()方法指定只返回 id、name、age 这 3 列,第二个查询使用Omit()方法忽略列 created 和 updated。

Exist

Exist()方法查询符合条件的记录是否存在,它的返回与 Get() 方法一致,都是 (bool, error)
不同之处在于Get()会将查询得到的字段赋值给传入的对象。

Find

Get()方法只能返回单条记录,其生成的 SQL 语句总是有LIMIT 1Find()方法返回所有符合条件的记录,Find()需要传入对象切片的指针或 map 的指针:

func main() {
    engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")

    slcUsers:= make([]User, 1)
    engine.Where("age > ? and age < ?", 12, 30).Find(&slcUsers)
    fmt.Println("users whose age between [12,30]:", slcUsers)

    mapUsers := make(map[int64]User)
    engine.Where("length(name) = ?", 3).Find(&mapUsers)
    fmt.Println("users whose has name of length 3:", mapUsers)
}

map的键为主键,所以如果表为复合主键就不能使用这种方式了。

Iterate

Find()一样,Iterate()也是找到满足条件的所有记录,只不过传入了一个回调去处理每条记录:

func main() {
    engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")

    engine.Where("age > ? and age < ?", 12, 30).Iterate(&User{}, func(i int, bean interface{}) error {
        fmt.Printf("user%d:%v\n", i, bean.(*User))
        return nil
    })
}

如果回调返回一个非nil的错误,后面的记录就不会再处理了。

Rows

Rows()方法与Iterate()类似,不过返回一个Rows对象由我们自己迭代,更加灵活:

func main() {
    engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")

    rows, _ := engine.Where("age > ? and age < ?", 12, 30).Rows(&User{})
    defer rows.Close()

    u := &User{}
    for rows.Next() {
        rows.Scan(u)
        fmt.Println(u)
    }
}
Count
Sum
插入

使用engine.Insert()方法,可以插入单条数据,也可以批量插入多条数据:

func main() {
    engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")
    user := &User{Name: "lzy", Age: 50}

    affected, _ := engine.Insert(user)
    fmt.Printf("%d records inserted, user.id:%d\n", affected, user.Id)

    users := make([]*User, 2)
    users[0] = &User{Name: "xhq", Age: 41}
    users[1] = &User{Name: "lhy", Age: 12}

    affected, _ = engine.Insert(&users)
    fmt.Printf("%d records inserted, id1:%d, id2:%d", affected, users[0].Id, users[1].Id)
}
更新

注意:传入结构体指针的情况,xorm只会更新非空的字段,这里容易制造Bug。
如果一定要更新空字段,需要使用Cols()方法显示指定更新的列。使用Cols()方法指定列后,即使字段为空也会更新:

func main() {
  engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")
  engine.ID(1).Update(&User{Name: "ldj"})
  engine.ID(1).Cols("name", "age").Update(&User{Name: "dj"})
}

第一个Update()方法只会更新name字段,其他空字段不更新。第二个Update()方法会更新name和age两个字段,age被更新为 0。

删除

直接调用engine.Delete()删除符合条件的记录,返回删除的条目数量:

func main() {
    engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")

    affected, _ := engine.Where("name = ?", "lzy").Delete(&User{})
    fmt.Printf("%d records deleted", affected)
}
执行原始SQL

除了上面提供的方法外,xorm还可以执行原始的 SQL 语句:

func main() {
    engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")

    querySql := "select * from user limit 1"
    reuslts, _ := engine.Query(querySql)
    for _, record := range reuslts {
        for key, val := range record {
            fmt.Println(key, string(val))
        }
    }

    updateSql := "update `user` set name=? where id=?"
    res, _ := engine.Exec(updateSql, "ldj", 1)
    fmt.Println(res.RowsAffected())
}
排错

了便于排查可能出现的问题,xorm提供了 ShowSQL() 方法设置将执行的 SQL 同时在控制台中输出:

func main() {
    engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")
    engine.ShowSQL(true)

    user := &User{}
    engine.ID(1).Omit("created", "updated").Get(user)
    fmt.Printf("user:%v\n", user)
}

如果调试信息都输出到控制台并不利于我们查询,xorm可以设置日志选项,将日志输出到文件中:

func main() {
    engine, _ := xorm.NewEngine("mysql", "root:12345@/test?charset=utf8")
    f, err := os.Create("sql.log")
    if err != nil {
      panic(err)
    }

    engine.SetLogger(log.NewSimpleLogger(f))
    engine.Logger().SetLevel(log.LOG_DEBUG)
    engine.ShowSQL(true)

    user := &User{}
    engine.ID(1).Omit("created", "updated").Get(user)
    fmt.Printf("user:%v\n", user)
}

log.NewSimpleLogger(f)是xorm的子包xorm.io/xorm/log提供的简单日志封装,而非标准库log。

相关文章

网友评论

      本文标题:go orm 库 xorm

      本文链接:https://www.haomeiwen.com/subject/wsaxyrtx.html