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

xorm:golang的orm(只写了一小部分)的更多相关文章

  1. drf序列化高级、自定义只读只写、序列化覆盖字段、二次封装Response、数据库查询优化(断关联)、十大接口、视图家族

    目录 自定义只读 自定义只写 序列化覆盖字段 二次封装Response 数据库关系分析 断外键关联关系 ORM操作外键关系 ORM四种关联关系 基表 系列化类其他配置(了解) 十大接口 BaseSer ...

  2. Go 只读/只写channel

    Go中channel可以是只读.只写.同时可读写的. //定义只读的channel read_only := make (<-chan int) //定义只写的channel write_onl ...

  3. ES6新增对象方法的访问描述符:get(只读)、set(只写)

    Es6新增对象方法的访问描述符:get(只读).set(只写),可以直接使用,一般用于数据监听,用途类似于vue.$watch. var obj = { a:1, get bar() { return ...

  4. JS调用函数时候加括号与只写函数名字的区别 fn与fn()的区别

    经常见插件里面函数调用的时候只写个函数名字,不写函数参数,甚至连括号也不写,比如说: <!DOCTYPE html> <html> <head> <meta ...

  5. python文件的只读,只写操作

    只读:r rb(bytes类型数据) 只写:w wb(bytes类型数据) 在文件最后追加: f = open('log',mode='a',encoding='utf-8') f.write('这里 ...

  6. 只写Python一遍代码,就可以同时生成安卓及IOS的APP,真优秀

    前言: 用Python写安卓APP肯定不是最好的选择,但是肯定是一个很偷懒的选择 我们使用kivy开发安卓APP,Kivy是一套专门用于跨平台快速应用开发的开源框架,使用Python和Cython编写 ...

  7. Golang,用map写个单词统计器

    Golang中也有实用的泛型编程模板.如map.据Go官方团队称,其实现为Hash表,而非类似cpp或Java的红黑树.所以理论上速度更能快上几个等级(Hash与红黑树的效率对比可以看我的文章C++中 ...

  8. 使用sqlalchemy用orm方式写pipeline将scrapy item快速存入 MySQL

    传统的使用scrapy爬下来的数据存入mysql,用的是在pipeline里用pymysql存入数据库, 这种方法需要写sql语句,如果item字段数量非常多的 情况下,编写起来会造成很大的麻烦. 我 ...

  9. Golang beego ORM + CRUP 操作详解

      构建beego Web 项目         首先构建一个beego 的web 项目,这个我们完全可以参考beego 官网中的开发文档,上面介绍的非常的详细,在这我就不给大家介绍,主要是介绍ORM ...

随机推荐

  1. NDK的环境配置

    http://www.androiddevtools.cn/ 下载NDK, 最新版本. 解压压缩包,如解压后文件夹名为如android-ndk-r13,放在指定的位置 配置环境变量: 系统环境path ...

  2. 代码实现从键盘接收一个字符串, 程序对其中所有字符进行排序,例如键盘输入: helloitcast程序打印:acehillostt

    package com.loaderman.test; import java.util.Comparator; import java.util.Scanner; import java.util. ...

  3. 作业类型维护流程(CO)

    一.建立作业类型——kl01 目的: 藉由做作業類型執行生產報工 目錄路徑: 會計à成本控制à成本中心會計à主檔資料à作業類型à個別處理à KL01 - 建立 Transaction   Code: ...

  4. 用泛型方法Java从实体中提取属性值,以及在泛型方法中的使用

    public <T> T getFieldValue(Object target, String fieldName, Class<T> typeName) { try { O ...

  5. 机器学习:gensim之Word2Vec 详解

    一 前言 Word2Vec是同上一篇提及的PageRank一样,都是Google的工程师和机器学习专家所提出的的:在学习这些算法.模型的时候,最好优先去看Google提出者的原汁Paper和Proje ...

  6. CDC类介绍

    CDC类 中文介绍 CDC类定义的是设备上下文对象的类. CDC对象提供处理显示器或打印机等设备上下文的成员函数,以及处理与窗口客户区对应的显示上下文的成员. 通过CDC对象的成员函数进行所有的绘图. ...

  7. 技术简历写这么写,才能得到BAT面试官们的青睐

    公众号[程序员江湖] 作者陆小凤,985 软件硕士,阿里 Java 研发工程师,在技术校园招聘.自学编程.计算机考研等方面有丰富经验和独到见解,目前致力于分享程序员干货和学习经验,同时热衷于分享作为程 ...

  8. 【AMAD】splinter -- 用于测试web app的python框架

    简介 动机 作用 用法 热度分析 个人评分 简介 Splinter1是一个开源工具,使用Python编写,用于测试web apps.它可以用来对浏览器实现自动化操作,比如访问URLs,和按钮等交互. ...

  9. HTTPS SSL TLS 相关理解

    1,在理解 HTTPS SSL TLS 之前先对常用的加密方式进行一个简述: (1),对称加密: 采用一个密钥,对明文进行加密生成密文,相反采用此密钥可对加密后的密文进行解密还原成明文. 代表算法有, ...

  10. Ubuntu重启关机命令

    重启命令 :  1.reboot 立刻重启 2.shutdown -r now 立刻重启 3.shutdown -r 10 过10分钟自动重启 4.shutdown -r 20:35 在时间为20:3 ...