type
Post
status
Published
date
Jul 4, 2020
slug
summary
sqlx 可以认为是Go语言内置database/sql的封装,在内置database/sql基础上提供了功能强大的扩展
tags
Golang
category
技术分享
icon
password

介绍

💡
简化操作,提高效率,sqlx 可以认为是Go语言内置database/sql的封装,在内置database/sql基础上提供了功能强大的扩展

安装

go get github.com/jmoiron/sqlx

基本使用

连接

  • 和原生方式差别不大
  • 使用sqlx.Connect 方法,相当于 Open+Ping 两个操作,获得一个数据库连接对象db
var db *sqlx.DB func initDB() (err error) { dsn := "user:password@tcp(127.0.0.1:3306)/sql_test?charset=utf8mb4&parseTime=True" // 也可以使用MustConnect连接不成功就panic db, err = sqlx.Connect("mysql", dsn) if err != nil { fmt.Printf("connect DB failed, err:%v\n", err) return } //设置最大连接数等 db.SetMaxOpenConns(20) db.SetMaxIdleConns(10) return }

查询

💡
注意:该库使用反射拿到结构体user的值,因此user字段名需要大写
  • 单行查询
    • 使用db的 Get 方法进行单行查询,参数是(查询结果保存目标对象,语句,参数...)
    • 对象参数需要传递指针
    • func queryRowDemo() { sqlStr := "select id, name, age from user where id=?" var u user err := db.Get(&u, sqlStr, 1) if err != nil { fmt.Printf("get failed, err:%v\n", err) return } fmt.Printf("id:%d name:%s age:%d\n", u.ID, u.Name, u.Age) }
  • 多行查询
    • 使用 Select 方法多行查询
    • 对象参数需要传递指针
    • func queryMultiRowDemo() { sqlStr := "select id, name, age from user where id > ?" var users []user //定义保存批量数据的user切片 err := db.Select(&users, sqlStr, 0) // if err != nil { fmt.Printf("query failed, err:%v\n", err) return } fmt.Printf("users:%#v\n", users) }
       

      增删改

      和原生方式基本相同
      // 插入数据 func insertRowDemo() { sqlStr := "insert into user(name, age) values (?,?)" ret, err := db.Exec(sqlStr, "沙河小王子", 19) if err != nil { fmt.Printf("insert failed, err:%v\n", err) return } theID, err := ret.LastInsertId() // 新插入数据的id if err != nil { fmt.Printf("get lastinsert ID failed, err:%v\n", err) return } fmt.Printf("insert success, the id is %d.\n", theID) } // 更新数据 func updateRowDemo() { sqlStr := "update user set age=? where id = ?" ret, err := db.Exec(sqlStr, 39, 6) if err != nil { fmt.Printf("update failed, err:%v\n", err) return } n, err := ret.RowsAffected() // 操作影响的行数 if err != nil { fmt.Printf("get RowsAffected failed, err:%v\n", err) return } fmt.Printf("update success, affected rows:%d\n", n) } // 删除数据 func deleteRowDemo() { sqlStr := "delete from user where id = ?" ret, err := db.Exec(sqlStr, 6) if err != nil { fmt.Printf("delete failed, err:%v\n", err) return } n, err := ret.RowsAffected() // 操作影响的行数 if err != nil { fmt.Printf("get RowsAffected failed, err:%v\n", err) return } fmt.Printf("delete success, affected rows:%d\n", n) }
       

      结果绑定

      DB.NamedExec方法用来绑定SQL语句与结构体,或map中的同名字段
      func insertUserDemo()(err error){ sqlStr := "INSERT INTO user (name,age) VALUES (:name,:age)" _, err = db.NamedExec(sqlStr, map[string]interface{}{ "name": "李白", "age": 9000, }) return }
       
      NamedQueryDB.NamedExec类似,但支持查询。
       

      事务操作

      db.Beginx() tx.Exec()
      func transactionDemo2()(err error) { tx, err := db.Beginx() // 开启事务 if err != nil { fmt.Printf("begin trans failed, err:%v\n", err) return err } defer func() { if p := recover(); p != nil { tx.Rollback() panic(p) // re-throw panic after Rollback } else if err != nil { fmt.Println("rollback") tx.Rollback() // err is non-nil; don't change it } else { err = tx.Commit() // err is nil; if Commit returns error update err fmt.Println("commit") } }() sqlStr1 := "Update user set age=20 where id=?" rs, err := tx.Exec(sqlStr1, 1) if err!= nil{ return err } n, err := rs.RowsAffected() if err != nil { return err } if n != 1 { return errors.New("exec sqlStr1 failed") } sqlStr2 := "Update user set age=50 where i=?" rs, err = tx.Exec(sqlStr2, 5) if err!=nil{ return err } n, err = rs.RowsAffected() if err != nil { return err } if n != 1 { return errors.New("exec sqlStr1 failed") } return err }
 
 
Java 四种本地文件拷贝方式比较和测试Golang原生库操作MySQL