xorm:golang的orm(只寫了一小部分)


xorm

xorm是一個簡單而強大的Go語言ORM庫. 通過它可以使數據庫操作非常簡便。這個庫是國人開發的,是基於原版 xorm:https://github.com/go-xorm/xorm 的定制增強版本。安裝該orm的話,直接通過go get -u github.com/xormplus/xorm即可

當然orm並不能直接操作數據庫,還是要借助第三方驅動的,目前支持的驅動如下

  • Mysql: https://github.com/go-sql-driver/mysql
  • MyMysql: https://github.com/ziutek/mymysql
  • Postgres: https://github.com/lib/pq
  • Tidb: https://github.com/pingcap/tidb
  • SQLite: https://github.com/mattn/go-sqlite3
  • MsSql: https://github.com/denisenkom/go-mssqldb
  • Oracle: https://github.com/mattn/go-oci8 (試驗性支持)

創建引擎

引擎使用來執行我們所寫的sql語句的

package main

import (
	"fmt"
	_ "github.com/lib/pq" // 引用驅動,python中,是不需要顯示引用的,但是golang需要引用執行以下內部的Init函數,我這里是postgresql,其他數據庫就換成其他的驅動
	"github.com/xormplus/core"
	"github.com/xormplus/xorm"
)

func main() {
	engine, err := xorm.NewPostgreSQL("postgresql://postgres:zgghyys123@localhost:5432/postgres?sslmode=disable")
	// 引擎這里結尾要加上一個sslmode=disable,不然會報出:pq: SSL is not enabled on the server
	if err != nil {
		fmt.Println(err)
	} else {
		//調用engine.Ping可以查看是否建立成功
		_ = engine.Ping()  // [xorm] [info]  2019/08/25 21:14:49.581814 PING DATABASE postgres
	}

	//此外還可以設置日志,通過設置日志,可以顯示sql、警告和錯誤信息等等,默認的顯示級別為info
	engine.ShowSQL(true) // 則會在控制台打印出生成的SQL語句
	engine.Logger().SetLevel(core.LOG_DEBUG) //則會在控制台打印info及以上的信息
	/*
	如果希望將信息不僅打印到控制台,而是保存為文件,那么可以通過類似如下的代碼實現,NewSimpleLogger(w io.Writer)接收一個io.Writer接口來將數據寫入到對應的設施中。
	f, err := os.Create("sql.log")
	if err != nil {
	    println(err.Error())
	    return
	}
	engine.SetLogger(xorm.NewSimpleLogger(f))
	 */

	//此外還可以設置連接池
	/*
	如果需要設置連接池的空閑數大小,可以使用engine.SetMaxIdleConns(n)來實現
	如果需要設置最大打開連接數,則可以使用engine.SetMaxOpenConns(n)來實現。
	 */
}

獲取表信息

package main

import (
	"fmt"
	_ "github.com/lib/pq" // 引用驅動,python中,是不需要顯示引用的,但是golang需要引用執行以下內部的Init函數,我這里是postgresql,其他數據庫就換成其他的驅動
	"github.com/xormplus/xorm"
)

func main() {
	engine, err := xorm.NewPostgreSQL("postgresql://postgres:zgghyys123@localhost:5432/postgres?sslmode=disable")
	if err != nil {
		fmt.Println(err)
	} else {
		// info是一個切片,存儲的數據類型為*core.Table,*core.Table是一個結構體指針,我們來看看都有哪些屬性
		/*
		type Table struct {
			Name          string
			Type          reflect.Type
			columnsSeq    []string
			columnsMap    map[string][]*Column
			columns       []*Column
			Indexes       map[string]*Index
			PrimaryKeys   []string
			AutoIncrement string
			Created       map[string]bool
			Updated       string
			Deleted       string
			Version       string
			Cacher        Cacher
			StoreEngine   string
			Charset       string
			Comment       string
		}
		 */
		info, err := engine.DBMetas()
		if err != nil {
			fmt.Println(err)
		}else {
			for _, v := range info{
				fmt.Println(fmt.Sprintf("表名:%s", v.Name))
				/*
				表名:alembic_version
				表名:user1
				表名:heroes
				 */
			}
		}
	}
}

此外還可以判斷表是否存在,表是否為空,以及刪除表

package main

