zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    string与wstring之间的转换
    QTableWidget去除选中虚边框
    在新机器部署Qt+mysql程序
    Qt文件路径分隔符
    MySQL通过增加用户实现远程连接数据库
    Qt 配置文件QSettings读取以及中文问题
    git config proxy
    ubuntu14.04 us sources.list
    How to keep Environment Variables when Using SUDO
    ubuntu hash sum mismatch error
  • 原文地址:https://www.cnblogs.com/traditional/p/11414089.html
Copyright © 2011-2022 走看看