Xorm学习笔记

xorm 是一个用Go 语言编写的简单而强大的ORM (对象关系映射) 库。它允许开发者用Go 语言的结构体来操作数据库,而无需直接编写SQL 语句,从而简化了数据库操作。xorm 可以将数据库表映射到Go 语言的结构体,并提供了一系列方便的方法来执行常见的数据库操作,如创建、读取、更新和删除(CRUD) 等。支持多种数据库。

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

安装xorm

安装

1
go get xorm.io/xorm

安装具体数据库的驱动(以MySQL为例)

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

demo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
	"fmt"

	_ "github.com/go-sql-driver/mysql"
	"xorm.io/xorm"
)

func main() {
	var err error
	// 连接数据库,需要账户密码和连接地址以及数据库名
	e, err := xorm.NewEngine("mysql", "username:password@tcp(ip:port)/dbname?charset=utf8")
	if err != nil {
		panic(err)
	}
	// 测试链接
	if err2 := e.Ping(); err2 != nil {
		panic(err2)
	} else {
		fmt.Println("连接成功")
	}
	defer e.Close() //延迟关闭数据库
}

创建引擎

使用xorm来操作数据库,需要先用xorm.NewEngine()创建一个引擎,或者使用xorm.NewEngineGroup()创建引擎组。Engine Group是xorm的主从读写分离解决方案,主要配置内容为主库和从库的配置,以及从库的负载策略。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 方法一
conns := []string{ 
	"root:123456@/test?charset=utf8mb4", // 第一个默认是master 
	"root:123456@/test1?charset=utf8mb4", // 第二个开始都是slave 
	"root:123456@/test2?charset=utf8mb4", 
} 
eg, err := xorm.NewEngineGroup("mysql", conns)

// 方法二
master, err := xorm.NewEngine("mysql", "root:123456@/test?charset=utf8mb4") if err != nil { 
	panic(err) 
}

创建完成 EngineGroup 之后,并没有立即连接数据库,此时可以通过 eg.Ping() 来进行数据库的连接测试是否可以连接到数据库,该方法会依次调用引擎组中每个Engine的Ping方法。另外对于某些数据库有连接超时设置的,可以通过起一个定期Ping的Go程来保持连接鲜活。EngineGroup 可以通过 eg.Close() 来手动关闭,但是一般情况下可以不用关闭,在程序退出时会自动关闭。

创建表

  1. 创建结构体
1
2
3
4
5
6
type Users struct {
	Id     int       `xorm:"pk"`
	Name   string    `xorm:"varchar(25) notnull unique comment('姓名')"`
	Age    uint8     `xorm:"default 18"`
	Create time.Time `xorm:"created"`
}

字段格式:

  • 字段名:默认使用结构体字段名(驼峰式会自动转为下划线式,如 UserName → user_name)。
  • 数据类型:Go 类型决定数据库类型(如 int → INTstring → VARCHAR)。
  • 标签(Tag):通过 `xorm:"..."` 定义列属性。【可选】

关键字pk说明:是否是主键,如果有多个字段都使用了此标记,则为复合主键 关键字autoincr说明:是否是自增,主键如果被设置为自动递增,插入的时候可以省略主键

  1. 创建表
1
2
err3 := e.Sync2(new(Users)) // 同步数据库结构  
fmt.Printf("err3: %v\n", err3)

初始状态下,数据库test中没有表users,调用Sync2()方法会根据User的结构自动创建一个users表。执行后,通过desc users查看表结构:

建表也可以用Sync方法,Sync2已经弃用,Sync 不会对已有表结构的字段进行任何的更改、删除操作,而只会进行增加字段操作。如果表users已经存在,Sync()方法会对比User结构与表结构的不同,对表做相应的修改。这个修改操作只局限于添加字段操作。

增删改查

  1. 插入数据:使用engine.Insert(&user),可以插入单条数据或者批量插入多条数据。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 插入单条数据
user := Users{  
    Id:   1,  
    Name: "Amy",  
    Age:  17,  
}   
i, _ := e.Insert(&user)  

// 批量插入多条数据
users := make([]*Users, 0, 4)  
users = append(users,  
    &Users{Id: 3, Name: "Alice", Age: 18},  
    &Users{Id: 4, Name: "Susan", Age: 15},  
    &Users{Id: 5, Name: "Joicy", Age: 18},  
    &Users{Id: 6, Name: "Lily", Age: 19},  
)  
i, _ := e.Insert(&users)

Insert传入切片时,数据分成多条SQL进行插入,如果其中一条插入时出错,可能造成后续数据不能继续插入。 Insert传入切片指针时,数据会拼接为一条SQl执行能够插入,由于各数据库SQL长度限制,需要注意不要使用太长的切片内容。如果数据量太大,需要分片进行插入。官方建议每条长度不要超过150。

  1. 查询数据:查询主要使用GetFind方法,Get查找一个结果,Find则为多个结果,结果会保存的出入参数中。
1
2
3
4
5
6
7
8
9
// Alias 别名  Get单条查询
user := Users{}  
e.Alias("ua").Where("ua.id=1").And("ua.name='Tom'").Get(&user)  
fmt.Printf("姓名:%s, 年龄:%d\n", user.Name, user.Age)  

// Find多条查询 
var names []string   
e.Table("users").Select("Name").Where("Age=?", 18).Find(&names)  
fmt.Printf("姓名: %v\n", names)

查询参数:

  • Where("a = ? AND b = ?", 1, 2): where 条件
  • Alias("o").Where("o.name = ?", name): 表别名
  • .Where(...).And(...): AND
  • .Asc("id") .Desc("time") OrderBy(string):结果排序,可以组合使用
  • .ID(1):查询主键
  • Or(interface{}, …interface{}): OR条件
  • Select(string):Select内容
  • SQL(string, …interface{}):SQL内容
  • .In("cloumn", 1, 2, 3): IN
  • .Distinct("age", "department"): 归类去重
  • Table(nameOrStructPtr interface{}):传入表名称或者结构体指针,如果传入的是结构体指针,则按照IMapper的规则提取出表名
  • Limit(int, …int):限制获取的数目,第一个参数为条数,第二个参数表示开始位置,如果不传则为0
  • GroupBy(string)
  • Count: 统计数据数量
  • Exist: 判断某个记录是否存在,比Get,Exist性能更好
  • Sum:求和数据可以使用Sum, SumInt, SumsSumsInt 四个方法
  1. 修改数据:通过engine.Update()实现,可以传入结构指针或map[string]interface{}。对于传入结构体指针的情况,xorm只会更新非空的字段。如果一定要更新空字段,需要使用Cols()方法显示指定更新的列。使用Cols()方法指定列后,即使字段为空也会更新
1
2
3
user := Users{}  
user.Name = "JuLi"  
e.ID(1).Update(&user)  

  1. 删除数据 软删除:逻辑删除,记录留在表里;如果表中有 deleted_at 或类似的软删除字段,可以配置软删除:engine.ID(1).Delete(&Users{}),执行删除实际上是更新deleted_at 字段,标记删除时间。
1
2
3
4
5
type Users struct { 
	Id int `xorm:"pk autoincr"` 
	Name string `xorm:"varchar(25)"` 
	DeletedAt time.Time `xorm:"deleted"` // 软删除标记
}

真正删除:无视软删除,engine.ID(1).Unscoped().Delete(&Users{})

xorm vs gorm

gorm 和 xorm 都是 Go 语言中流行的 ORM(对象关系映射)框架,它们可以帮助开发者更高效地与数据库交互,功能类似。xorm更接近原生sql。

参考:

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计
本博客已稳定运行