上一篇文章我們進行了資料操作,都是使用佔位符的方式來操作的
我們們其實可以使用 mysql 預處理的方式來操作這些
那麼我們一起來看看什麼是已處理呢?
什麼是預處理?
瞭解什麼是預處理,我們可以來對比一下,普通的 sql 語句執行過程和 預處理的執行過程
普通 sql 語句執行過程:
- 客戶端對 SQL 語句進行 佔位符 替換得到完整的 sql 語句
- 客戶端傳送完整 sql 語句到 mysql 服務端
- mysql 服務端執行完整的 sql 語句並將結果返回給客戶端
預處理執行過程:
把 sql 語句分成兩部
- 命令部分
- 資料部分
- 先把命令部分傳送給 mysql 服務端,mysql 服務端進行 sql 預處理
- 然後把資料部分傳送給 mysql 服務端, mysql 服務端對 sql 語句進行佔位符替換
- mysql 服務端執行完整的 sql 語句並將結果返回給客戶端
透過步驟和流程,我們大概知道預處理肯定比普通的 sql 執行快
那麼預處理有啥好處?
- 最佳化 mysql 伺服器重複執行 sql 的方法,可以提升伺服器效能,提前讓伺服器編譯,一次編譯多次
執行,節省後續編譯的成本 - 避免 sql 注入的問題
//預處理 插入資料操作
func prepareInfo(db *sql.DB) {
sqlInfo := "insert into user (name,age)values(?,?)"
stmt, err := db.Prepare(sqlInfo)
if err != nil {
fmt.Println("Exec err : ", err)
return
}
ret, err := stmt.Exec("花豬2", 28)
if err != nil {
fmt.Println("stmt Exec err : ", err)
return
}
ret, err = stmt.Exec("花豬3", 28)
if err != nil {
fmt.Println("stmt Exec err : ", err)
return
}
rows, err := ret.RowsAffected()
if err != nil {
fmt.Println("stmt Exec err : ", err)
return
}
fmt.Println("rows = ", rows)
}
Go實現 MySQL 的事務
- 開啟事務處理,會有回滾機制,全部成功了,且提交成功,才算事務處理成功
func (db *DB) Begin() (*Tx, error)
事務開始func (tx *Tx) Commit() error
事務提交func (tx *Tx) Rollback() error
事務回滾func trasaction(db *sql.DB) { //開啟一個事務 tx, err := db.Begin() if err != nil { if tx != nil { tx.Rollback() } fmt.Printf("Begin err :%v", err) return } sqlStr := "update user set name='xxx' where id=?" _, err = tx.Exec(sqlStr, 9) if err != nil { if tx != nil { tx.Rollback() } fmt.Printf("Exec err :%v", err) return } sqlStr = "update user set name='xxx' where id=?" _, err = tx.Exec(sqlStr, 6) if err != nil { if tx != nil { tx.Rollback() } fmt.Printf("Exec err :%v", err) return } //提交事務 err = tx.Commit() if err != nil { if tx != nil { tx.Rollback() } fmt.Printf("Commit err :%v", err) return } fmt.Println("commit success ") }
sqlx使用
我們們還可以使用第三方庫 sqlx
- 安裝第三方庫 sqlx ,
go get github.com/jmoiron/sqlx
第三方庫可以提交高開發效率,簡化開發操作
package main import ( "fmt" "github.com/jmoiron/sqlx" _ "github.com/go-sql-driver/mysql" // 註釋掉後異常 _ 呼叫初始化函式 ) var db *sqlx.DB func insertInfo() { sqlStr := "insert into user(name,age)values(?,?)" res, err := db.Exec(sqlStr, "xxx", 2) if err != nil { fmt.Printf("Exec err : %v", err) return } id, err := res.LastInsertId() if err != nil { fmt.Printf("LastInsertId err : %v", err) return } fmt.Printf("id == %d", id) rows, err := res.RowsAffected() if err != nil { fmt.Printf("RowsAffected err : %v", rows) return } fmt.Printf("rows == %d", rows) return } func main() { var err error dsn := "root:123456@tcp(127.0.0.1:3306)/go_test?charset=utf8mb4" db, err = sqlx.Connect("mysql", dsn) if err != nil { fmt.Printf("Connect err : %v\n", err) return } db.SetMaxOpenConns(20) db.SetMaxIdleConns(10) //插入資料 insertInfo() }
gin + mysql + rest full api
當然 之前說到的 http 包裡面的方法實現,我們也不需要用它了,我們們也可以交給框架,真的是可以做到高效實現業務,但同時,自己下來還是要去對具體的實現原理多研究研究
實踐如下步驟:
- 匯入
github.com/gin-gonic/gin
庫 建立
users
表,id,name,telephone
欄位CREATE TABLE `users` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `name` VARCHAR(20) DEFAULT '', `telephone` VARCHAR(20) DEFAULT '', PRIMARY KEY(`id`) )ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
<img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d8827a4583814e2cb9567af33ddbd3eb~tplv-k3u1fbpfcp-zoom-1.image" style="zoom:100%;"/>
上圖是實踐過程中產生的資料
- 包裝對資料庫的增刪改查操作
- 寫路由的操作
需要原始碼進行參考對比的 xdm ,可以評論或者私信,感謝能有反饋
歡迎點贊,關注,收藏
朋友們,你的支援和鼓勵,是我堅持分享,提高質量的動力
好了,本次就到這裡
技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。
我是小魔童哪吒,歡迎點贊關注收藏,下次見~