详解Go语言如何使用xorm实现读取mysql

目录
  • 一、介绍
  • 二、安装使用xorm,注意连接的关闭!
    • 关于连接数的坑以及engine.Close()
    • 常用方法介绍
  • 三、mysql生产struct
  • 四、xorm常用操作示例--insert数据
    • 4.1 insert 增加1条数据
    • 4.2 insert 增加多条数据
    • 4.3 insert 增加不同表数据
  • 五、xorm常用操作示例--删除某行
    • 5.1 通过id删除
    • 5.2 通过where条件删除
    • 5.3 软删除,通过某个字段实现软删除,比如status=0
  • 六、xorm常用操作示例--update更新操作
    • 6.1 以结构体的参数,传递要更新的字段
    • 6.2 以map做为参数,传递要更新的字段
    • 6.3指定字段更新,未指定的将不更新,指定了的即使为0也会更新。
    • 6.4指定字段更新,未指定的根据值是否是有值来更新。
  • 七、xorm常用操作示例--查询单条
    • 7.1 根据主键Id来获得单条数据:
    • 7.2 根据where来获得单条数据:
    • 7.3 根据user机构体中非空数据来获得单条数据:
  • 八、xorm常用操作示例--查询多条数据
    • 8.1 返回结果为 结构体slice:
    • 8.2 返回结果为 结构体map:
  • 九、xorm常用操作示例--FindAndCount 分页
  • 十、xorm常用操作示例--事务操作

一、介绍

xorm是go语言的常用orm之一,用来操作数据库。

主要特性特性:

  • 支持根据数据库自动生成xorm的结构体
  • 支持Struct和数据库表之间的灵活映射, 并支持自动同步
  • 支持事务
  • 支持使用Id, In, Where, Limit, Join, Having, Table, Sql, Cols等函数和结构体等方式作为条件
  • 支持查询结果集导出csv、tsv、xml、json、xlsx、yaml、html功能

二、安装使用xorm,注意连接的关闭!

import (
    _ "github.com/go-sql-driver/mysql"
    "xorm.io/xorm"
)

然后我们就可以构造一个new方法来初始化使用 orm客户端了。

我们在下面的代码,会通过一个函数返回 xorm.EngineInterface,以及一个 engine.Close()函数供使用者调用,之所以这样是因为,有些比如脚本脚本之类的
当执行完,就需要把 mysql连接关闭掉,以用来节省连接数。

如果都不关闭的话,在高并发的情况下,连接数很多,会把mysql打爆!

type MysqlClient xorm.EngineInterface
func NewMysqlClient() (MysqlClient, func(), error) {
    // 创建 engine 对象
    engine, err := xorm.NewEngine("mysql", "user:pwd@tcp(ip:port)/dbname?charset=utf8")
    if err != nil {
        fmt.Printf("init engine fail! err:%+v", err)
    }
    // 连接池配置
    engine.SetMaxOpenConns(30)                  // 最大 db 连接
    engine.SetMaxIdleConns(10)                  // 最大 db 连接空闲数
    engine.SetConnMaxLifetime(30 * time.Minute) // 超过空闲数连接存活时间

    // 日志相关配置
    engine.ShowSQL(true)                    // 打印日志
    engine.Logger().SetLevel(log.LOG_DEBUG) // 打印日志级别
    engine.SetLogger(log.SimpleLogger{})    // 设置日志输出 (控制台, 日志文件, 系统日志等)

    // 测试连通性
    if err = engine.Ping(); err != nil {
        fmt.Printf("ping to db fail! err:%+v", err)
    }
    return engine, func() {
        engine.Close()
    }, err
}

关于连接数的坑以及engine.Close()

engine可以通过engine.Close来手动关闭,但是一般情况下可以不用关闭,在程序退出时会自动关闭。

但是如果,每个连接都是新建了一个 client的话,一般http服务不会退出,如果此时高并发,就会增加无数的mysql连接数,打爆mysql。

在这个NewMysqlClient函数里我们创建了一个 全局的变量 MysqlClient,全局共用一个连接。

常用方法介绍

engine.SetMaxOpenConns(30) 创建连接池

engine.ShowSQL(true) 在控制台打印sql语句

engine.Logger().SetLevel(log.LOG_DEBUG) 在控制台打印调试及以上的信息

engine.SetLogger(log.DiscardLogger{}) 把日志写入到文件,或者专门的日志收集系统里。

三、mysql生产struct

使用官方自带的reverse工具 https://gitea.com/xorm/reverse比如我们现在在有一个表

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  `status` smallint(6) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB

我们使用 reverse -f sql_reverse.yaml 来生成 struct

