Go之XORM操作MySQL
創(chuàng)作不易感謝支持。
一條主寫Go和PHP的小菜鳥。平常有時間喜歡自己寫點東西,如有不對的地方,歡迎大佬指點。 個人博客:太陽上的雨天 地址:http://blog.caixiaoxin.cn 善于分享,希望有助他人. 非常感謝各位大佬的關(guān)注和支持
XORM
xorm 一個簡單強大的Go語言O(shè)RM庫。通過它讓操作數(shù)據(jù)庫變得更加簡單。
[XORM操作指南]
XORM關(guān)系映射,只是Go操作數(shù)據(jù)庫的其中之一。比如還有GORM。至于兩者的區(qū)別,一搜一大堆,不再介紹。
這里只介紹一下XORM的基本使用。
導(dǎo)入包
go get -u github.com/go-sql-driver/mysql go get -u github.com/xormplus/xorm定義結(jié)構(gòu)體
名稱映射規(guī)則
-
指責(zé)
結(jié)構(gòu)體名稱 ----- 表名
結(jié)構(gòu)體字段 ------ 表字段
結(jié)構(gòu)體字段屬性 ----- 對象的表子段屬性
| implemented Conversion | Conversion.ToDB / Conversion.FromDB | Text |
| int, int8, int16, int32, uint, uint8, uint16, uint32 | Int | |
| int64, uint64 | BigInt | |
| float32 | Float | |
| float64 | Double | |
| complex64, complex128 | json.Marshal / json.UnMarshal | Varchar(64) |
| []uint8 | Blob | |
| array, slice, map except []uint8 | json.Marshal / json.UnMarshal | Text |
| string | Varchar(255) | |
| time.Time | DateTime | |
| cascade struct | primary key field value | BigInt |
| struct | json.Marshal / json.UnMarshal | Text |
| Others | Text | |
| bool | 1 or 0 | Bool |
前綴映射、后綴映射、緩存映射
通過 core.NewPrefixMapper(core.SnakeMapper{}, “prefix”) 可以創(chuàng)建一個在SnakeMapper的基礎(chǔ)上在命名中添加統(tǒng)一的前綴
例如,如果希望所有的表名都在結(jié)構(gòu)體自動命名的基礎(chǔ)上加一個前綴而字段名不加前綴,則可以在engine創(chuàng)建完成后執(zhí)行以下語句:
tbMapper := core.NewPrefixMapper(core.SnakeMapper{}, "pre_") engine.SetTableMapper(tbMapper)執(zhí)行之后,結(jié)構(gòu)體 type User struct 默認對應(yīng)的表名就變成了 pre_user 了,而之前默認的是 user
- 通過 core.NewSufffixMapper(core.SnakeMapper{}, “suffix”) 可以創(chuàng)建一個在SnakeMapper的基礎(chǔ)上在命名中添加統(tǒng)一的后綴
- 通過 core.NewCacheMapper(core.SnakeMapper{}) 可以創(chuàng)建一個組合了其它的映射規(guī)則,起到在內(nèi)存中緩存曾經(jīng)映射過的命名映射
創(chuàng)建xorm引擎
在xorm里面,可以同時存在多個Orm引擎,一個Orm引擎稱為Engine,一個Engine一般只對應(yīng)一個數(shù)據(jù)庫
db/db.go
package dbimport ("fmt"_ "github.com/go-sql-driver/mysql""github.com/xormplus/xorm" )var engine *xorm.Enginefunc Init() *xorm.Engine {engine, err := xorm.NewEngine("mysql", "root:root@/test?charset=utf8mb4")if err != nil {panic(err)}err = engine.Ping()if err != nil {fmt.Printf("connect ping failed: %v", err)}engine.ShowSQL(true)return engine }寫入數(shù)據(jù)庫
先創(chuàng)建兩張表,表比較簡單,只是做演示使用
CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(100) NOT NULL,`password` varchar(100) NOT NULL,`email` varchar(100) NOT NULL,`created_at` timestamp NULL DEFAULT NULL,`updated_at` timestamp NULL DEFAULT NULL,`deleted_at` timestamp NULL DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;CREATE TABLE `address` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`addr` varchar(100) DEFAULT NULL,`created_at` timestamp NULL DEFAULT NULL,`updated_at` timestamp NULL DEFAULT NULL,`deleted_at` timestamp NULL DEFAULT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;ORM方式寫入
同一張表的操作
-
寫入一條數(shù)據(jù)
type Users struct {Username string `xorm:"username"`Password string `xorm:"password""`Email string `xorm:"email"`CreatedAt time.Time `xorm:"created"`UpdatedAt time.Time `xorm:"updated"`DeletedAt time.Time ` xorm:"deleted"` }func main() {engine := db.Init()u := &Users{}u.Username = "test"u.Password = "123456"u.Email = "test@sina.com"affected, err := engine.Insert(u)if err != nil {log.Fatal(fmt.Printf("insert into failed, err: %v", err))}fmt.Println(affected) } -
批量寫入
使用slice
func main() {engine := db.Init()u := make([]Users, 2)u[0].Username = "test2"u[0].Password = "123456"u[0].Email = "test2@sina.com"u[1].Username = "test3"u[1].Password = "123456"u[1].Email = "test3@sina.com"affected, err := engine.Insert(u)if err != nil {log.Fatal(fmt.Printf("insert into failed, err: %v", err))}fmt.Println(affected) }使用slice指針批量寫入
func main() {engine := db.Init()u := make([]*Users, 2)u[0] = &Users{}u[0].Username = "test4"u[0].Password = "123456"u[0].Email = "test4@sina.com"u[1] = &Users{}u[1].Username = "test5"u[1].Password = "123456"u[1].Email = "test5@sina.com"affected, err := engine.Insert(u)if err != nil {log.Fatal(fmt.Printf("insert into failed, err: %v", err))}fmt.Println(affected) }多張表的操作
-
寫入一條記錄
type Users struct {Username string `xorm:"username"`Password string `xorm:"password""`Email string `xorm:"email"`CreatedAt time.Time `xorm:"created"`UpdatedAt time.Time `xorm:"updated"`DeletedAt time.Time `xorm:"deleted"` }type Address struct {Addr string `xorm:"Addr"`CreatedAt time.Time `xorm:"created"`UpdatedAt time.Time `xorm:"updated"`DeletedAt time.Time `xorm:"deleted"` }func main() {engine := db.Init()u := &Users{}u.Username = "test4"u.Password = "123456"u.Email = "test4@sina.com"a := &Address{}a.Addr = "杭州"affected, err := engine.Insert(u, a)if err != nil {log.Fatal(fmt.Printf("insert into failed, err: %v", err))}fmt.Println(affected) } -
批量寫入
func main() {engine := db.Init()u := make([]*Users, 2)u[0] = &Users{}u[0].Username = "test6"u[0].Password = "123456"u[0].Email = "test4@sina.com"u[1] = &Users{}u[1].Username = "test7"u[1].Password = "123456"u[1].Email = "test5@sina.com"a := make([]*Address, 2)a[0] = &Address{}a[0].Addr = "杭州"a[1] = &Address{}a[1].Addr = "上海"affected, err := engine.Insert(u, a)if err != nil {log.Fatal(fmt.Printf("insert into failed, err: %v", err))}fmt.Println(affected) }Note: 這里的多表寫入并沒有使用事務(wù)。如果部分成功,部分失敗不支持回滾
執(zhí)行原生sql寫入數(shù)據(jù)
func main() {engine := db.Init()sql := "INSERT INTO users(username, password, email) values (?, ?, ?)"res, err := engine.Exec(sql, "original", "123", "123@sina.com")if err != nil {log.Fatal(fmt.Printf("insert into failed, err: %v", err))}fmt.Println(res) }Note: 執(zhí)行原生sql寫入數(shù)據(jù),created_at、updated_at時間的值不寫的則為空。
原生sql寫入還有其余三種方式,這里不再贅述
刪除數(shù)據(jù)
ORM方式刪除 - 軟刪除
在Delete()時,deleted標記的字段將會被自動更新為當(dāng)前時間而不是去刪除該條記錄
func main() {engine := db.Init()var u = &Users{}u.Username = "test1"affected, err := engine.Delete(u)if err != nil {log.Fatal(fmt.Printf("deleter into failed, err: %v", err))}fmt.Println(affected) }執(zhí)行原生sql刪除 - 物理刪除
func main() {engine := db.Init()sql := "DELETE FROM users where id = ?"affected, err := engine.Exec(sql, 1)if err != nil {log.Fatal(fmt.Printf("deleter into failed, err: %v", err))}fmt.Println(affected) }Note: 也可以使用原生sql update更新deleted_at時間為當(dāng)前時間戳,實現(xiàn)軟刪除。
更新數(shù)據(jù)
-
update方式
更新數(shù)據(jù)使用engine.Update方法,update的參數(shù)可以是一個結(jié)構(gòu)體指針或者一個Map[string]interface{}類型。
- 當(dāng)傳入的為結(jié)構(gòu)體指針時,只有非空和0的field才會被作為更新的字段。如果非要更新空字段,需要使用Cols方法顯示指定更新的列
- 當(dāng)傳入的為Map類型時,key為數(shù)據(jù)庫Column的名字,value為要更新的內(nèi)容。且需要使用engine.Table方法指定表名
-
執(zhí)行原生sql更新數(shù)據(jù)
func main() {engine := db.Init()sql := "UPDATE users SET username = ?, updated_at = ? WHERE id = ?"res, err := engine.Exec(sql, "aaa", time.Now().Format("2006-01-02 15:04:05"), 13)if err != nil {log.Fatal(fmt.Printf("update username failed, err: %v", err))}fmt.Println(res) }
查詢數(shù)據(jù)
ORM
查詢一條數(shù)據(jù) - GET方法
func main() {engine := db.Init()// SELECT * FROM user LIMIT 1user1 := &Users{}has, _ := engine.ID(1).Get(user1)if has {fmt.Printf("user1:%v\n", user1)}// SELECT * FROM user WHERE name = ? ORDER BY id DESC LIMIT 1user2 := &Users{}has, _ = engine.Where("username = ?", "aaa").Desc("id").Get(user2)if has {fmt.Printf("user1:%v\n", user1)} }查詢多條數(shù)據(jù) - Find 方法
Find()需要傳入對象切片的指針或 map 的指針
func main() {engine := db.Init()slicUsers := make([]Users, 0)_ = engine.Find(&slicUsers)fmt.Println(slicUsers)mapUsers := make([]Users, 0)engine.Where("username = ?", "aaa").Find(&mapUsers)fmt.Println(mapUsers) }Iterate 效果與Find方法一樣,對了一個回調(diào)函數(shù)處理每條記錄
func main() {engine := db.Init()engine.Where("username = ?", "aaa").Iterate(new(Users), func(i int, bean interface{}) error {users := bean.(*Users)fmt.Println(users)return nil}) }Count 統(tǒng)計滿足條件的數(shù)量,參數(shù)為struct指針
func main() {engine := db.Init()count, _ := engine.Where("length(username) > ?", 3).Count(&Users{})fmt.Println(count) }Rows方法 和 Iterate方法類似。
func main() {engine := db.Init()u := &Users{}rows, _ := engine.Where("id > ?", 5).Rows(u)defer rows.Close()for rows.Next() {rows.Scan(u)fmt.Println(u)} }原生sql查詢
寫sql語句,然后執(zhí)行即可。和更新刪除類似,不再贅述。
總結(jié)
以上是生活随笔為你收集整理的Go之XORM操作MySQL的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三分钟教你学Git(二十七) - 修改多
- 下一篇: mysql连接 xorm_xorm