golang中使用sqlx進行MySQL操作

實現

增刪改查

package main

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

var db *sqlx.DB
var dsn = "root:Monica216@@@tcp(localhost:3306)/myblog?charset=utf8"

func initDB() (err error) {
	// 數據庫信息
	// 用戶名:密碼@tcp(ip:端口)/數據庫的名字
	//dsn := "test:sdafdsf22@tcp(1.1.1.1:3306)/myblog?charset=utf8"

	// 連接數據庫
	db, err = sqlx.Connect("mysql", dsn)
	if err != nil {
		return
	}
	db.SetMaxOpenConns(10) // 設置數據庫連接池的最大連接數
	db.SetMaxIdleConns(5)  // 設置最大空閒連接數
	return
}

type User struct {
	ID     int    `db:"id"`
	Name   string `db:"name"`
	Age    int    `db:"age"`
	Status int    `db:"status"`
}

func (u User) Value() (driver.Value, error) {
	return []interface{}{u.Name, u.Age}, nil
}

func main() {
	err := initDB()
	if err != nil {
		fmt.Printf("init DB failed, err:%v\n", err)
		return
	}

	// 查詢單行數據
	sqlStr1 := `select id, name, age from User where id=?`
	var u User
	db.Get(&u, sqlStr1, 1)
	fmt.Printf("u:%#v\n", u)

	var userList []User
	sqlStr2 := `select id,name, age from User`
	err = db.Select(&userList, sqlStr2)
	if err != nil {
		fmt.Printf("select failed, err:%v\n", err)
		return
	}
	fmt.Printf("userList:%#v\n", userList)
	queryMultiRowDemo()
	//insertRowDemo()
	//updateRowDemo()
	deleteRowDemo()
	//insertUserDemo()
	//namedQuery()
	//transactionDemo1()
	//BatchInsertUsers()

}

func queryMultiRowDemo() {
	sqlStr := "select id, name, age from User where id > ?"
	var users []User
	err := db.Select(&users, sqlStr, 1)
	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, 88, 4)
	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, 9)
	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)
}

// 插入數據
func insertUserDemo() (err error) {
	sqlStr := "insert into User(name,age) values (:name,:age)"
	_, err = db.NamedExec(sqlStr,
		map[string]interface{}{
			"name": "奮鬥",
			"age":  24,
		})
	return
}

func namedQuery() {
	sqlStr := "select * from User where name=:name"
	// 使用map做命名查詢
	rows, err := db.NamedQuery(sqlStr, map[string]interface{}{"name": "wunai"})
	if err != nil {
		fmt.Printf("db.NamedQuery failed, err:%v\n", err)
		return
	}
	defer rows.Close()

	for rows.Next() {
		var u User
		err := rows.StructScan(&u)
		if err != nil {
			fmt.Printf("scan failed,err:%v\n", err)
			continue
		}
		fmt.Printf("namedQuery User:%#v\n", u)
	}

	u := User{
		Name: "奮鬥",
	}
	// 使用結構體命名查詢, 根據結構體字段的db tag進行映射
	rows, err = db.NamedQuery(sqlStr, u)
	if err != nil {
		fmt.Printf("db.NamedQuery failed,err:%v\n", err)
		return
	}
	defer rows.Close()
	for rows.Next() {
		var u User
		err := rows.StructScan(&u)
		if err != nil {
			fmt.Printf("scan failed, err:%v\n", err)
			continue
		}
		fmt.Printf("namedQuery User:%#v\n", u)
	}
}

// 事務操作
func transactionDemo1() (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)
		} else if err != nil {
			fmt.Printf("rollback, err = %#v", err)
			tx.Rollback()
		} else {
			err = tx.Commit()
			fmt.Println("commit")
		}
	}()

	sqlStr1 := "update User set age = 30 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
}


批量操作

package main

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

// BatchInsertUsers 自行構造批量插入的語句
func BatchInsertUsers(users []*User) error {
	// 存放 (?, ?) 的slice
	valueStrings := make([]string, 0, len(users))
	// 存放values的slice
	valueArgs := make([]interface{}, 0, len(users)*2)
	// 遍歷users準備相關數據
	for _, u := range users {
		// 此處佔位符要與插入值的個數對應
		valueStrings = append(valueStrings, "(?, ?)")
		valueArgs = append(valueArgs, u.Name)
		valueArgs = append(valueArgs, u.Age)
	}
	// 自行拼接要執行的具體語句
	stmt := fmt.Sprintf("INSERT INTO user (name, age) VALUES %s",
		strings.Join(valueStrings, ","))
	_, err := db.Exec(stmt, valueArgs...)
	return err
}

// BatchInsertUsers2 使用sqlx.In幫我們拼接語句和參數, 注意傳入的參數是[]interface{}
func BatchInsertUsers2(users []interface{}) error {
	query, args, _ := sqlx.In(
		"INSERT INTO user (name, age) VALUES (?), (?), (?)",
		users..., // 如果arg實現了 driver.Valuer, sqlx.In 會通過調用 Value()來展開它
	)
	fmt.Println(query) // 查看生成的querystring
	fmt.Println(args)  // 查看生成的args
	_, err := db.Exec(query, args...)
	return err
}

// BatchInsertUsers3 使用NamedExec實現批量插入
func BatchInsertUsers3(users []*User) error {
	_, err := db.NamedExec("INSERT INTO user (name, age) VALUES (:name, :age)", users)
	return err
}

func main() {
	err := initDB()
	if err != nil {
		panic(err)
	}
	defer db.Close()
	u1 := User{Name: "七米", Age: 18}
	u2 := User{Name: "q1mi", Age: 28}
	u3 := User{Name: "小王子", Age: 38}

	// 方法1
	users := []*User{&u1, &u2, &u3}
	err = BatchInsertUsers(users)
	if err != nil {
		fmt.Printf("BatchInsertUsers failed, err:%v\n", err)
	}

	// 方法2
	users2 := []interface{}{u1, u2, u3}
	err = BatchInsertUsers2(users2)
	if err != nil {
		fmt.Printf("BatchInsertUsers2 failed, err:%v\n", err)
	}

	// 方法3
	users3 := []*User{&u1, &u2, &u3}
	err = BatchInsertUsers3(users3)
	if err != nil {
		fmt.Printf("BatchInsertUsers3 failed, err:%v\n", err)
	}
	//users4 := make([]interface{}, 3)
	//uu1 := User{Name: "hello1", Age: 11}
	//uu2 := User{Name: "hello2", Age: 11}
	//uu3 := User{Name: "hello3", Age: 11}
	//users4[0] = uu1
	//users4[1] = uu2
	//users4[2] = uu3
	//fmt.Printf("users4 = %#v", users4)
	//BatchInsertUsers2(users4)
}



參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章