sql_reverse.yaml的代码如下:

# 步骤1:安装 go get xorm.io/reverse
# 步骤2:修改上面文件中的conn_str以及include_tables的表
# 步骤3:执行reverse -f sql_reverse.yaml

kind: reverse
name: mydb
source:
  database: mysql
  conn_str: 'user:pasword@tcp(localhost:3306)/test?charset=utf8mb4'
targets:
  - type: codes
    language: golang
    include_tables: # 需要生成的表的结构
      - user //我们要生产的表明
    multiple_files: true
    output_dir: ./internal/domain/flow/repository/po
    template: |
      package po

      {{$ilen := len .Imports}}
      {{if gt $ilen 0}}
      import (
        {{range .Imports}}"{{.}}"{{end}}
      )
      {{end}}

      {{range .Tables}}
      type {{TableMapper .Name}} struct {
      {{$table := .}}
      {{range .ColumnsSeq}}{{$col := $table.GetColumn .}}    {{ColumnMapper $col.Name}}    {{Type $col}} `{{Tag $table $col}}`
      {{end}}
      }

      func (m *{{TableMapper .Name}}) TableName() string {
          return "{{$table.Name}}"
      }
      {{end}}
    template_path: ./template/goxorm.tmpl # template path for code file, it has higher perior than template field on language

生成对应的go代码为

type User struct {
    Id     int64  `json:"id" xorm:"'id' int(11) not null pk autoincr  "`
    Name   string `json:"name" xorm:"'name' varchar(45) null   "`
    Status int64  `json:"status" xorm:"'status' smallint(3) null   "`
}

func (m *User) TableName() string {
    return "user"
}

四、xorm常用操作示例--insert数据

4.1 insert 增加1条数据

增加一条对象。

engine, _, _ := NewMysqlClient()
    u := User{
        Name:   "hisheng",
        Status: 0,
    }
    affected, err := engine.Insert(&u)
    t.Log(affected, err)

4.2 insert 增加多条数据

多条数据,还是Insert方法,参数为slice就行。

func TestInsertUsers(t *testing.T) {
    engine, _, _ := NewMysqlClient()
    us := []User{{Name: "hi", Status: 1}, {Name: "sheng", Status: 1}}
    affected, err := engine.Insert(&us)
    t.Log(affected, err)
}

当插入多条数据的时候,官方建议我们少于150条数据,多余150条数据的时候,容易插入失败。

4.3 insert 增加不同表数据

user := new(User)
user.Name = "myname"
...
questions := make([]Question, 1)
questions[0].Content = "whywhywhwy?"
affected, err := engine.Insert(user, &questions)

五、xorm常用操作示例--删除某行

5.1 通过id删除

user := new(User)
affected, err := engine.ID(id).Delete(user)

5.2 通过where条件删除

user := new(User)
affected, err := engine.Where("id = ?",1).Delete(user)

5.3 软删除,通过某个字段实现软删除,比如status=0

这个用更新的方法

u := User{
        Status: 0,
    }
    affected, err := engine.Where("id = ?",1).MustCols("status").Update(&u)
    t.Log(affected, err)

注意这里,增加了一个MustCols,因为xorm默认是有值自动更新的,而status和默认值,是一样的,默认值会被忽略而不被更新,此时要更新,需要加一个 MustCols字段。

六、xorm常用操作示例--update更新操作

6.1 以结构体的参数,传递要更新的字段

func TestUpdate(t *testing.T) {
    engine, _, _ := NewMysqlClient()
    u := User{
        Name: "1111",
    }
    affected, err := engine.ID(1).Update(&u)
}

这个会Update的参数是更新字段。这里会更新Name字段。

6.2 以map做为参数,传递要更新的字段

以map作为要更新的字段,传递方式,map的格式为 map[string]interface{}

func TestUpdateMap(t *testing.T) {
    engine, _, _ := NewMysqlClient()
    u := map[string]interface{}{"name": "111"}
    affected, err := engine.ID(1).Update(u)
}

6.3指定字段更新,未指定的将不更新,指定了的即使为0也会更新。

我们通过添加Cols函数指定需要更新结构体中的值。

affected, err := engine.ID(id).Cols("age").Update(&user)

6.4指定字段更新,未指定的根据值是否是有值来更新。

有时候希望能够指定必须更新某些字段,而其它字段根据值的情况自动判断,可以使用 MustCols 来组合 Update 使用。

affected, err := engine.ID(id).MustCols("age").Update(&user)

七、xorm常用操作示例--查询单条

查询单条数据使用Get方法,在调用Get方法时需要传入一个对应结构体的指针,同时结构体中的非空field自动成为查询的条件和前面的方法条件组合在一起查询。

