go使用xorm操作mysql

今天学习一下go语言对mysql的操作,因为以前在c#中习惯了用orm操作,所以今天了解了一下,尝试下用go语言的xorm操作mysql数据库.

xorm地址: https://github.com/go-xorm/xorm


###1. xorm安装

1
go get github.com/go-xorm/xorm

另外我们需要连接mysql,所以需要MySQL的驱动

1
go get github.com/go-sql-driver/mysql

###2. xorm创建连接
xorm将连接实例称为引擎,一个连接就是一个引擎,我们测试只需要一个连接即可,如果需要连接多个mysql,新建多个引擎就可以了

1
2
// 新建orm引擎
engine, err := xorm.NewEngine("mysql", "root:pwd@tcp(192.168.2.100:3307)/XormTest?charset=utf8")

###3. 设置字段映射方式

由于我们程序中的结构体和数据库中的命名方式可能不相同,比如驼峰命名和匈牙利命名,为了将不同命名方式的表名和字段对应起来,xorm提供了三种映射方式

  • SnakeMapper 支持struct为驼峰式命名,表结构为下划线命名之间的转换,这个是默认的Maper;
  • SameMapper 支持结构体名称和对应的表名称以及结构体field名称与对应的表字段名称相同的命名;
  • GonicMapper 和SnakeMapper很类似,但是对于特定词支持更好,比如ID会翻译成id而不是i_d。

我们数据库和结构体采用相同的命名方式,所以设置为SameMapper

1
2
// 设置字段映射方法
engine.SetMapper(core.SameMapper{})

###4. 插入数据
先新建一个结构体,并在数据库中新建对应的表

1
2
3
4
5
6
7
type User struct {
ID int `xorm:"pk autoincr"`
UserName string
UserPwd string
CreatedAt time.Time `xorm:"created"`
Flag int
}
  • ID 后面的标签,是xorm的属性标记,pk主键,autoincr自增长,其他可查看官方doc

对应数据库表:

数据插入使用Insert方法,传入一个结构体指针,返回影响行数和error

1
2
3
4
5
6
7
8
9
// 插入数据
newUser := User{
UserName: "root",
UserPwd: "test",
Flag: 1,
}
affected, err = engine.Insert(&newUser)
checkErr(err)
log.Println("新插入", affected, "条数据,ID:", newUser.ID)

###5. 查询数据
查询方法比较多,根据使用环境选择就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
var user User
// ID获取单条
engine.ID(1).Get(&user)
log.Println("查出数据,ID:", user.ID)

// where获取单条
has, err = engine.Where("UserName = ?", "root").Get(&user)
checkErr(err)
log.Println("查出数据", has, "ID:", user.ID)

// user结构体中已有的非空数据来获得单条数据
user = User{UserName: "root"}
engine.Get(&user)
log.Println("查出数据,ID:", user.ID)

// find 获取多条 where
var users []User
engine.Where("UserName = ?", "root").Find(&users)
for _, item := range users {
log.Println("查出数据:", item)
}

// find 获取多条 结构体中已有的非空数据来获得
engine.Find(&users, &User{
UserName: "root",
})
for _, item := range users {
log.Println("查出数据:", item)
}

// find map
usersMap := make(map[int]User, 0)
err = engine.Find(&usersMap)
checkErr(err)
for _, item := range usersMap {
log.Println("查出数据:", item)
}

// find 查询单个字段
var ids []int
err := engine.Table(new(User)).Cols("ID").Find(&ids)
checkErr(err)
log.Println("查出IDs:", ids)
  • 知识点:Get()方法中传入的结构体指针不只有指定表的作用,其实例中不为0值的字段将作为查询条件,比如上面的
    1
    2
    3
    4
    // user结构体中已有的非空数据来获得单条数据
    user = User{UserName: "root"}
    engine.Get(&user)
    log.Println("查出数据,ID:", user.ID)

###6. 是否存在
xorm提供了exist方法判断查询的数据是否存在,在不需要查出数据而仅需要判断的时候,性能比Get要好,官方推荐

1
2
3
4
5
6
7
8
9
10
11
12
// Exist 判断是否存在
has, err = engine.Exist(&User{
UserName: "root",
})
checkErr(err)
log.Println("数据是否存在:", has)
has, err = engine.Where("UserName = ?", "root").Exist(&User{})
checkErr(err)
log.Println("数据是否存在:", has)
has, err = engine.Table(new(User)).Where("UserName = ?", "root").Exist()
checkErr(err)
log.Println("数据是否存在:", has)

###7. 更新数据
更新是常用的方法,xorm提供了非0值更新,和指定列更新的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
user := new(User)

user.UserName = "update"
user.UserPwd = "update"

// 非0值更新
affected, err = engine.ID(1).Update(user)
checkErr(err)
log.Println("更新", affected, "条数据")

// 指定列更新
affected, err = engine.ID(2).Cols("UserName").Update(user)
checkErr(err)
log.Println("更新", affected, "条数据")

// map更新
affected, err = engine.Table(new(User)).ID(3).Update(map[string]interface{}{"UserPwd": "update"})
checkErr(err)
log.Println("更新", affected, "条数据")
  • 使用map更新的时候,需要使用Table方法指定数据表

###8. 删除数据
删除方法比较简单,指定ID删除

1
2
3
4
user := new(User)
affected, err = engine.ID(id).Delete(user)
checkErr(err)
log.Println("删除ID为", id, "的", affected, "条数据")
  • 删除一般用的比较少,通常逻辑删除,xorm提供了一种软删除,可以查看doc

###9. 事务支持
事务用的还是比较多的,xorm的事务也比较简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 事务
session := engine.NewSession()
defer session.Close()

err = session.Begin()
checkErr(err)

// 插入数据
newUser := User{
UserName: "root",
UserPwd: "test",
Flag: 1,
}
affected, err = engine.Insert(&newUser)
if err != nil {
session.Rollback()
checkErr(err)
}
err = session.Commit()
checkErr(err)
log.Println("新插入", affected, "条数据,ID:", newUser.ID)

###10 .总结
以上就是xorm的基本用法,只是列举了一些常用的东西,更多的请查看官方doc.
记录一个问题,在使用Table方法指定数据表的时候,如果直接传一个表明的字符串(“User”),查询出的数据不正确,不知道是不是用法有问题

1
2
// map更新
affected, err = engine.Table(new(User)).ID(3).Update(map[string]interface{}{"UserPwd": "update"})

这种方式是正确的,下面这种结果不正确

1
2
// map更新
affected, err = engine.Table("User").ID(3).Update(map[string]interface{}{"UserPwd": "update"})

记录一下