import (
	"fmt"
	_ "github.com/lib/pq" // 引用驅動,python中,是不需要顯示引用的,但是golang需要引用執行以下內部的Init函數,我這里是postgresql,其他數據庫就換成其他的驅動
	"github.com/xormplus/xorm"
)

func main() {
	engine, err := xorm.NewPostgreSQL("postgresql://postgres:zgghyys123@localhost:5432/postgres?sslmode=disable")
	if err != nil {
		fmt.Println(err)
	} else {
		//判斷user1是否存在
		flag, _ := engine.IsTableExist("user1")
		fmt.Println(flag) // true

		//判斷user1內容是否為空
		flag, _ = engine.IsTableEmpty("user1")
		fmt.Println(flag) // false

		//刪除user1,DropTables可以接收多個參數
		_ = engine.DropTables("user1")
		//再來查看user1是否存在
		flag, _ = engine.IsTableExist("user")
		fmt.Println(flag) // false
	}
}

創建表

首先可以原生建表

package main

import (
	"fmt"
	_ "github.com/lib/pq" // 引用驅動,python中,是不需要顯示引用的,但是golang需要引用執行以下內部的Init函數,我這里是postgresql,其他數據庫就換成其他的驅動
	"github.com/xormplus/xorm"
)

func main() {
	engine, err := xorm.NewPostgreSQL("postgresql://postgres:zgghyys123@localhost:5432/postgres?sslmode=disable")
	if err != nil {
		fmt.Println(err)
	} else {
		create_table_sql := `
			create table girls(
			id int primary key,
			name varchar(255) not null,
			age int not null,
			gender varchar(1)
		)
		`
		//調用engine.Exec可以執行原生sql語句
		res, err := engine.Exec(create_table_sql)
		if err != nil {
			fmt.Println(err)
		}else {
			//res是一個sql.Result類型
			/*
			type Result interface {
				LastInsertId() (int64, error)
				RowsAffected() (int64, error)
			}
			 */
			//這兩行打印的無所謂,只要上面的err為nil即可,我們看看數據庫里面有沒有表
			fmt.Println(res.LastInsertId()) // 0 LastInsertId is not supported by this driver
			fmt.Println(res.RowsAffected()) // 0 <nil>
		}
	}
}

創建成功了的

orm形式建表

在golang中,使用結構體映射為數據庫中的字段

package main

import (
	"fmt"
	_ "github.com/lib/pq" // 引用驅動,python中,是不需要顯示引用的,但是golang需要引用執行以下內部的Init函數,我這里是postgresql,其他數據庫就換成其他的驅動
	"github.com/xormplus/xorm"
)

func main() {
	engine, err := xorm.NewPostgreSQL("postgresql://postgres:zgghyys123@localhost:5432/postgres?sslmode=disable")
	if err != nil {
		fmt.Println(err)
	} else {
		type boy struct {
			// 字段名 類型 tag
			//golang的orm中的約束使用tag來體現,多個約束使用空格分割

			/*
			pk表示主鍵 autoincr 自增
			如果Field名就叫做Id,並且類型為int64,如果不加tag,會自動被xorm視為主鍵,並且自增。
			如果想用Id以外、或者非int64類型作為主鍵,必須要顯示的在tag中指定,`xorm:"pk autoincr"`
			 */
			Id int `xorm:"pk autoincr"`

			/*
			'姓名'是映射到數據庫的字段名,如果不指定則是當前結構體字段(Field)的名稱
			建議使用單引號括起來放到最后
			 */
			Name string `xorm:"varchar(255) not null '姓名'"`

			/*
				default,默認值
			 */
			Age int `xorm:"not null default 16 '年齡'"`

			/*
			default,默認值,如果是varchar則需要加上單引號
			 */
			Gender int `xorm:"varchar(1) not null default '女' '性別'"`
		}

		//可以指定schema,對於postgresql來說,很多時候還是要指定schema的
		engine.SetSchema("anime") //設置schema為anime

		//使用engine.Sync(new(boy)),完成映射
		err := engine.Sync(new(boy))
		if err != nil {
			fmt.Println(err)
		}
	}
}

也是創建成功了的

插入數據

orm形式插入數據

package main

import (
	"fmt"
	"github.com/xormplus/xorm"
)
import _"github.com/lib/pq"