7.1 根据主键Id来获得单条数据:

user := new(User)
has, err := engine.ID(id).Get(user)

7.2 根据where来获得单条数据:

user := new(User)
has, err := engine.Where("name=?", "xlw").Get(user)

7.3 根据user机构体中非空数据来获得单条数据:

user := &User{Id:1}
has, err := engine.Get(user)

八、xorm常用操作示例--查询多条数据

查询多条数据使用Find方法,Find方法的第一个参数为slice的指针或Map指针,即为查询后返回的结果,第二个参数可选,为查询的条件struct的指针。

8.1 返回结果为 结构体slice:

everyone := make([]User, 0)
err := engine.Find(&everyone)

8.2 返回结果为 结构体map:

users := make(map[int64]User)
err := engine.Find(&users)

九、xorm常用操作示例--FindAndCount 分页

FindAndCount 返回结果为 结构体slice 以及总数:

everyone := make([]User, 0)
count,err := engine.Limit(1,20).FindAndCount(&everyone)

十、xorm常用操作示例--事务操作

func TestTransaction(t *testing.T) {
    engine, _, _ := NewMysqlClient()
    session := engine.NewSession()
    defer session.Close()
    if err := session.Begin(); err != nil {
        fmt.Println(err)
        return
    }
    if _, err := session.Insert(&User{Name: "11", Status: 0}); err != nil {
        fmt.Println(err)
        _ = session.Rollback()
        return
    }
    _ = session.Commit()
}

以上就是详解Go语言如何使用xorm实现读取mysql的详细内容,更多关于Go语言 xorm读取mysql的资料请关注我们其它相关文章!

(0)

