sqlx

项目地址

1. 准备工作

-- 用户表信息
create table if not exists test.`user`
(
`id` int not null auto_increment primary key,
`userid` int not null comment '用户id',
`username` varchar(256) not null comment '用户名',
`password` varchar(256) not null comment '用户密码',
`avatar` varchar(256) not null comment '用户头像',
`create_time` datetime default null comment '创建时间',
`update_time` datetime default null on update CURRENT_TIMESTAMP comment '更新时间'
) comment '用户表信息';

insert into test.`user` (`id`, `userid`, `username`, `password`, `avatar`) values (0, 702, '郑弘文', 'BY', 'www.johnetta-homenick.info');
insert into test.`user` (`id`, `userid`, `username`, `password`, `avatar`) values (1, 8565380, '朱鸿涛', 'sm', 'www.ardell-turner.co');
insert into test.`user` (`id`, `userid`, `username`, `password`, `avatar`) values (2, 6, '吴弘文', 'glL', 'www.cristobal-rempel.info');

2. 安装

database/sql 是Go操作数据库的标准库之一,它提供了一系列的接口方法,用于访问数据库(MySQL, SQLite, Oracle, PostgreSQL),它并不会提供数据库独有的方法,独有的方法由数据库驱动去实现。

在通常工作中,使用sqlx包来操作数据库,sqlx是基于标准sql的扩展,可以通过sqlx操作各种类型的数据,如将查询的数据转为结构体等。

go get "github.com/go-sql-driver/mysql"
go get "github.com/jmoiron/sqlx"

3. 使用

连接数据库

package main

import (
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

func main() {
    mysqlDB := connectMySQL()
    defer mysqlDB.Close()
}

var (
    userName  string = "root"
    password  string = "root"
    ipAddress string = "192.168.1.104"
    port      string = "3306"
    dbName    string = "test"
    charset   string = "utf8mb4"
)

// 连接数据库
func connectMySQL() *sqlx.DB {
    dbstr := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s", userName, password, ipAddress, port, dbName, charset)

    db, err := sqlx.Open("mysql", dbstr)
    fmt.Println(err)

    ping(db)
    return db
}

func ping(DB *sqlx.DB) {
    err := DB.Ping()
    if nil != err {
        fmt.Println("ping failed")
    } else {
        fmt.Println("ping success")
    }
}

Exec增删改

package main

import (
   "fmt"
   "sqlx_demo/demo1"
   "time"
)

func main() {
   mysqlDB := demo1.ConnectMySQL()
   defer mysqlDB.Close()

   // mysqlDB
   // Exec 执行SQL语句
   insertSQL := "insert into user(userid, username, password, avatar, create_time, update_time) values (?,?,?,?,?,?)"
   result, err := mysqlDB.Exec(insertSQL, 10000, "root", "123456", "avatar.png", time.Now(), time.Now())
   if nil != err {
      fmt.Println("数据插入失败", err)
      return
   }

   id, _ := result.LastInsertId()
   fmt.Println("数据插入成功, last id: ", id)

   updateSQL := "update user set username = 'root' where id = 1"
   result2, err := mysqlDB.Exec(updateSQL)
   rowNum, _ := result2.RowsAffected()
   fmt.Println("数据更新成功, affected rows: ", rowNum)

   // 删除
   deleteSQL := "delete from user where id = 2"
   resul3, err := mysqlDB.Exec(deleteSQL)
   rowNum, _ = resul3.RowsAffected()
   fmt.Println("删除成功, affected rows:", rowNum)
}

Query查询

Query方法返回的是一个sql.Rows类型的结果集,也可以用来查询多个字段的数据,不过需要定义多个字段的变量进行接收,迭代后者的next()方法,然后用Scan()方法给对应类型变量赋值,以便取出结果,最后再把结果集关闭(释放连接)。

func main() {
    mysqlDB := ConnectMySQL()
    defer mysqlDB.Close()

    querySQL := "select * from test.user"
    rows, err := mysqlDB.Query(querySQL)
    if err != nil {
        fmt.Println("数据查询失败", err)
        return
    }

    // rows
    // rows.Next()
    for rows.Next() {
        var id, userid int
        var username, password, avatar, create_time, update_time string

        // rows.Scan
        rows.Scan(&id, &userid, &username, &password, &avatar, &create_time, &update_time)

        fmt.Println(id, userid, username, password, avatar, create_time, update_time)
    }
    rows.Close()

}

Get和Select方法

func (db *DB) Get(dest interface{}, query string, args ...interface{}) error

Get:将查询的一条记录,保存到结构体。

func (db *DB) Select(dest interface{}, query string, args ...interface{}) error

Select:将查询的多条记录保存的结构体的切片中。

func main() {
    mysqlDB := ConnectMySQL()
    defer mysqlDB.Close()

  // 结构体的字段名首字母必须大写
    type user struct {
        Id         int    `db:"id"`
        UserId     int    `db:"userid"`
        UserName   string `db:"username"`
        Password   string `db:"password"`
        Avatar     string `db:"avatar"`
        CreateTime string `db:"create_time"`
        UpdateTime string `db:"update_time"`
    }

    // 相当于var userData 后传入*user
    userData := new(user)
    mysqlDB.Get(userData, "select * from test.user where id = 3")
    fmt.Println(userData)

    var userSlice []user
    // Select(指针)
    err := mysqlDB.Select(&userSlice, "select * from test.user")
    if nil != err {
        fmt.Println(err)
    }

    for i := range userSlice {
        fmt.Println(userSlice[i])
    }
}

4. 线程池

4.1. 说明

只用sqlx.Open()函数创建连接池,此时只是初始化了连接池,并没有连接数据库,连接时惰性的,只有调用sqlx.DB的方法时,此时才真正用到了连接,连接池才会创建连接。

4.2. 配置

DB.SetMaxIdleConns(n int)设置连接池中的保持连接的最大连接数,默认是0,表示连接池不会保持数据库连接的状态。

DB.SetMaxOpenConn(n int)设置打开数据库的最大连接数,包含正在使用的连接和连接池的连接。默认值是0,表示无限制。

DB.SetConnMaxLifeTime(d time.Duration)设置连接可以被使用的最长有效时间,如果过期,连接将被拒绝。

4.3. 数据库连接重试次数

sqldx中的方法帮我们做了很多事情,我们不用考虑连接失败的情况,当调用方法进行数据库操作的时候,如果连接失败,sqlx中的方法会帮我们处理,它会自动连接2次。

其他方法也有这种处理,变量maxBadConnRetries是如果连接失败的尝试的次数,默认是2.

Copyright © rootwhois.cn 2021-2022 all right reserved,powered by GitbookFile Modify: 2023-03-05 10:55:52

results matching ""

    No results matching ""