func main() {
	engine, _ := xorm.NewPostgreSQL("postgres://postgres:zgghyys123@localhost:5432/postgres?sslmode=disable")
	type girl struct {
		Id int `xorm:"pk autoincr"`
		Name string `xorm:"varchar(255) not null"`
		Age int `xorm:"not null"`
        //CreatedAt time.Time `xorm:"created"` 會自動加上當前的創建時間
	}
	engine.SetSchema("anime")
	_ = engine.Sync(new(girl))

	g := &girl{Name:"satori", Age:16}
	//插入數據可以使用Insert方法,對象可以是一個struct對象指針,插入一條數據,或者多個struct指針組成的切片所對應的指針,插入多條數據
	//注意到這里沒有傳入Id,因為Id在數據庫中是自增的。如果給Id賦值了,那么該字段會作為非自增字段插入
	affected, err:= engine.Insert(g) // 返回兩個結果,受影響的行數和err
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println("受影響的行數", affected)
	}

	//插入多條數據
	rows := []*girl{
		{Name:"koishi", Age:16},
		{Name:"frandlescarlet", Age:400},
		{Name:"mashiro", Age:16},
	}
	affected, err = engine.Insert(&rows) // 對的,這里切片也要傳遞指針
	if err!=nil{
		fmt.Println(err)
	}else{
		fmt.Println("受影響的行數", affected)
	}
	/*
	受影響的行數 1
	受影響的行數 3
	 */
}

原生形式插入數據

package main

import (
	"github.com/xormplus/xorm"
)
import _"github.com/lib/pq"

func main() {
	engine, _ := xorm.NewPostgreSQL("postgres://postgres:zgghyys123@localhost:5432/postgres?sslmode=disable")

	// 第一種方式
	sql_1 := "insert into anime.girl(name, age) values('kurisu', 18)"
	_, _ = engine.Exec(sql_1)
	// 第二種方式
	sql_2 := "insert into anime.girl(name, age) values(?, ?)"
	_, _ = engine.Exec(sql_2, "nagisa", 20)

	// 第三種方式
	sql_3 := "insert into anime.girl(name, age) values(?, ?)"
	_, _ = engine.SQL(sql_3, "tomoyo", 18).Execute()
}

查詢和統計數據

支持執行SQL與ORM兩種方式查詢數據

orm方式查詢和統計數據

package main

import (
	"fmt"
	"github.com/xormplus/xorm"
)
import _"github.com/lib/pq"

//字段名大寫,和數據庫的表的字段名保持一致即可
//結構體的名字和表名一致即可,這里可以大寫可以小寫
type Girl struct {
	Id int64
	Name string
	Age int
}

