golang xorm mysql_golang 之xorm
xorm
xorm是一個(gè)簡(jiǎn)單而強(qiáng)大的ORM庫(kù)。
安裝
go get -u github.com/go-xorm/xorm
驅(qū)動(dòng)支持
Mysql: github.com/go-sql-driver/mysql
MyMysql: github.com/ziutek/mymysql
Postgres: github.com/lib/pq
Tidb: github.com/pingcap/tidb
SQLite: github.com/mattn/go-sqlite3
MsSql: github.com/denisenkom/go-mssqldb
MsSql: github.com/lunny/godbc
Oracle: github.com/mattn/go-oci8 (試驗(yàn)性支持)
創(chuàng)建orm引擎
一個(gè)xorm可同時(shí)存在orm引擎,一個(gè)Orm引擎稱(chēng)為Engine,一個(gè)Engine一般只對(duì)應(yīng)一個(gè)數(shù)據(jù)庫(kù)。Engine通過(guò)調(diào)用xorm.NewEngine生成,如:
package main
import (
"github.com/go-xorm/xorm"
_ "github.com/go-sql-driver/mysql"
)
func main() {
engine, err := xorm.NewEngine("mysql", "root:passwd@tcp(127.0.0.1:3306)/dabase_name?timeout=3s&parseTime=true&loc=Local&charset=utf8")
if err !=nil{
return
}
engine.Ping() // 可以判斷是否能連接
defer engine.Close() // 退出后關(guān)閉
}
定義表結(jié)構(gòu)體
表名映射一般有三種方式,且都按優(yōu)先級(jí)高低
表名的優(yōu)先級(jí)順序如下:
engine.Table() 指定的臨時(shí)表名優(yōu)先級(jí)最高
TableName() string 其次
Mapper 自動(dòng)映射的表名優(yōu)先級(jí)最后
字段名的優(yōu)先級(jí)順序如下:
結(jié)構(gòu)體tag指定的字段名優(yōu)先級(jí)較高
Mapper 自動(dòng)映射的表名優(yōu)先級(jí)較低
Column屬性定義,首先定義一個(gè)結(jié)構(gòu)體如
type User struct {
Id int64
Name string `xorm:"varchar(25) notnull unique 'usr_name'"`
Balance float64
Version int `xorm:"version"` // 樂(lè)觀鎖
}
具體tag詳情如下。且字段名根據(jù)不同數(shù)據(jù)庫(kù)區(qū)分大小寫(xiě)
Tag說(shuō)明
name
當(dāng)前field對(duì)應(yīng)的字段的名稱(chēng),可選,如不寫(xiě),則自動(dòng)根據(jù)field名字和轉(zhuǎn)換規(guī)則命名,如與其它關(guān)鍵字沖突,請(qǐng)使用單引號(hào)括起來(lái)。
pk
是否是Primary Key,如果在一個(gè)struct中有多個(gè)字段都使用了此標(biāo)記,則這多個(gè)字段構(gòu)成了復(fù)合主鍵,單主鍵當(dāng)前支持int32,int,int64,uint32,uint,uint64,string這7種Go的數(shù)據(jù)類(lèi)型,復(fù)合主鍵支持這7種Go的數(shù)據(jù)類(lèi)型的組合。
當(dāng)前支持30多種字段類(lèi)型,詳情參見(jiàn)本文最后一個(gè)表格
字段類(lèi)型
autoincr
是否是自增
[not ]null 或 notnull
是否可以為空
unique或unique(uniquename)
是否是唯一,如不加括號(hào)則該字段不允許重復(fù);如加上括號(hào),則括號(hào)中為聯(lián)合唯一索引的名字,此時(shí)如果有另外一個(gè)或多個(gè)字段和本unique的uniquename相同,則這些uniquename相同的字段組成聯(lián)合唯一索引
index或index(indexname)
是否是索引,如不加括號(hào)則該字段自身為索引,如加上括號(hào),則括號(hào)中為聯(lián)合索引的名字,此時(shí)如果有另外一個(gè)或多個(gè)字段和本index的indexname相同,則這些indexname相同的字段組成聯(lián)合索引
extends
應(yīng)用于一個(gè)匿名成員結(jié)構(gòu)體或者非匿名成員結(jié)構(gòu)體之上,表示此結(jié)構(gòu)體的所有成員也映射到數(shù)據(jù)庫(kù)中,extends可加載無(wú)限級(jí)
-
這個(gè)Field將不進(jìn)行字段映射
->
這個(gè)Field將只寫(xiě)入到數(shù)據(jù)庫(kù)而不從數(shù)據(jù)庫(kù)讀取
這個(gè)Field將只從數(shù)據(jù)庫(kù)讀取,而不寫(xiě)入到數(shù)據(jù)庫(kù)
created
這個(gè)Field將在Insert時(shí)自動(dòng)賦值為當(dāng)前時(shí)間
updated
這個(gè)Field將在Insert或Update時(shí)自動(dòng)賦值為當(dāng)前時(shí)間
deleted
這個(gè)Field將在Delete時(shí)設(shè)置為當(dāng)前時(shí)間,并且當(dāng)前記錄不刪除
version
這個(gè)Field將會(huì)在insert時(shí)默認(rèn)為1,每次更新自動(dòng)加1
default 0或default(0)
設(shè)置默認(rèn)值,緊跟的內(nèi)容如果是Varchar等需要加上單引號(hào)
json
表示內(nèi)容將先轉(zhuǎn)成Json格式,然后存儲(chǔ)到數(shù)據(jù)庫(kù)中,數(shù)據(jù)庫(kù)中的字段類(lèi)型可以為T(mén)ext或者二進(jìn)制
需要注意的幾點(diǎn)
如果field名稱(chēng)為ID,且類(lèi)型為int64,并且 沒(méi)有定義tag,則會(huì)被xorm視為主鍵,且擁有自增屬性。如果要用其它名字為主鍵,需對(duì)應(yīng)tag加上 xorm:"pk"
string類(lèi)型默認(rèn)為varchar(255)
支持type MyString string 等自定義的field。支持Slice, Map,等f(wàn)ield成員。這些成員默認(rèn)存儲(chǔ)為T(mén)ext類(lèi)型。并且擁有Json格式來(lái)序列化和反序列化。
實(shí)現(xiàn)Conversion接口的類(lèi)型或者結(jié)構(gòu)體,將根據(jù)接口的轉(zhuǎn)換方式在類(lèi)型和數(shù)據(jù)庫(kù)記錄之間進(jìn)行相互轉(zhuǎn)換。
type Conversion interface {
FromDB([]byte) error
ToDB() ([]byte, error)
}
表結(jié)構(gòu)常用操作
獲取數(shù)據(jù)庫(kù)信息
DBMetas(): xorm支持獲取表結(jié)構(gòu)信息。通過(guò)調(diào)用engine.DBMetas()獲取表,字段,索引信息
TableInfo(): 根據(jù)傳入的結(jié)構(gòu)體指針及對(duì)應(yīng)的Tag,提取出模型對(duì)應(yīng)的表結(jié)構(gòu)信息。
表操作
CreateTables(): 創(chuàng)建表engine.CreateTables() 參數(shù)為一個(gè)或多個(gè)空的對(duì)應(yīng)Struct的指針。可用方法有Charset()和StoreEngine()。
IsTableEmpty(): 判斷是否為空。參數(shù)和CreateTables()相同。
IsTableExist():判斷是否存在
DropTables(): 刪除表engine.DropTables().參數(shù)為一個(gè)或多個(gè)空的對(duì)應(yīng)Struct的指針或者表的名字。如果為string傳入,則只刪除對(duì)應(yīng)的表,如果傳入的為Struct,則刪除表的同時(shí)還會(huì)刪除對(duì)應(yīng)的索引。
創(chuàng)建索引和唯一索引
CreateIndexes: 根據(jù)struct中的Tag來(lái)創(chuàng)建索引
CreateUniques: 根據(jù)struct中的tag來(lái)創(chuàng)建唯一索引
同步數(shù)據(jù)庫(kù)結(jié)構(gòu)到 mysql中
Sync
自動(dòng)檢測(cè)和創(chuàng)建表,這個(gè)檢測(cè)是根據(jù)表的名字
自動(dòng)檢測(cè)和新增表中的字段,這個(gè)檢測(cè)是根據(jù)字段名
自動(dòng)檢測(cè)和創(chuàng)建索引和唯一索引,這個(gè)檢測(cè)是根據(jù)索引的一個(gè)或多個(gè)字段名,而不根據(jù)索引名稱(chēng)
err := engine.Sync(new(User), new(Group))
// 其中User ,Group為要?jiǎng)?chuàng)建的兩個(gè)表對(duì)應(yīng)的struct
Sync2, 對(duì)Sync進(jìn)行改進(jìn),推薦使用Sync2
自動(dòng)檢測(cè)和創(chuàng)建表,這個(gè)檢測(cè)是根據(jù)表的名字
自動(dòng)檢測(cè)和新增表中的字段,這個(gè)檢測(cè)是根據(jù)字段名,同時(shí)對(duì)表中多余的字段給出警告信息
自動(dòng)檢測(cè),創(chuàng)建和刪除索引和唯一索引,這個(gè)檢測(cè)是根據(jù)索引的一個(gè)或多個(gè)字段名,而不根據(jù)索引名稱(chēng)。因此這里需要注意,如果在一個(gè)有大量數(shù)據(jù)的表中引入新的索引,數(shù)據(jù)庫(kù)可能需要一定的時(shí)間來(lái)建立索引。
自動(dòng)轉(zhuǎn)換varchar字段類(lèi)型到text字段類(lèi)型,自動(dòng)警告其它字段類(lèi)型在模型和數(shù)據(jù)庫(kù)之間不一致的情況。
自動(dòng)警告字段的默認(rèn)值,是否為空信息在模型和數(shù)據(jù)庫(kù)之間不匹配的情況
以上信息需要將engine.ShowWarn設(shè)置為true才會(huì)顯示。調(diào)用方法
err := engine.Sync2(new(User), new(Group))
導(dǎo)入導(dǎo)出SQL腳本
dump
engine.DumpAll(w io.Writer)
或
engine.DumpAllFile(fpath string)
Import
engine.Import(r io.Reader)
或者
engine.ImportFile(fpath string)
插入數(shù)據(jù)操作(表結(jié)構(gòu)參照上面User表)
ORM插入一條數(shù)據(jù)
user := new(User)
user.Name = "myname"
affected, err := engine.Insert(user)
// INSERT INTO user (name) values (?)
插入同一個(gè)表的多條數(shù)據(jù)
users := make([]User, 1)
users[0].Name = "name0"
users[0].ID = "0"
...
affected, err := engine.Insert(&users)
指針Slice插入多條記錄
users := make([]*User, 1)
users[0] = new(User)
users[0].Name = "name0"
users[0].ID = "0"
...
affected, err := engine.Insert(&users)
不同表的一條記錄
user := new(User)
user.Name = "myname"
question := new(Question)
question.Content = "whywhywhwy?"
affected, err := engine.Insert(user, question)
不同表的多條記錄
users := make([]User, 1)
users[0].Name = "name0"
...
questions := make([]Question, 1)
questions[0].Content = "whywhywhwy?"
affected, err := engine.Insert(&users, &questions)
使用SQL插入數(shù)據(jù)
sql ="insert into config(key,value) values (?, ?)"
res, err := engine.Exec(sql, "OSCHINA", "OSCHINA")
或者
sql_2 := "insert into config(key,value) values (?, ?)"
affected, err := engine.Sql(sql_4, "OSCHINA", "OSCHINA").Execute()
或者
//SqlMap中key為 "sql_i_1" 配置的Sql語(yǔ)句為:insert into config(key,value) values (?, ?)
sql_i_1 := "sql_i_1"
affected, err := engine.SqlMapClient(sql_i_1, "config_1", "1").Execute()
或者
sql_i_3 := "insert.example.stpl"
paramMap_i_t := map[string]interface{}{"key": "config_3", "value": "3"}
affected, err := engine.SqlTemplateClient(sql_i_3, ¶mMap_i_t).Execute()
查詢(xún)操作
ORM常用查詢(xún)
注意下面出現(xiàn)的 & +表結(jié)構(gòu)體
設(shè)置別名
engine.Alias("o").Where("o.name = ?", name).Get(&order)
條件查找
engine.Where(...).And(...).Get(&order)
某個(gè)字段排序
// 正序
engine.Asc("id").Find(&orders)
//倒序
engine.Asc("id").Desc("time").Find(&orders)
主鍵查找
var user User
engine.Id(1).Get(&user)
// SELECT * FROM user Where id = 1
// 或者復(fù)合主鍵
engine.Id(core.PK{1, "name"}).Get(&user)
// SELECT * FROM user Where id =1 AND name= 'name'
select, in, cols
engine.Select("a.*, (select name from b limit 1) as name").Find(&beans)
engine.Select("a.*, (select name from b limit 1) as name").Get(&bean)
// in
engine.In("cloumn", 1, 2, 3).Find()
engine.In("column", []int{1, 2, 3}).Find()
// cols
engine.Cols("age", "name").Get(&usr)
// SELECT age, name FROM user limit 1
engine.Cols("age", "name").Find(&users)
// SELECT age, name FROM user
engine.Cols("age", "name").Update(&user)
// UPDATE user SET age=? AND name=?
GET方法,查詢(xún)到的數(shù)據(jù)會(huì)賦給結(jié)構(gòu)體
has, err := engine.Get(&user)
// SELECT * FROM user LIMIT 1
has, err := engine.Where("name = ?", name).Desc("id").Get(&user)
// SELECT * FROM user WHERE name = ? ORDER BY id DESC LIMIT 1
var name string
has, err := engine.Where("id = ?", id).Cols("name").Get(&name)
// SELECT name FROM user WHERE id = ?
var id int64
has, err := engine.Where("name = ?", name).Cols("id").Get(&id)
// SELECT id FROM user WHERE name = ?
var valuesMap = make(map[string]string)
has, err := engine.Where("id = ?", id).Get(&valuesMap)
// SELECT * FROM user WHERE id = ?
var valuesSlice = make([]interface{}, len(cols))
has, err := engine.Where("id = ?", id).Cols(cols...).Get(&valuesSlice)
// SELECT col1, col2, col3 FROM user WHERE id = ?
或者
user := new(User)
has, err := engine.Where("name=?", "xlw").Get(user)
子查詢(xún)
var student []Student
err = db.Table("student").Select("id ,name").Where("id in (?)", db.Table("studentinfo").Select("id").Where("status = ?", 2).QueryExpr()).Find(&student)
//SELECT id ,name FROM `student` WHERE (id in (SELECT id FROM `studentinfo` WHERE (status = 2)))
SQL操作返回格式j(luò)son or xml
var users []User
results,err := engine.Where("id=?", 6).Search(&users).Xml() //返回查詢(xún)結(jié)果的xml字符串
results,err := engine.Where("id=?", 6).Search(&users).Json() //返回查詢(xún)結(jié)果的json字符串
更新操作
update方法
user := new(User)
user.Name = "myname"
affected, err := engine.Id(id).Update(user)
指定更新值
affected, err := engine.Id(id).Cols("age").Update(&user)
// 或
affected, err := engine.Table(new(User)).Id(id).Update(map[string]interface{}{"age":0})
更新時(shí)間,可以在字段名后添加 update如下
type User struct {
Id int64
Name string
UpdatedAt time.Time `xorm:"updated"`
}
刪除操作
delete方法
user := new(User)
affected, err := engine.Id(id).Delete(user)
//Delete的返回值第一個(gè)參數(shù)為刪除的記錄數(shù),第二個(gè)參數(shù)為錯(cuò)誤。
xorm還提供了軟刪除,如下設(shè)置
type User struct {
Id int64
Name string
DeletedAt time.Time `xorm:"deleted"`
}
如果設(shè)置軟刪除,那么永久刪除或者獲取使用Unscoped
var user User
engine.Id(1).Unscoped().Get(&user)
// 此時(shí)將可以獲得記錄
engine.Id(1).Unscoped().Delete(&user)
// 此時(shí)將可以真正的刪除記錄
創(chuàng)建數(shù)據(jù)庫(kù)組
xorm提供了可以連接多個(gè)數(shù)據(jù)庫(kù)。如下
package main
import (
"github.com/go-xorm/xorm"
_ "github.com/go-sql-driver/mysql"
)
func main() {
conns := []string{
"mysql", "root:passwd@tcp(127.0.0.1:3306)/dabase_name?timeout=3s&parseTime=true&loc=Local&charset=utf8",
"mysql", "root:passwd@tcp(127.0.0.1:3306)/dabase_name?timeout=3s&parseTime=true&loc=Local&charset=utf8",
"mysql", "root:passwd@tcp(127.0.0.1:3306)/dabase_name?timeout=3s&parseTime=true&loc=Local&charset=utf8",
}
engine, err := xorm.NewEngineGroup("mysql", conns)
if err !=nil{
return
}
engine.Ping() // 可以判斷是否能連接
defer engine.Close() // 退出后關(guān)閉
}
連接池
engine內(nèi)部支持連接池接口和對(duì)應(yīng)的函數(shù)。
如果需要設(shè)置連接池的空閑數(shù)大小,可以使用engine.SetMaxIdleConns()來(lái)實(shí)現(xiàn)。
如果需要設(shè)置最大打開(kāi)連接數(shù),則可以使用engine.SetMaxOpenConns()來(lái)實(shí)現(xiàn)。
詳細(xì)查詢(xún)操作可參照github,鏈接? https://github.com/go-xorm/xorm/
總結(jié)
以上是生活随笔為你收集整理的golang xorm mysql_golang 之xorm的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: xorm reverse
- 下一篇: mysql房源数据库_[宜配屋]听图阁