Go语言数据库框架——xorm
文章目錄
- XORM
- 1 概念
- 1.1 ORM
- 1.2 Mysql
- 1.3 Mysql命令大全
- 2 XORM 的基本使用
- 2.1 下載xorm
- 2.2 安裝驅動
- 2.3 xorm引擎
- 2.3.1 創建引擎
- 2.3.2 打印日志
- 2.3.3 連接池
- 2.3.4 名稱映射規則
- 2.3.5 數據類型對應規則
- 2.3.6 xorm對數據類型的定義
- 2.4 創建引擎組
- 2.5 基本操作
- 3 XORM數據庫操作
- 3.1 表操作
- 3.2 增
- 3.3 刪除
- 3.4 查改
XORM
1 概念
1.1 ORM
ORM 是 Object Relational Mapping 的縮寫,譯為“對象關系映射”框架。
ORM 框架是一種數據持久化技術,是一種為了解決面向對象與關系型數據庫中數據類型不匹配的技術,它通過描述對象與數據庫表之間的映射關系,自動將應用程序中的對象持久化到關系型數據庫的表中。
Gorm和Xorm都是Go語言的ORM庫,其他相關的數據庫框架庫參考:https://my.oschina.net/u/168737/blog/1531834
執行一下兩條命令 安裝mysql引擎 以及 安裝xorm庫 go get -u github.com/go-sql-driver/mysql go get github.com/go-xorm/xorm1.2 Mysql
下載安裝:https://cloud.tencent.com/developer/article/1636375
啟動/停止服務:net start/stop mysql
登錄:mysql -u root -p密碼
列出數據庫:show databases,退出數據庫:quit
1.3 Mysql命令大全
Mysql常用命令大全:https://www.cnblogs.com/bluecobra/archive/2012/01/11/2318922.html
CREATE DATABASE IF NOT EXISTS golang; USE golang; DROP TABLE IF EXISTS user;CREATE TABLE user (id INT NOT NULL AUTO_INCREMENT,name VARCHAR(30) NOT NULL,PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO classes(id, name) VALUES (1, 'sommer'); INSERT INTO classes(id, name) VALUES (2, 'Jack'); INSERT INTO classes(id, name) VALUES (3, 'hapu'); INSERT INTO classes(id, name) VALUES (4, 'Dim');select * from user;2 XORM 的基本使用
參考資源:
-
xorm操作
-
使用go xorm來操作mysql的方法實例
-
xorm使用
-
xorm官方文檔
-
Go語言的ORM庫xorm實戰篇
-
xorm基礎
2.1 下載xorm
go get github.com/go-xorm/xorm go get github.com/go-xorm/cmd2.2 安裝驅動
go get github.com/go-sql-driver/mysql //Mysql go get github.com/ziutek/mymysql/godrv //MyMysql go get github.com/lib/pq //Postgres go get github.com/mattn/go-sqlite3 //SQLite go get github.com/denisenkom/go-mssqldb //MSSQL2.3 xorm引擎
Engine 引擎用于對單個數據庫進行操作
Engine Group 引擎用于對讀寫分離的數據庫或者負載均衡的數據庫進行操作
2.3.1 創建引擎
import (_ "github.com/go-sql-driver/mysql""xorm.io/xorm" )var engine *xorm.Enginefunc main() {var err error/**配置連接數據庫信息格式:用戶名:密碼@(數據庫服務器地址:端口)/數據庫名稱?charset=字符集*/engine, err = xorm.NewEngine("mysql", "root:root@(127.0.0.1)/golang?charset=utf8")engine.Ping() //連接測試defer engine.Close() //延遲關閉數據庫 }2.3.2 打印日志
engine.ShowSQL(true)//在控制臺打印出生成的SQL語句; engine.Logger().SetLevel(core.LOG_DEBUG)//在控制臺打印調試及以上的信息; -------------------------------------------------------------------- // 將日志保存為文件 f, err := os.Create("sql.log") if err != nil {println(err.Error())return } engine.SetLogger(xorm.NewSimpleLogger(f))2.3.3 連接池
如果需要設置連接池的空閑數大小,使用 engine.SetMaxIdleConns() 來實現。 如果需要設置最大打開連接數,則使用 engine.SetMaxOpenConns() 來實現。 如果需要設置連接的最大生存時間,則使用 engine.SetConnMaxLifetime() 來實現。2.3.4 名稱映射規則
xorm 內置了三種 Mapper 實現:names.SnakeMapper , names.SameMapper和names.GonicMapper。
SnakeMapper 支持struct為駝峰式命名,表結構為下劃線命名之間的轉換,這個是默認的Maper; // user_table——UserTable,user_id——UserId SameMapper 支持結構體名稱和對應的表名稱以及結構體field名稱與對應的表字段名稱相同的命名; GonicMapper 和SnakeMapper很類似,但是對于特定詞支持更好,比如ID會翻譯成id而不是i_d。 engine.SetMapper(names.GonicMapper{}) // 給表加前綴 tbMapper := names.NewPrefixMapper(names.SnakeMapper{}, "prefix_") engine.SetTableMapper(tbMapper) // 加后綴 names.NewSuffixMapper(names.SnakeMapper{}, "suffix")表名的優先級順序如下:
engine.Table() 指定的臨時表名優先級最高 TableName() string 其次 Mapper 自動映射的表名優先級最后字段名的優先級順序如下:
結構體tag指定的字段名優先級較高 xorm:"'column_name'" Mapper 自動映射的表名優先級較低 type User struct {Id int //`xorm:"INT 'id'"`Name string //`xorm:"VARCHAR(30) 'name'"` }2.3.5 數據類型對應規則
| implemented Conversion | Text |
| int, int8, int16, int32, uint, uint8, uint16, uint32 | Int |
| int64, uint64 | BigInt |
| float32 | Float |
| float64 | Double |
| complex64, complex128 | Varchar(64) |
| []uint8 | Blob |
| array, slice, map except []uint8 | Text |
| bool | Bool |
| string | Varchar(255) |
| time.Time | DateTime |
| cascade struct | BigInt |
| struct | Text |
| Others | Text |
2.3.6 xorm對數據類型的定義
| pk | 是否是Primary Key |
| autoincr | 是否是自增 |
| [not ]null 或 notnull | 是否可以為空 |
| unique | 是否是唯一 |
| index | 是否是索引 |
| extends | 應用于一個匿名成員結構體或者非匿名成員結構體之上 |
| - | Field將不進行字段映射 |
| -> | Field將只寫入到數據庫而不從數據庫讀取 |
| <- | Field將只從數據庫讀取,而不寫入到數據庫 |
| created | Field將在Insert時自動賦值為當前時間 |
| updated | Field將在Insert或Update時自動賦值為當前時間 |
| deleted | Field將在Delete時設置為當前時間,并且當前記錄不刪除 |
| version | Field將會在insert時默認為1,每次更新自動加1 |
| default 0或default(0) | 設置默認值,緊跟的內容如果是Varchar等需要加上單引號 |
| json | 表示內容將先轉成Json格式,然后存儲到數據庫中,數據庫中的字段類型可以為Text或者二進制 |
| comment | 設置字段的注釋(當前僅支持mysql) |
2.4 創建引擎組
在xorm中,通過創建引擎組EngineGroup來實現對從數據庫(Master/Slave)讀寫分離的支持。在創建引擎章節中,我們已經介紹過了,在xorm里面,可以同時存在多個Orm引擎,一個Orm引擎稱為Engine,一個Engine一般只對應一個數據庫,而EngineGroup一般則對應一組數據庫。EngineGroup通過調用xorm.NewEngineGroup生成,如:
import (_ "github.com/lib/pq""github.com/xormplus/xorm" )var eg *xorm.EngineGroupfunc main() {conns := []string{"postgres://postgres:root@localhost:5432/test?sslmode=disable;","postgres://postgres:root@localhost:5432/test1?sslmode=disable;","postgres://postgres:root@localhost:5432/test2?sslmode=disable",}var err erroreg, err = xorm.NewEngineGroup("postgres", conns) }or
import (_ "github.com/lib/pq""github.com/xormplus/xorm" )var eg *xorm.EngineGroupfunc main() {var err errormaster, err := xorm.NewEngine("postgres", "postgres://postgres:root@localhost:5432/test?sslmode=disable")if err != nil {return}slave1, err := xorm.NewEngine("postgres", "postgres://postgres:root@localhost:5432/test1?sslmode=disable")if err != nil {return}slave2, err := xorm.NewEngine("postgres", "postgres://postgres:root@localhost:5432/test2?sslmode=disable")if err != nil {return}slaves := []*xorm.Engine{slave1, slave2}eg, err = xorm.NewEngineGroup(master, slaves) }創建完成EngineGroup之后,并沒有立即連接數據庫,此時可以通過eg.Ping()來進行數據庫的連接測試是否可以連接到數據庫,該方法會依次調用引擎組中每個Engine的Ping方法。另外對于某些數據庫有連接超時設置的,可以通過起一個定期Ping的Go程來保持連接鮮活。EngineGroup可以通過eg.Close()來手動關閉,但是一般情況下可以不用關閉,在程序退出時會自動關閉。
- NewEngineGroup方法
func NewEngineGroup(args1 interface{}, args2 interface{}, policies ...GroupPolicy) (*EngineGroup, error)
前兩個參數的使用示例如上,有兩種模式。
模式一:通過給定DriverName,DataSourceName來創建引擎組,每個引擎使用相同的Driver。每個引擎的DataSourceNames是[]string類型,第一個元素是Master的DataSourceName,之后的元素是Slave的DataSourceName。
模式一:通過給定*xorm.Engine,[]*xorm.Engine來創建引擎組,每個引擎可以使用不同的Driver。第一個參數為Master的*xorm.Engine,第二個參數為Slave的[]*xorm.Engine。
NewEngineGroup方法,第三個參數為policies,為Slave給定負載策略,該參數將在負載策略章節詳細介紹,如示例中未指定,則默認為輪詢負載策略。
- Master方法
func (eg *EngineGroup) Master() *Engine
返回Master數據庫引擎 - Slave方法
func (eg *EngineGroup) Slave() *Engine
依據給定的負載策略返回一個Slave數據庫引擎 - Slaves方法
func (eg *EngineGroup) Slaves() []*Engine
返回所以Slave數據庫引擎 - GetSlave方法
func (eg *EngineGroup) GetSlave(i int) *Engine
依據一組Slave數據庫引擎[]*xorm.Engine下標返回指定Slave數據庫引擎。通過給定DriverName,DataSourceName來創建引擎組,則DataSourceName的第二個元素的數據庫為下標0的Slave數據庫引擎。 - SetPolicy方法
func (eg *EngineGroup) SetPolicy(policy GroupPolicy) *EngineGroup
設置引擎組負載策略
2.5 基本操作
package mainimport ("fmt"_ "github.com/go-sql-driver/mysql" //千萬不要忘記導入"github.com/go-xorm/xorm""xorm.io/core" )var engine *xorm.Engine func main() {//1.創建數據庫引擎對象var err error engine, err = xorm.NewEngine("mysql", "root:root@(127.0.0.1:3306)/golang?charset=utf8mb4")engine.Ping() //連接測試,連接正常輸出 PING DATABASE mysqlif err != nil {panic(err.Error())}// 2.延遲關閉數據庫引擎defer engine.Close()// 3.數據庫引擎設置engine.ShowSQL(true) //將sql語句顯示在控制臺中engine.Logger().SetLevel(core.LOG_DEBUG) // 設置日志級別,在控制臺打印調試及以上的信息// 查詢表中所有的數據session := engine.Table("user")count, err := session.Count()if err != nil {panic(err.Error())}fmt.Println(count)// 使用原生sql語句進行查詢result, err := engine.Query("select * from user")if err != nil {panic(err.Error())}for key, value := range result {fmt.Println(key, value)} }測試
package main import ("fmt""github.com/go-xorm/xorm""github.com/go-xorm/core"_ "github.com/go-sql-driver/mysql" ) // 對應數據庫的tablename必須為student // 執行mysql時,對應的字段為xxx,yyy,zzz; 也可以省掉,默認的mysql字段為id,username,address type Student struct {Id int `xorm:"INT(11) 'xxx'"`Username string `xorm:"VARCHAR(64) 'yyy'"`Address string `xorm:"VARCHAR(256) 'zzz'"` } func main() {engine, err := xorm.NewEngine("mysql", "root@/taoge?charset=utf8") // dbname是taogeif err != nil{fmt.Println(err)return}// 如下Ping可以不要// if err := engine.Ping(); err != nil{// fmt.Println(err)// return// }//engine.ShowSQL(true) // 顯示SQL的執行, 便于調試分析engine.SetTableMapper(core.SnakeMapper{})st1 := new(Student)st1.Username = "taoge"st1.Address = "China"affected, err := engine.Insert(st1)fmt.Println(affected)st2 := new(Student)result,err := engine.Where("xxx=?", 1).Get(st2)fmt.Println(result)fmt.Println(st2.Username)fmt.Println(st2.Address) }創建數據庫:
CREATE TABLE `student` (`xxx` int(11) NOT NULL AUTO_INCREMENT,`yyy` varchar(64) NOT NULL,`zzz` varchar(256) NOT NULL ,PRIMARY KEY (`xxx`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;3 XORM數據庫操作
3.1 表操作
engine.DBMetas() // 獲取數據庫中所有的表,字段,索引的信息。 engine.CreateTables() //創建表,參數為一個或多個空的對應Struct的指針。 engine.IsTableEmpty() //判斷表是否為空,參數和 CreateTables 相同 engine.IsTableExist() //判斷表是否存在 engine.DropTables() //刪除表 參數為一個或多個空的對應Struct的指針或者表的名字。如果為string傳入,則只刪除對應的表,如果傳入的為Struct,則刪除表的同時還會刪除對應的索引。 engine.CreateIndexes //根據struct中的tag來創建索引 engine.CreateUniques //根據struct中的tag來創建唯一索引err := engine.Sync(new(User), new(Group)) //同步數據庫結構 err := engine.Sync2(new(User), new(Group))// 導出數據庫的結構和數據 engine.DumpAll(w io.Writer) engine.DumpAllToFile(fpath string) // 執行SQL腳本 engine.Import(r io.Reader) engine.ImportFile(fpath string) //判斷一個表當中內容是否為空 personEmpty, err := engine.IsTableEmpty(new(PersonTable)) if err != nil {panic(err.Error()) } if personEmpty {fmt.Println("人員表是空的!") }else{fmt.Println("人員表不為空!") }//判斷表結構是否存在 studentExist, err := engine.IsTableExist(new(StudentTable)) if err != nil {panic(err.Error()) } if studentExist {fmt.Println("學生表存在!") }else{fmt.Println("學生表不存在!") }3.2 增
// 插入單條記錄 user1 := new(User) user1.Id = 6 user1.Name = "Dim" affected, err := engine.Insert(user1) fmt.Println("插入單條數據:", affected, err)// 插入多條數據 users := make([]*User, 3) users[0] = new(User) users[0].Id = 11 users[0].Name = "name11" users[1] = new(User) users[1].Id = 12 users[1].Name = "name12" users[2] = new(User) users[2].Id = 13 users[2].Name = "name13" affects, errs := engine.Insert(&users) fmt.Println("插入多條數據:", affects, errs)3.3 刪除
刪除數據Delete方法,參數為struct的指針并且成為查詢條件。
軟刪除Deleted,不真正的刪除數據,而是標記一個刪除時間。
// 刪除 affdel, errdel := engine.Delete(user) fmt.Println(affdel, errdel)3.4 查改
func main(){engine, err := xorm.NewEngine("mysql", "root:root@/elmcms?charset=utf8")if err != nil {panic(err.Error())}//條件查詢//1.ID查詢//首先你得要有一個結構體來存放查詢出來的數據var person PersonTable//select * from person_table where id = 1 并且get只獲取到一條記錄哈!engine.Id(1).Get(&person)fmt.Println(person)fmt.Println("----------------------------")//2.where多條件查詢//首先你得要有一個結構體來存放查詢出來的數據var person1 PersonTable//select * from person_table where person_age = 26 and person_sex = 2engine.Where(" person_age = ? and person_sex = ?", 30, 1).Get(&person1)fmt.Println(person1)fmt.Println("----------------------------")//3.and條件查詢//首先你得要有一個結構體來存放查詢出來的數據var persons []PersonTable//select * from person_table where person_age = 26 and person_sex = 2 find 會返回一條或者多條記錄err = engine.Where(" person_age = ?", 30).And("person_sex = ?", 1).Find(&persons)if err != nil {panic(err.Error())}fmt.Println(persons)fmt.Println("----------------------------")//4.or條件查詢var personArr []PersonTable//select * from person_table where person_age = 26 or person_sex = 1err = engine.Where(" person_age = ?", 26).Or("person_sex = ?", 1).Find(&personArr)if err != nil {panic(err.Error())}fmt.Println(personArr)fmt.Println("----------------------------")//5.原生sql語句查詢 支持likevar personNative []PersonTable//執行原生的sql語句err = engine.SQL(" select * from person_table where person_name like '%i%' ").Find(&personNative)if err != nil {panic(err.Error())}fmt.Println(personNative)fmt.Println("----------------------------")//6.排序條件查詢var personOrderBy []PersonTable//select * from person_table orderby person_age 升序排列//engine.OrderBy(" person_age ").Find(&personsOrderBy) 不寫desc默認就是asc升序排序err = engine.OrderBy(" person_age desc ").Find(&personOrderBy)if err != nil {panic(err.Error())}fmt.Println(personOrderBy)fmt.Println("----------------------------111")//7.查詢特定字段var personCols []PersonTableengine.Cols("person_name", "person_age").Find(&personCols)for _,col := range personCols {fmt.Println(col)}//fmt.Println(personCols)fmt.Println("----------------------------")//增加記錄//插入你得先有數據 弄到結構體里面去personInsert := PersonTable{PersonName: "wahaha",PersonAge: 40,PersonSex: 10,}rowNum, err := engine.Insert(&personInsert)fmt.Println(rowNum) //rowNum表示受影響的行數fmt.Println("----------------------------")//刪除操作personDelete := PersonTable{}//根據id刪除rowNum1, err := engine.Id(4).Delete(&personDelete)fmt.Println(rowNum1) //rowNum1也是表示受影響的行數fmt.Println("----------------------------")//更新操作personUpdate := PersonTable{PersonName: "胡紹良",PersonAge: 30,PersonSex: 1,}rowNum2, err := engine.Id(1).Update(&personUpdate)fmt.Println(rowNum2) // rowNum2也是表示受影響的行數fmt.Println("----------------------------")//統計功能countcount, err := engine.Count(new(PersonTable))fmt.Println("persontable表總記錄數:",count)//事務操作personsArray := []PersonTable{PersonTable{PersonName: "Jack",PersonAge: 28,PersonSex: 1,},PersonTable{PersonName: "Mali",PersonAge: 28,PersonSex: 1,},PersonTable{PersonName: "Ruby",PersonAge: 28,PersonSex: 1,},}session := engine.NewSession()session.Begin()for i:=0;i<len(personsArray);i++{_, err = session.Insert(personsArray[i])if err != nil {session.Rollback()session.Close()}}err = session.Commit()session.Close()if err != nil {panic(err.Error())}}//人員結構表 type PersonTable struct {Id int64 `xorm:"pk autoincr"`PersonName string `xorm:"varchar(24)"`PersonAge int `xorm:"int default 0"`PersonSex int `xorm:"notnull"`City CityTable `xorm:"-"` }type CityTable struct {CityName stringCityLongitude float32CityLatitude float32}總結
以上是生活随笔為你收集整理的Go语言数据库框架——xorm的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 仿wordpress管理后台设计的后台管
- 下一篇: 【开发教程2】疯壳·ARM功能手机-测试