今天学习一下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
| 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 engine.ID(1).Get(&user) log.Println("查出数据,ID:", user.ID)
has, err = engine.Where("UserName = ?", "root").Get(&user) checkErr(err) log.Println("查出数据", has, "ID:", user.ID)
user = User{UserName: "root"} engine.Get(&user) log.Println("查出数据,ID:", user.ID)
var users []User engine.Where("UserName = ?", "root").Find(&users) for _, item := range users { log.Println("查出数据:", item) }
engine.Find(&users, &User{ UserName: "root", }) for _, item := range users { log.Println("查出数据:", item) }
usersMap := make(map[int]User, 0) err = engine.Find(&usersMap) checkErr(err) for _, item := range usersMap { log.Println("查出数据:", item) }
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{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
| 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"
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, "条数据")
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
| affected, err = engine.Table(new(User)).ID(3).Update(map[string]interface{}{"UserPwd": "update"})
|
这种方式是正确的,下面这种结果不正确
1 2
| affected, err = engine.Table("User").ID(3).Update(map[string]interface{}{"UserPwd": "update"})
|
记录一下