相关推荐

  • 聊聊go xorm生成mysql的结构体问题

    网上很多资源都说是xorm reverse mysql "root:123456@tcp(127.0.0.1:3306)/users?charset=utf8" ./ 执行后报错:2022/03/16 15:00:53 [Error] reverse.go:196 Unknown colType INT UNSIGNED 实际上原有的xorm 已经不能用了,现在要这么用: go get xorm.io/reverse 然后进入到GOPATH下面的bin目录 vi custom.yml,

  • 使用go xorm来操作mysql的方法实例

    在golang中要实现对数据库的操作, 一个比较好用的方式就是使用XORM,xorm是一个简单而强大的Go语言ORM库,通过它可以使数据库操作非常简便. 在xorm里面,可以同时存在多个ORM引擎,一个ORM引擎称为Engine,一个Engine一般只对应一个数据库. golang的连接池配置 这里初始化一个全局的xorm.Engine对象, xorm.Engine通过调用xorm.NewEngine生成在很多其他的API都需要传入该对象作为参数. 这里需要理解这里设定的3个参数的意义: Set

  • Go 使用xorm操作mysql详情

    目录 xorm 安装 生成数据结构 struct 使用 xorm xorm 官方介绍:xorm 是一个简单而强大的 Go 语言 ORM 库. 通过它可以使数据库操作非常简便. xorm 的目标并不是让你完全不去学习 SQL,我们认为 SQL 并不会为 ORM 所替代,但是 ORM 将可以解决绝大部分的简单 SQL 需求. xorm 支持两种风格的混用. xorm 还提供了工具,通过 reverse 命令根据数据库的表结构生成对应的 struct,省去了人工组织代码的工作,十分方便.官方地址:ht

  • 详解Go语言如何使用xorm实现读取mysql

    目录 一.介绍 二.安装使用xorm,注意连接的关闭! 关于连接数的坑以及engine.Close() 常用方法介绍 三.mysql生产struct 四.xorm常用操作示例--insert数据 4.1 insert 增加1条数据 4.2 insert 增加多条数据 4.3 insert 增加不同表数据 五.xorm常用操作示例--删除某行 5.1 通过id删除 5.2 通过where条件删除 5.3 软删除,通过某个字段实现软删除,比如status=0 六.xorm常用操作示例--update

  • 详解C语言函数返回值解析

    详解C语言函数返回值解析 程序一: int main() { int *p; int i; int*fun(void); p=fun(); for(i=0;i<3;i++) { printf("%d\n",*p); p++; } return 0; }; int* fun(void) { static int str[]={1,2,3,4,5}; int*q=str; return q; } //不能正确返回 虽然str是在动态变量区,而该动态变量是局部的,函数结束时不保留的.

  • 详解C语言 三大循环 四大跳转 和判断语句

    三大循环for while 和 do{ }while; 四大跳转 : 无条件跳转语句 go to; 跳出循环语句 break; 继续跳出循环语句 continue; 返回值语句 return 判断语句 if,if else,if else if else if...else ifelse 组合 if(0 == x) if(0 == y) error(): else{ //program code } else到底与那个if配对 C语言有这样的规定: else 始终与同一括号内最近的未匹配的if语

  • 详解C语言gets()函数与它的替代者fgets()函数

    在c语言中读取字符串有多种方法,比如scanf() 配合%s使用,但是这种方法只能获取一个单词,即遇到空格等空字符就会返回.如果要读取一行字符串,比如: I love BIT 这种情况,scanf()就无能为力了.这时我们最先想到的是用gets()读取. gets()函数从标准输入(键盘)读入一行数据,所谓读取一行,就是遇到换行符就返回.gets()函数并不读取换行符'\n',它会吧换行符替换成空字符'\0',作为c语言字符串结束的标志. gets()函数经常和puts()函数配对使用,puts

  • 详解C 语言项目中.h文件和.c文件的关系

    详解C 语言项目中.h文件和.c文件的关系 在编译器只认识.c(.cpp))文件,而不知道.h是何物的年代,那时的人们写了很多的.c(.cpp)文件,渐渐地,人们发现在很多.c(.cpp)文件中的声明语句就是相同的,但他们却不得不一个字一个字地重复地将这些内容敲入每个.c(.cpp)文件.但更为恐怖的是,当其中一个声明有变更时,就需要检查所有的.c(.cpp)文件. 于是人们将重复的部分提取出来,放在一个新文件里,然后在需要的.c(.cpp)文件中敲入#include XXXX这样的语句.这样即

  • 详解C语言用malloc函数申请二维动态数组的实例

    详解C语言用malloc函数申请二维动态数组的实例 C语言在程序运行中动态的申请及释放内存十分方便,一维数组的申请及释放比较简单. Sample one #include <stdio.h> int main() { char * p=(char *)malloc(sizeof(char)*5);//申请包含5个字符型的数组 free(p); return 0; } 是否申请二维动态内存也如此简单呢?答案是否定的.申请二维数组有一下几种方法 Sample two /* 申请一个5行3列的字符型

  • 详解易语言的程序的输入方法概念

    为了便于输入程序,易语言内置四种名称输入法:首拼.全拼.双拼.英文.三种拼音输入法均支持南方音及多音字.首拼输入法及全拼输入法在系统中被合并为"首拼及全拼输入法",系统自动判别所输入的拼音是首拼方式还是全拼方式.双拼输入法的编码规则与 Windows 系统所提供的双拼输入法一致.例如:欲输入"取整 (1.23)"语句,各种输入法的输入文本为: ・ 首拼及全拼输入法: qz(1.23) 或者 quzheng(1.23) ・ 双拼输入法: quvg(1.23) ・ 英文

  • 详解go语言 make(chan int, 1) 和 make (chan int) 的区别

    遇到golang channel 的一个问题:发现go 协程读取channel 数据 并没有按照预期进行协作执行. 经过查资料: 使用channel 操作不当导致,channel分 有缓冲区 和 无缓冲区 , 以下是两者的区别. 无缓冲区channel 用make(chan int) 创建的chan, 是无缓冲区的, send 数据到chan 时,在没有协程取出数据的情况下, 会阻塞当前协程的运行.ch <- 后面的代码就不会再运行,直到channel 的数据被接收,当前协程才会继续往下执行.

  • 详解C语言-二级指针三种内存模型

    二级指针相对于一级指针,显得更难,难在于指针和数组的混合,定义不同类型的二级指针,在使用的时候有着很大的区别 第一种内存模型char *arr[] 若有如下定义 char *arr[] = {"abc", "def", "ghi"}; 这种模型为二级指针的第一种内存模型,在理解的时候应该这样理解:定义了一个指针数组(char * []),数组的每个元素都是一个地址. 在使用的时候,若要使用中间量操作元素,那么此时中间量应该定义为 char *tm

  • 详解C语言进程同步机制

    本文是对进程同步机制的一个大总结(9000+字吐血总结),涵盖面非常的全,包括了进程同步的一些概念.软件同步机制.硬件同步机制.信号量机制和管程机制,对每种机制结合代码做了详细的介绍,并且对琐碎的知识点和概念解释的非常清晰. ​ 在前面的博客中讲述了进程的状态及其状态的转换,每种状态的含义和转换的原因.同样我们也知道,在OS引入了进程后,可以使系统中的多道程序可以并发的执行,进程的并发执行一方面极大的提高了系统的资源利用率和吞吐量,但是另一方面却使系统变得更加复杂,如果不能采取有效的措施,对多个

随机推荐