func main(){
	engine, err := xorm.NewPostgreSQL("postgresql://postgres:zgghyys123@localhost:5432/postgres?sslmode=disable")
	if err != nil {
		fmt.Println(err)
	}
	//指定schema
	engine.SetSchema("anime")

	//創建一個結構體指針
	g1 := new(Girl)

	//使用engine.Get方法,傳入相應的指針
	//返回兩個參數,第一個參數表示記錄是否存在,第二個表示是否有錯
	has, err := engine.Get(g1)
	if err!= nil {
		fmt.Println(err)
	}else {
		fmt.Println(has) // true
	}
	//正確執行engine.Get之后,記錄會存到g1里面
	//注意Get方法只會獲取一條記錄,那么默認是符合條件的第一條
	fmt.Println(g1) // &{1 satori 16}


	/*
	Find:Get是查詢一條數據,Find查詢多條
	那么此時Find里面接收的則是一個切片對應的指針,切片的類型是相應結構體類型
	 */
	girl1 := make([]Girl, 0)
	if err := engine.Find(&girl1); err!=nil{
		fmt.Println(err)
	}else{
		//這樣就全部獲取出來了
		fmt.Println(girl1) // [{1 satori 16} {2 koishi 16} {3 frandlescarlet 400} {4 mashiro 16} {5 kurisu 18} {6 nagisa 20} {7 tomoyo 18}]
	}


	/*
		where:查詢
	*/
	girl2 := make([]Girl, 0)
	if  err = engine.Where("name = ?", "koishi").Find(&girl2);err!=nil{
		fmt.Println(nil)
	}else{
		fmt.Println(girl2) // [{2 koishi 16}]
	}

	girl3 := make([]Girl, 0)
	if err = engine.Where("name = ? and age = ?", "koishi", 16).Find(&girl3);err!=nil{
		fmt.Println(err)
	}else{
		fmt.Println(girl3) // [{2 koishi 16}]
	}

	girl4 := make([]Girl, 0)
	//where語句可以重復嵌套
	if err = engine.Where("name = ?", "koishi").Where("age = ?", 16).Find(&girl4);err!=nil{
		fmt.Println(err)
	}else{
		fmt.Println(girl4) // [{2 koishi 16}]
	}


	/*
	And:和where基本相同
	 */
	girl5 := make([]Girl, 0)
	if err = engine.Where("name = ?", "mashiro").And("age = ?", 16).Find(&girl5);err!=nil{
		fmt.Println(err)
	}else{
		fmt.Println(girl5) // [{4 mashiro 16}]
	}

	/*
	Or:
	 */
	girl6 := make([]Girl, 0)
	if err = engine.Where("name = ?", "mashiro").Or("age = ?", 16).Find(&girl6);err!=nil{
		fmt.Println(err)
	}else{
		fmt.Println(girl6) // [{1 satori 16} {2 koishi 16} {4 mashiro 16}]
	}

	girl7 := make([]Girl, 0)
	if err = engine.Where("name = ? or age = ?", "mashiro", 16).Find(&girl7);err!=nil{
		fmt.Println(err)
	}else{
		fmt.Println(girl7) // [{1 satori 16} {2 koishi 16} {4 mashiro 16}]
	}

	/*
	Asc:正序排序
	 */
	girl8 := make([]Girl, 0)
	if err = engine.Asc("name").Find(&girl8);err!=nil{
		fmt.Println(err)
	}else {
		fmt.Println(girl8) // [{3 frandlescarlet 400} {2 koishi 16} {5 kurisu 18} {4 mashiro 16} {6 nagisa 20} {1 satori 16} {7 tomoyo 18}]
	}


	/*
		Desc:正序排序
	*/
	girl9 := make([]Girl, 0)
	if err = engine.Desc("name").Find(&girl9);err!=nil{
		fmt.Println(err)
	}else {
		fmt.Println(girl9) // [{7 tomoyo 18} {1 satori 16} {6 nagisa 20} {4 mashiro 16} {5 kurisu 18} {2 koishi 16} {3 frandlescarlet 400}]
	}


	/*
	OrderBy:按照指定的順序排序,和Asc類似
	 */
	girl10 := make([]Girl, 0)
	if err = engine.OrderBy("name").Find(&girl10);err!=nil{
		fmt.Println(err)
	}else{
		fmt.Println(girl10) // [{3 frandlescarlet 400} {2 koishi 16} {5 kurisu 18} {4 mashiro 16} {6 nagisa 20} {1 satori 16} {7 tomoyo 18}]
	}


	/*
	Select:選擇想要的字段
	 */
	girl11 := make([]Girl, 0)
	if err = engine.Select("id,name").Find(&girl11);err!=nil{
		fmt.Println(err)
	}else{
		//只選擇id和name,可以看到age全是零值
		fmt.Println(girl11) //[{1 satori 0} {2 koishi 0} {3 frandlescarlet 0} {4 mashiro 0} {5 kurisu 0} {6 nagisa 0} {7 tomoyo 0}]
	}


	/*
	In
	 */
	girl12 := make([]Girl, 0)
	if err = engine.In("id", []int{1, 2,5}).Find(&girl12);err!=nil{
		fmt.Println(err)
	}else{
		fmt.Println(girl12) // [{1 satori 16} {2 koishi 16} {5 kurisu 18}]
	}


	/*
	Distinct
	 */
	girl13 := make([]Girl, 0)
	if err = engine.Distinct("age").Find(&girl13);err!=nil{
		fmt.Println(err)
	}else {
		fmt.Println(girl13) // [{0  16} {0  400} {0  20} {0  18}]
	}


	/*
	Limit:
	 */
	girl14 := make([]Girl, 0)
	//Limit(2, 3):取兩條,從第三條開始
	if err = engine.Limit(2, 3).Find(&girl14);err!=nil{
		fmt.Println(err)
	}else{
		fmt.Println(girl14) //[{4 mashiro 16} {5 kurisu 18}]
	}

}

不想寫了,可以查看https://www.kancloud.cn/xormplus/xorm/167094


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM