mysql是關係型數據庫RDBMS(Relational database management system)的典型表明,也是後臺開發中打交道最多的一個組件。mysql
func InsertUser(user bean.User) (bool){
//開啓事務
tx, err := DB.Begin()
if err != nil{
fmt.Println("tx fail")
return false
}
//準備sql語句
stmt, err := tx.Prepare("INSERT INTO nk_user (`name`, `password`) VALUES (?, ?)")
if err != nil{
fmt.Println("Prepare fail")
return false
}
//將參數傳遞到sql語句中而且執行
res, err := stmt.Exec(user.UserName, user.Password)
if err != nil{
fmt.Println("Exec fail")
return false
}
//將事務提交
tx.Commit()
//得到上一個插入自增的id
fmt.Println(res.LastInsertId())
return true
}
複製代碼
func SelectAllUser() ([]bean.User) {
//執行查詢語句
rows, err := DB.Query("SELECT * from nk_user")
if err != nil{
fmt.Println("查詢出錯了")
}
var users []bean.User
//循環讀取結果
for rows.Next(){
var user bean.User
//將每一行的結果都賦值到一個user對象中
err := rows.Scan(&user.Id, &user.UserName, &user.Password)
if err != nil {
fmt.Println("rows fail")
}
//將user追加到users的這個數組中
users = append(users, user)
}
return users
}
複製代碼
這裏會發現,當字段比較多,有二三十個,sql語句都須要本身寫,同時scan還得指定每個字段去接收,若是類型同樣的錯位了,就是一個難以排查的事故。 同時,sql語句太長,也很差維護。在大型項目開發過程當中,幾乎全部團隊都會選擇用orm。git
ORM全稱是:Object Relational Mapping(對象關係映射),其主要做用是在編程中,把面向對象的概念跟數據庫中表的概念對應起來。舉例來講就是,我定義一個對象,那就對應着一張表,這個對象的實例,就對應着表中的一條記錄。github
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
func main() {
db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
defer db.Close()
}
複製代碼
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
db.NewRecord(user) // => returns `true` as primary key is blank
db.Create(&user)
db.NewRecord(user) // => return `false` after `user` created
複製代碼
// Get first record, order by primary key
db.First(&user)
//// SELECT * FROM users ORDER BY id LIMIT 1;
// Get last record, order by primary key
db.Last(&user)
//// SELECT * FROM users ORDER BY id DESC LIMIT 1;
// Get all records
db.Find(&users)
//// SELECT * FROM users;
// Get record with primary key (only works for integer primary key)
db.First(&user, 10)
//// SELECT * FROM users WHERE id = 10;
複製代碼
// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
//// SELECT * FROM users WHERE name = 'jinzhu' limit 1;
// Get all matched records
db.Where("name = ?", "jinzhu").Find(&users)
//// SELECT * FROM users WHERE name = 'jinzhu';
db.Where("name <> ?", "jinzhu").Find(&users)
// IN
db.Where("name in (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// Time
db.Where("updated_at > ?", lastWeek).Find(&users)
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
複製代碼
db.Save(&data) gorm支持一個Save命令,其語意是當model中Id主鍵有值時,更新該model。無值時建立一條。若是是須要先從數據庫讀model,再更新寫入,就很適合用Save操做。golang
gromdb是鏈式的結構: 每一個操做返回的都是gorm.DB db.Where().Limit().Offset()sql
在業務開發中,能夠靈活運用,好比有type類型,status狀態兩個字段,若是填了才過濾,不填就返回全部的,能夠按下面這樣寫:數據庫
if status != "" {
db.Where("status = ?", status)
}
if type != 0 "" {
db.Where("type = ?", type)
}
db.Find([]*Data)
複製代碼
callback是一個不得不提的能力,顧名思義,回調,即 經過它能夠方便地對gorm進行二次封裝。目前gorm 支持以下callback編程
好比,若是有加密需求,就能夠在beforeCreate時運用加密。 在afterFind運用解祕。如下是一個簡單的條件判斷示例:數組
func (u *User) BeforeUpdate() (err error) {
if u.readonly() {
err = errors.New("read only user")
}
return
}
// Rollback the insertion if user's id greater than 1000 func (u *User) AfterCreate() (err error) { if u.Id > 1000 { err = errors.New("user id is already greater than 1000") } return } 複製代碼
若是callback中有失敗,那麼整個事物都會回滾。bash
單獨建一個model文件夾,一個model一個文件,能夠理解爲一個表一個文件。 在其中用類型的方法,封裝好針對這個model直接訪問的方法。 同時定義個對外暴露的變量Nsp,外面直接經過這個Nsp訪問方法。 若是有針對多表的訪問和聯合,應該再封裝一個更高層。這樣代碼結構會比較清晰。app