sqlx是基于Go内置database/sql包上的扩展,主要是简化了sql的使用过程, sqlx的sql.DB, sql.TX, sql.Stmt等保持底层实现不变,因此可以很方便地从database/sql切换到sqlx。sqlx另外还提供了一些功能:
go get github.com/jmoiron/sqlx
import (
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
func main(){
//连接数据库
// 只用 sqlx.Open() 函数创建连接池,此时只是初始化了连接池,并没有连接数据库.
// 连接都是惰性的,只有调用 sqlx.DB 的方法时,
// 此时才真正用到了连接,连接池才会去创建连接.
DB, err := sqlx.Open("mysql", "root:Guogr@12345@tcp(127.0.0.1:3306)/test?charset=utf8")
if err != nil {
fmt.Println("connect error:", err)
}
defer DB.Close()
err = DB.Ping()
if err != nil {
fmt.Println("connect ping error:", err)
}
// 连接池配置
DB.SetMaxIdleConns(100)
DB.SetMaxOpenConns(500)
DB.SetConnMaxIdleTime(5*time.Minute)
}
CREATE TABLE `person` (
`first_name` text,
`last_name` text,
`email` text,
`id` int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4;
使用struct需要注意,sqlx默认解析的tag为"db",未设置tag,默认情况下是直接将field名转换为小写,因此默认情况下不满足需求时,需要注意设置field的tag名,否则可能导致数据解析失败。
// Person 用户信息表
type Person struct {
Id int
FirstName string `db:"first_name"`
LastName string `db:"last_name"`
Email string `db:"email"`
}
sqlStr := "insert into person(first_name, last_name, email) values (?,?,?)"
ret, err := DB.Exec(sqlStr, "Jason", "Moron", "jmoiron@jmoiron.net")
if err != nil {
fmt.Println("插入出错", err)
return
}
theID, err := ret.LastInsertId() // 新插入数据的id
if err != nil {
fmt.Println("获取插入的id错误:", err)
return
}
fmt.Println("插入成功,id为:", theID)
ret, err = DB.NamedExec("INSERT INTO person (first_name, last_name, email) VALUES (:first_name, :last_name, :email)",
&Person{FirstName: "Jane", LastName: "Citizen",
Email: "jane.citzen@example.com"})
if err != nil {
fmt.Println("插入出错", err)
return
}
theID, err = ret.LastInsertId() // 新插入数据的id
if err != nil {
fmt.Println("获取插入的id错误:", err)
return
}
fmt.Println("插入成功,id为:", theID)
// batch insert with structs
personStructs := []Person{
{FirstName: "Ardie0", LastName: "Savea", Email: "asavea@ab.co.nz"},
{FirstName: "Sonny Bill0", LastName: "Williams", Email: "sbw@ab.co.nz"},
{FirstName: "Ngani0", LastName: "Laumape", Email: "nlaumape@ab.co.nz"},
}
ret, err = DB.NamedExec(`INSERT INTO person (first_name, last_name, email)
VALUES (:first_name, :last_name, :email)`, personStructs)
if err != nil {
fmt.Println("批量插入出错", err)
return
}
affectRows, err := ret.RowsAffected()
fmt.Printf("affect rows:%d, err=%v \n", affectRows, err)
// batch insert with maps
personMaps := []map[string]interface{}{
{"first_name": "Ardie1", "last_name": "Savea",
"email": "asavea@ab.co.nz"},
{"first_name": "Sonny Bill1", "last_name": "Williams",
"email": "sbw@ab.co.nz"},
{"first_name": "Ngani1", "last_name": "Laumape",
"email": "nlaumape@ab.co.nz"},
}
// 开启事务
tx, err := DB.Beginx()
_, err = tx.NamedExec(`INSERT INTO person (first_name, last_name, email)
VALUES (:first_name, :last_name, :email)`, personMaps)
if err != nil {
// 出错就回滚
tx.Rollback()
fmt.Println("批量插入出错", err)
return
}
tx.Commit()
// 2. 查询数据
sqlStr = "SELECT * FROM person WHERE last_name=:last_name"
// 使用map做命名查询
rows, _ := DB.NamedQuery(sqlStr, map[string]interface{}{"last_name": "Savea"})
defer rows.Close()
for rows.Next() {
var m Person
rows.StructScan(&m)
fmt.Println(m)
}
// 使用结构体做命名查询
var person = Person{LastName: "Savea"}
rows, _ = DB.NamedQuery(sqlStr, person)
defer rows.Close()
for rows.Next() {
var p Person
rows.StructScan(&p)
fmt.Println(p)
}
Get用于查询单条数据,Select则用于查询多条数据,需要注意的是方法中的dest必须满足要求,Get中不能为nil,Select中必须为slice。
// Get 查询
var personGet Person
err = DB.Get(&personGet, "select * from person where id=?", 1)
if err != nil {
fmt.Println("查询出错", err)
}
fmt.Println(personGet)
// Select 查询
var persons []Person
err = DB.Select(&persons, "select * from person where id > ?", 1)
if err != nil {
fmt.Println("查询出错", err)
}
fmt.Println(persons)
// 3 修改数据
sqlStr = "update person set last_name= ? where id = ?"
ret, err = DB.Exec(sqlStr, "Savea", 1)
if err != nil {
fmt.Println("更新失败", err)
return
}
n, err := ret.RowsAffected()
if err != nil {
fmt.Println("获取影响的行数失败:", err)
return
}
fmt.Println("更新成功,影响行数为:", n)
sqlStr = "delete from person where id = ?"
ret, err = DB.Exec(sqlStr, 1)
if err != nil {
fmt.Println("删除出错:", err)
return
}
n, err = ret.RowsAffected() // 操作影响的行数
if err != nil {
fmt.Println("获取操作影响的行数出错:", err)
return
}
fmt.Println("删除成功,影响的行数为:", n)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。