开发者

Go使用XORM操作MySQL的陷阱盘点分析

开发者 https://www.devze.com 2023-12-02 08:58 出处:网络 作者: frank
目录使用 XORM 操作 mysql 的陷阱类型零值自增 id更新 created 字段总结使用 XORM 操作 MySQL 的陷阱
目录
  • 使用 XORM 操作 mysql 的陷阱
    • 类型零值
    • 自增 id
    • 更新 created 字段
  • 总结

    使用 XORM 操作 MySQL 的陷阱

    虽然使用 ORM 操作 MySQL 比直接使用标准库 `sql`[1] 和三方 MySQL 数据库驱动包[2]操作 MySQL 更加方便,但是也会遇到一些陷阱。

    类型零值

    在 golang 中,每个数据类型都有各自的类型零值,比如 int 的零值是 0,string 的零值是 ''等。

    示例代码:

    package main
    import (
     EAfgRKFR"fmt"
     _ "github.com/go-sql-driver/mysql"
     "xorm.io/xorm"
    )
    func main() {
     // 创建 Engine
     engine, err := xorm.NewEngine("mysql", "root:root@/example?charset=utf8")
     defer func() {
      err = engine.Close()
      if err != nil {
       fmt.Printf("engine close err=%v\n", err)
       return
      }
     }()
     if err != nil {
      fmt.Printf("init xorm engine fail, err=%v\n",php err)
      return
     }
     // 更新数据
     example := &Example{
      Title: "go",
      View:  0,
     }
     condi := &Example{
      Id: 2,
     }
     affected, err := engine.Update(example, condi)
     if err != nil {
      fmt.Printf("Update err=%v\n", err)
      return
     }
     fmt.Printf("affected=%d\n", affected)
    }
    type Example struct {
     Id      int    `json:"id" form:"id"`
     Title   string `json:"title" form:"title"`
     View    int    `json:"view" form:"view"`
     Created int    `json:"created" form:"created" xorm:"created"`
     Updated int    `json:"updated" form:"updated" xorm:"updated"`
    }

    阅读上面这段代码,我们可以发现示例代码中将 id=2 的数据 view 字段更新为 0,因为 0 是 int 的类型零值,XORM 的 Update 方法会自动忽略类型零值,所以该数据 view 字段的值没有更改。

    但是,在实际项目开发中,我们可能需要将某个字段的值更新为该字段类型的类型零值,此时我们该怎么操作呢?

    affected, err := engine.Cols("title", "view").Update(example, condi)
    

    我们可以使用 Cols() 方法,指定需要更新的字段,这样即便需要更新字段的值是该字段类型的类型零值,也可以正常更改。

    提示:建议在设计数据库表时,字段的值尽量使用非类型零值。

    自增 id

    在插入数据时,我们可能需要返回自增 id,我们先看一段代码:

    // 插入数据
    example := &Example{
      Title: "php",
      View:  90,
    }
    affected, err := engine.Insert(example)
    if err != nil {
      fmt.Printf("Insert err=%v\n", err)
      return
    }
    fmt.Printf("affected=%v\n", affected)

    阅读上面这段代码,我们插入一条数据,返回结果是影响行数和错误信息,而不是直接返回该条数据的自增 id。

    可能有些读者朋友们会接着使用查询方法,查询最新一条数据的 id,在并发请求数低的场景中,该方法是可以查到新插入数据的自增 ipythond。

    但是在并发请求数高的场景中,该方法查到的最新一条数据的 id,未必是我们刚插入的数据的自增 id。

    id := example.Id
    fmt.Printf("affected=%v || id=%d\n", affected, id)
    

    阅读上面这段代码,我们想要获取新插入数据的自增 id,直接 example.Id 即可获取,但是前提条件是结构体中,id 字段使用 xorm:"autoincr" 标签。

    更新 created 字段

    我们在结构体中,使用标签 xorm:created 和 xorm:updated 即可自动编程插入当前时间。

    但是,使用 xorm:created 标签的字段,只有在第一次插入数据时写入当前时间,此后将不再会更改;使用 xorm:updated 标签的字段,在第一次插入数据时写入当前时间,此后每次 Update 操作,时间都会更改。

    如果我们的业务需求是需要更改使用 xorm:created 标签的字段,可以做到吗?

    // 更改数据
    example := &Example{
      Title: "JavaScript",
      View:  98,
    }
    condi := &Example{
      Id: 2,
    }
    affected, err := engine.Update(example, condi)
    if err != nil {
      fmt.Printf("Update err=%v\n", err)
      return
    }
    fmt.Printf("affected=%d\n", affected)

    阅读上面这段代码,我们http://www.devze.com发现执行 Update 方法之后,使用 xorm:updated 标签的字段的值被更改,而使用 xorm:created 标签的字段的值没被更改。

    我们换一种更新数据的方式,代码如下:

    // 更改数据
    sql := "UPDATE example SET title=?, view=?, created=? WHERE id=?"
    res, err := engine.Exec(sql, "python", 60, time.Now().Unix(), 2)
    if err != nil {
      fmt.Printf("Update err=%v\n", err)
      return
    }
    affected, err := res.RowsAffected()
    if err != nil {
      fmt.Printf("RowsAffected err=%v\n", err)
      return
    }
    fmt.Printf("affected=%d\n", affected)
    

    阅读上面这段代码,我们可以发现使用 Exec 方法执行原生 SQL 可以满足我们的需求。

    总结

    本文我们介绍了使用 XORM 操作 MySQL 时,新手读者朋友们可能会遇到的陷阱,希望可以给大家带来一些帮助,更多关于Go XORM操作MySQL的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消