核心引擎 · Session会话
Session会话
所有的操作都要先获得一个mysql的session会话,因此封装一个session用于实现与数据库的交互。新建session文件夹并在session文件夹新建session.go文件。
现在的代码结构为:
1 | mygorm/ |
Session会话管理
-
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
38package session
import (
"database/sql"
"strings"
)
// Session 包含一个数据库连接(db)、SQL语句构建器(sql)和SQL变量列表(vars)。
type Session struct {
db *sql.DB
sql strings.Builder
vars []interface{}
}
// New 创建并返回一个新的 Session 实例,接受一个数据库连接作为参数。
func New(db *sql.DB) *Session {
return &Session{db: db}
}
// Reset 重置会话,清空之前的SQL语句和变量。
func (s *Session) Reset() {
s.sql.Reset()
s.vars = nil
}
// GetDB 返回当前会话的数据库连接。
func (s *Session) GetDB() *sql.DB {
return s.db
}
// Raw 一个 SQL 查询字符串和可变数量的参数,并将它们添加到 Session 结构体的内部状态
func (s *Session) Raw(sql string, values ...interface{}) *Session {
s.sql.WriteString(sql)
s.sql.WriteString(" ")
s.vars = append(s.vars, values...)
return s
} Session 结构体包含了一个指向数据库连接的指针(db),一个用于构建SQL语句的字符串构建器(sql)和一个用于存储SQL语句中的变量的切片(sqlVars)。
New 函数是一个构造函数,用于创建并返回一个新的 Session 实例,接受一个数据库连接作为参数。
Reset 方法用于重置会话状态,清空之前构建的SQL语句和变量。
GetDB 方法返回当前会话的数据库连接。
这个包的目的是为了提供一个简单的会话管理工具,使得在应用程序中执行数据库操作更加方便和模块化。它使用了Go语言的database/sql包来处理数据库连接。
Session会话SQL 操作
在基础 Go连接Mysql 中,介绍了Exec()、Query() 和 QueryRow() 这三个原生方法,所以接下来就封装这三个方法。
-
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
44
45// Exec 执行数据库写操作,并返回 sql.Result 对象和可能的错误
func (s *Session) Exec() (sql.Result, error) {
// 在函数返回前调用 Reset 方法,确保资源清理
defer s.Reset()
// 调用 GetDB 方法获取数据库连接,执行 SQL 语句并返回结果
r, err := s.GetDB().Exec(s.sql.String(), s.vars...)
if err != nil {
// 如果发生错误,记录错误信息
log.Error(err)
}
// 记录调试信息,包括执行的 SQL 语句和参数
log.Debug(s.sql.String(), s.vars)
return r, err
}
// Query 执行数据库查询操作,并返回 *sql.Rows 对象和可能的错误
func (s *Session) Query() (*sql.Rows, error) {
// 在函数返回前调用 Reset 方法,确保资源清理
defer s.Reset()
// 调用 GetDB 方法获取数据库连接,执行 SQL 语句并返回结果集
rows, err := s.GetDB().Query(s.sql.String(), s.vars...)
if err != nil {
// 如果发生错误,记录错误信息
log.Error(err)
}
return rows, err
}
// QueryRow 执行数据库查询操作,并返回 *sql.Row 对象
func (s *Session) QueryRow() *sql.Row {
// 在函数返回前调用 Reset 方法,确保资源清理
defer s.Reset()
// 调用 GetDB 方法获取数据库连接,执行 SQL 语句并返回单行结果
row := s.GetDB().QueryRow(s.sql.String(), s.vars...)
// 记录调试信息,包括执行的 SQL 语句和参数
log.Debug(s.sql.String(), s.vars)
return row
} Exec: 执行不返回行的 SQL 查询(例如 INSERT、UPDATE、DELETE)。它返回一个 sql.Result 和一个错误。
Query: 执行返回行的 SQL 查询(例如 SELECT)。它返回一个 *sql.Rows 和一个错误。
QueryRow: 执行预期返回单个行的 SQL 查询。它返回一个 *sql.Row。
测试
在session目录下新增session_test.go测试文件,用于测试方法。
现在的代码结构为:
1 | mygorm/ |
- my-gorm/session/session_test.go上面的代码是一个 Go 语言的测试函数,用于测试数据库查询功能。
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
43package session
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"github.com/scott-pb/mygorm/log"
"testing"
)
func TestSession_QueryRowQuery(t *testing.T) {
// 打开 MySQL 数据库连接
db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/my-gorm")
if err != nil {
log.Error(err)
return
}
// 设置与数据库的最大打开连接数
db.SetMaxOpenConns(100)
// 设置空闲中的最大连接数
db.SetMaxIdleConns(10)
// 创建一个新的 Session 实例
session := New(db)
// 定义 User 结构体,用于扫描查询结果
type User struct {
id uint // 用户 ID
name string // 用户名
birthday string // 出生日期
gender uint8 // 性别
}
var user User
// 查询数据库表 mg_user 中的第一行数据
row := session.Raw("select * from mg_user limit 1").QueryRow()
// 扫描查询结果并将数据填充到 User 结构体中
row.Scan(&user.id, &user.name, &user.birthday, &user.gender)
// 输出查询到的用户信息
log.Info(user)
}
- 导入了必要的包:
- database/sql:用于与数据库进行交互。
- _ “github.com/go-sql-driver/mysql”:这是一个 MySQL 驱动程序的匿名导入,用于注册 MySQL 驱动程序,使得 sql.Open 函数能够打开 MySQL 数据库连接。
- github.com/scott-pb/mygorm/log:上一篇的日志包,用于记录日志信息。
- testing:Go 语言的测试框架包。
定义一个名为 TestSession_QueryRowQuery 的测试函数。
在测试函数中进行了以下操作:
- 使用 sql.Open 函数打开了一个 MySQL 数据库连接,连接地址为 “root:123456@tcp(127.0.0.1:3306)/my-gorm”。如果打开连接时出现错误,则记录错误信息并返回。
- 使用 db.SetMaxOpenConns 和 db.SetMaxIdleConns 方法设置了数据库连接池的最大打开连接数和最大空闲连接数。
- 创建了一个新的 Session 实例,传入了已打开的数据库连接。
定义了一个结构体 User,用于存储从数据库查询结果中获取的用户信息。
调用 session.Raw(“select * from mg_user limit 1”).QueryRow() 方法执行了一条 SQL 查询,限制返回结果为数据库表 mg_user 中的第一行数据,并返回一个 *sql.Row 对象。 - 使用 row.Scan 方法将查询结果中的字段值扫描并赋值给 User 结构体中的字段。
- 最后,使用日志包中的 log.Info 方法输出了查询到的用户信息。
go test测试
1 | go test |
测试结果如下图:
可以看到执行时log日志记录了sql语句,且对应文件位置。