核心引擎 · Session会话

Session会话

所有的操作都要先获得一个mysql的session会话,因此封装一个session用于实现与数据库的交互。新建session文件夹并在session文件夹新建session.go文件。

现在的代码结构为:

1
2
3
4
5
6
7
mygorm/
log/
|--log.go
|--log_test.go
session/
|--session.go
|--go.mod

Session会话管理

  • my-gorm/session/session.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
    package 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() 这三个原生方法,所以接下来就封装这三个方法。

  • my-gorm/session/session.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
    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
2
3
4
5
6
7
8
mygorm/
log/
|--log.go
|--log_test.go
session/
|--session.go
|--session_test.go
|--go.mod
  • my-gorm/session/session_test.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
    43
    package 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)
    }
    上面的代码是一个 Go 语言的测试函数,用于测试数据库查询功能。
  1. 导入了必要的包:
  • database/sql:用于与数据库进行交互。
  • _ “github.com/go-sql-driver/mysql”:这是一个 MySQL 驱动程序的匿名导入,用于注册 MySQL 驱动程序,使得 sql.Open 函数能够打开 MySQL 数据库连接。
  • github.com/scott-pb/mygorm/log:上一篇的日志包,用于记录日志信息。
  • testing:Go 语言的测试框架包。
  1. 定义一个名为 TestSession_QueryRowQuery 的测试函数。

  2. 在测试函数中进行了以下操作:

  • 使用 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

测试结果如下图:

session-test.png

可以看到执行时log日志记录了sql语句,且对应文件位置。




本站由 [PengBin](/) 使用 [Stellar 1.26.3](https://github.com/xaoxuu/hexo-theme-stellar/tree/1.26.3) 主题创建。 本博客所有文章除特别声明外,均采用 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) 许可协议,转载请注明出处。