如果❤️我的文章有帮助,欢迎点赞、关注。这是对我继续技术创作最大的鼓励。更多往期文章在我的个人博客
本文介绍xorm。xorm是一个简单但强大的 Go 语言 ORM 库,使用它可以大大简化我们的数据库操作。
安装驱动
先安装:
$ go get xorm.io/xorm
如何还没有安装 MySQL
数据库驱动,需要执行以下命令安装对应的驱动:
$ go get github.com/go-sql-driver/mysql
连接数据库
使用xorm
来操作数据库,首先需要使用xorm.NewEngine()创建一个引擎。该方法的参数与sql.Open()参数相同。
package main
import (
"log"
"time"
_ "github.com/go-sql-driver/mysql"
"xorm.io/xorm"
)
func main() {
engine, err := xorm.NewEngine("mysql", "root:@/dianping?charset=utf8")
if err != nil {
log.Fatal(err)
}
}
同步数据库表结构
下面代码中,我们演示了xorm
的一个非常实用的功能,将数据库中的表与对应 Go 代码中的结构体做同步。
初始状态下,数据库dianping
中没有表student
,调用Sync2()方法会根据Student
的结构自动创建一个student
表。
如果表student
已经存在,Sync()方法会对比User结构与表结构的不同.
type Student 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, err := xorm.NewEngine("mysql", "root:@/dianping?charset=utf8")
if err != nil {
log.Fatal(err)
}
err = engine.Sync(new(Student))
if err != nil {
log.Fatal(err)
}
}
此修改只限于添加字段。 删除表中已有的字段会带来比较大的风险。如果我们User结构的Salt字段删除,然后执行程序。出现下面错误:
[xorm] [warn] 2021/03/29 22:44:38.528784 Table student has column salt but struct has not related field
查询
Get()
Get()方法用于查询单条数据,并使用返回的字段为传入的对象赋值:
func main() {
engine, err := xorm.NewEngine("mysql", "root:@/dianping?charset=utf8")
user1 := &Student{}
has, _ := engine.ID(1).Get(user1)
if has {
fmt.Printf("user1:%v\n", user1)
}
user2 := &Student{}
has, _ = engine.Where("name=?", "JJ").Get(user2)
if has {
fmt.Printf("user2:%v\n", user2)
}
user3 := &Student{Id: 5}
has, _ = engine.Get(user3)
if has {
fmt.Printf("user3:%v\n", user3)
}
user4 := &Student{Name: "Alex"}
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”的用户。 运行程序:
user1:&{1 CJ salt 18 123 2021-03-29 08:35:49 +0800 CST 2021-03-29 08:35:49 +0800 CST}
user3:&{5 cmy.K salt 15 123 2021-03-29 08:35:49 +0800 CST 2021-03-29 08:35:49 +0800 CST}
user4:&{6 Alex salt 19 123 2021-03-29 08:35:49 +0800 CST 2021-03-29 08:35:49 +0800 CST}
Process finished with exit code 0
查询条件的使用不区分调用顺序,但是必须在Get()方法之前调用。
实际上后面介绍的查询&统计方法也是如此,可以在调用实际的方法前添加一些过滤条件。
除此之外xorm支持只返回指定的列xorm.Cols()
或忽略特定的列xorm.Omit()
另外,为了便于排查可能出现的问题,xorm提供了ShowSQL()方法设置将执行的 SQL 同时在控制台中输出:
[xorm] [info] 2021/03/30 08:41:01.558169 [SQL] SELECT `id`, `name`, `salt`, `age`, `passwd`, `created`, `updated` FROM `student` WHERE `id`=? LIMIT 1 [1] - 1.1464ms
user1:&{1 CJ salt 18 123 2021-03-29 08:35:49 +0800 CST 2021-03-29 08:35:49 +0800 CST}
有时候,调试信息都输出到控制台并不利于我们查询,xorm可以设置日志选项,将日志输出到文件中:
func main() {
engine, err := xorm.NewEngine("mysql", "root:@/dianping?charset=utf8")
f, err := os.Create("sql.log")
if err != nil {
panic(err)
}
engine.SetLogger(log2.NewSimpleLogger(f))
engine.Logger().SetLevel(log2.LOG_DEBUG)
engine.ShowSQL(true)
user1 := &Student{}
has, _ := engine.ID(1).Get(user1)
if has {
fmt.Printf("user1:%v\n", user1)
}
}
Iterate()
Iterate() 找到满足条件的所有记录,只不过传入了一个回调去处理每条记录:
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对象由我们自己迭代,更加灵活
rows, _ := engine.Where("age > ? and age < ?", 12, 30).Rows(&User{})
defer rows.Close()
u := &User{}
for rows.Next() {
rows.Scan(u)
fmt.Println(u)
}
还有更多的 像
- Get() 方法只能返回单条记录
- Exist() 方法查询符合条件的记录是否存在
- Find() 方法返回所有符合条件的记录
mapUsers := make(map[int64]User) engine.Where(“length(name) = ?”, 3).Find(&mapUsers)
- Sum() 方法返回某一字段求和
engine.Sum(&Student{}, "total")
- Count()方法统计满足条件的记录数量
engine.Where("age >= ?", 50).Count(&Student{})
插入数据
使用engine.Insert()方法,可以插入单条数据,也可以批量插入多条数据:
engine, err := xorm.NewEngine("mysql", "root:@/dianping?charset=utf8")
user := &Student{Name: "lzy", Age: 50}
affected, _ := engine.Insert(user)
更新数据
更新通过engine.Update()实现,可以传入结构指针或map[string]interface{}。对于传入结构体指针的情况,xorm只会更新非空的字段。 如果一定要更新空字段,需要使用Cols()方法显示指定更新的列。使用Cols()方法指定列后,即使字段为空也会更新:
engine, err := xorm.NewEngine("mysql", "root:@/dianping?charset=utf8")
engine.ID(1).Update(&User{Name: "ldj"})
engine.ID(1).Cols("name", "age").Update(&User{Name: "dj"})
engine.Table(&User{}).ID(1).Update(map[string]interface{}{"age": 18})
删除数据
直接调用engine.Delete()删除符合条件的记录,返回删除的条目数量:
engine, err := xorm.NewEngine("mysql", "root:@/dianping?charset=utf8")
affected, _ := engine.Where("name = ?", "lzy").Delete(&User{})
fmt.Printf("%d records deleted", affected)
执行原始SQL
engine, err := xorm.NewEngine("mysql", "root:@/dianping?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做了一个简单的介绍,xorm的特性远不止于此。感兴趣可在文档与Github中自行探索。
参考
- xorm GitHub:https://github.com/go-xorm/xorm
- xorm 手册:http://gobook.io/read/gitea.com/xorm/manual-zh-CN/