下载引入框架
go语言中要使用orm框架需要先下载框架,并引入:
// 安装工具包
go get xorm.io/xorm
//安装数据库驱动(这里是mysql)
go get -u github.com/go-sql-driver/mysql
//引入框架
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
数据库构建
数据库构建,xorm也提供了数据表的构建功能,直接将结构体以构建为数据的表,专业事还是交给专业的人来做,有navicat这种构建和管理工具更专业。
构建如下数据库:
创建数据库引擎
创建引擎,所有数据库操作都需要基于数据库引擎,xorm提供两种数据库引擎,单例引擎和引擎组(一般直接命名为(Engine和Engine Group)。一个 Engine 引擎用于对单个数据库进行操作,一个 Engine Group 引擎用于对读写分离的数据库或者负载均衡的数据库进行操作。Engine 引擎和 EngineGroup 引擎的API基本相同,所有适用于 Engine 的API基本上都适用于 EngineGroup。
数据库引擎是单例模式,因此只能用指针类型。
var Engine *xorm.Engine
一般情况下引擎在包初始化函数init()
中初始化
func init(){
var err error
Engine, err = xorm.NewEngine("mysql", "root:123@/test?charset=utf8")
// err的错误处理
}
可以通过Engine.Ping()
来进行数据库的连接测试是否可以连接到数据库。通过Engine可以完成数据的CURD操作。
日志组件
xorm提供了日志组件来显示SQL,默认的显示级别为INFO。日志既可以通过运行的控制台来打印也可以保存到日志文件中。
Engine.ShowSQL(true)
会在控制台打印出生成的SQL语句;
engine.Logger().SetLevel(core.LOG_DEBUG)
更改控制台日志打印级别(这里是debug级别)
也可以将SQL信息保存到日志文件
f, err := os.Create("sql.log")
if err != nil {
println(err.Error())
return
}
Engine.SetLogger(xorm.NewSimpleLogger(f))
数据库连接池
Engine内部支持连接池接口和对应的函数。
如果需要设置连接池的空闲数大小,可以使用engine.SetMaxIdleConns()
来实现。
如果需要设置最大打开连接数,则可以使用engine.SetMaxOpenConns()
来实现。
数据库映射
创建完数据库引擎后,在使用时查询的数据需要赋值给go的数据结构(一般为结构体),xorm框架提供了多种映射方式。基于约定大于配置
的原则。
- SnakeMapper 支持struct为驼峰式命名,表结构为下划线命名之间的转换也是默认方式。
//设置其他映射方式
Engine.SetMapper(core.SameMapper{})
type StuTests struct {
StuId int
StuName string
StuAge int
StuSex string
}
//拆入数据
stu0 := StuTests{
0,
"xiaoxu1",
18,
"man",
}
//插入
Engine.Insert(&stu0)
//查询
var stu1 StuTests
Engine.Get(&stu1)
type Accounts struct {
Id int
User string
Password string
Role string
}
var act Accounts
Engine.Table("accounts").Where("id = ?", 1).Cols("user").Get(&act)
fmt.Println(act)
Engine.Get(&act)
fmt.Println(act)
数据库表和字段如下
如上图所示,使用该方式首字母大写的驼峰命名还是以单个单词的方式表名和字段名都可以成功映射。
还有其他映射方式访问非常优秀的学习网站xorm
- tag标签映射补充映射规则
在go的序列化一章,tag标签能够序列化json字符串,在xorm框架中也延用了这一特性。
type StuTests struct {
StuId int `xorm:"stu_id"`
StuName string `xorm:"stu_name"`
StuAge int `xorm:"stu_age"`
StuSex string `xorm:"stu_sex"`
}
tag标签一般用来做上一个映射方式的补充,应用于一些特殊的命名方式,另外如果表名命名方式也特殊的话可以使用engine.Table()
指定的临时表名。
导出数据库脚本
如果需要在web端通过按钮导出数据库脚本,实际上是通过Go语言执行数据库脚本,将sql文件导出到本地。
engine.DumpAll(w io.Writer)
方法返回数据库表的结构和数据的字节数组。
engine.DumpAllToFile(fpath string)
方法将数据库表的结构和数据写入到sql文件。
Engine.DumpAllToFile("./demo.sql")
执行后在文件夹下生成sql文件:
同样的也提供了导入的支持
engine.Import(r io.Reader)
engine.ImportFile(fpath string)
时间字段
在插入数据时需要时间可以在数据中设置生成当前时间,一般情况下编程语言生成的时间类型都是很全面的,在实际使用中一般只需要部分数据YYYY-MM-DD hh:mm:ss
类型。
Datetime:时间日期,格式是YYYY-mm-dd HH:ii:ss,表示的范围是从1000到9999年,有0值:0000-00-00 00:00:00。
Date:日期,就是datetime中的date部分。
Time:时间段,指定的某个区间之间,-时间到+时间。
Timestamp:时间戳,只是从1970年开始的YYYY-mm-dd HH:ii:ss 格式与datetime完全一致。
Year:年份,两种格式, year(2)和year(4):1901到2156
因此程序插入数据语言时都需要转化,xorm提供了自动转化的组件。
type StuTests struct {
StuId int `xorm:"stu_id"`
StuName string `xorm:"stu_name"`
StuAge int `xorm:"stu_age"`
StuSex string `xorm:"stu_sex"`
CreateTime time.Time `xorm:"created"`
}
在xorm标记中使用created
标记,对应的字段可以为time.Time或者自定义的time.Time或者int,int64等int类型。
stu0 := StuTests{
0,
"xiaoxu1-1",
18,
"man",
time.Now(),
}
Engine.Insert(&stu0)
然后正常插入即可,数据库的大的对应字段设置为datetime
。Updated
用于更新时自动同步当前时间。
数据库操作
xorm提供了众多方法,实现数据库操作,但是小编个人还是比较喜欢直接写sql语句的方式,因此接下来只介绍编写sql语句的方法。(习惯直接用框架方法的可以跳过了 😃)
Query 最原始的也支持SQL语句查询,返回的结果类型为 []map[string][]byte。QueryString 返回 []map[string]string, QueryInterface 返回 []map[string]interface{}
第一个方法返回字节数组,第二个方法返回struct的json字符串的形式,第三个方法返回空接口。一般使用第三个方法返回map数组[]map[string]interface{}
result, _ := Engine.QueryInterface("select * from stu_tests")
for index, item := range result {
fmt.Println(index)
fmt.Println(item)
}
Engine.Query
系列只用于执行DQL。
Engine.SQL()
返回值是一个Engine,用于sql和引擎方法混用。
var stu2 []StuTests
Engine.SQL("select * from stu_tests").Find(&stu2)
fmt.Println(stu2)
该方法返回的基本元素为结构体类型,因此查询多条数据需要返回结构体数组。
一般结合条件查询使用。
Engine.Exec()
用于执行DML,且支持表达式,?
作为占位符
//Engine.Exec()
sql := "update stu_tests set stu_name =? where stu_id =? "
result, err := Engine.Exec(sql, "hebei", 5)
if err != nil {
fmt.Println("demo4.main:update error", err)
return
}
返回result类型为sql.Result
,包含两个方法,分别返回最后插入行数的主键id和影响的行数。
//sql.Result
type Result interface {
LastInsertId() (int64, error)
RowsAffected() (int64, error)
}
Engine.Exec()
支持Insert, Update, Delete方法,支持表达式和占位符。插入就不要写sql了直接用engine.Insert()
方法。
实用方法
- 查询
Engine.SQL(DQL).Find(&变量)
DQL可以是任意结构化查询语言,通过Find批量查找返回的是一个结构体数组,实用起来非常方便。
// Engine.SQL() /*
//stu2 := make([]StuTests, 0)
var stu2 []StuTests
Engine.SQL("select * from stu_tests").Find(&stu2)
fmt.Println(stu2)
- 插入
Engine.Insert(...&变量)
通过结构体一键插入数据,(结构体于数据库表映射),支持单个和批量
- 更新
更新情况比较复杂,使用最多的为根据主键更新或者根据结构体更新。
- 根据主键更新
Engine.ID(1).Update(&user)
UPDATE user SET ... Where id = ?
前一个方法的为主键参数,后一个参数为更新的结构体,该方法已一个结构体为整体,需要注意是否需要回显。
Engine.Update(&user, &User{Name:name})
UPDATE user SET ... Where name = ?
结构体更新就是传入两个结构体变量,将满足第二个结构体数据的表中的数据,修改为第一个参数的结构体数据。
Engine.Exec("update user set age = ? where name = ?", age, name)
单个字段修改,使用Engine.Exec
方法对单个字段修改。
- 删除
数据库一般为软删除在数据库添加状态字段,查询时选择查询即可。
- SQL函数
在sql中经常使用sql函数,例如求和函数sum()
,获取记录函数count(*)
,平均数avg()
等,也可以使用一个较为通用的方法Engine.QueryString()
。
Engine.QueryString()
方法返回一个如下的map数组,在SQL查询中几乎所有数据都是以一个二维表的形式展现的。
[]map[string]string
那么这个二维表的数据项处理转化为结构体外,map类型也是比较直观的类型,对于一个数据项,列名为key,值为value,通过数组在存储多个数组。于是大多是查询的数据都可以直接转化为map的类型。
对于需要经常使用单个字段的转化为map不方便还需要解析,但是使用SQL方法一般查询的返回的比较少直接转化为map也具有通用性。
//count(*)函数
queryString, err := Engine.QueryString("select count(*) as sum from stu_tests")
if err != nil {
print(err)
return
}
fmt.Println(queryString)
fmt.Println(queryString[0]["sum"])
事务
对于一些重要的数据都需要事物的支持,xorm也提供了事物的支持。
Engine.NewSession()
创建一个事务数据库引擎,默认开启事物,并提供事物关闭方法,事务是原子操作需要提交。
session := Engine.NewSession()
//方法结束后关闭事务
defer session.Close()
// add Begin() before any action
if err := session.Begin(); err != nil {
// if returned then will rollback automatically
return err
}
/**
action
**/
// add Commit() after all actions
err = session.Commit()
if err != nil {
return
}
http://xorm.topgoer.com/
https://gitea.com/xorm/xorm/src/branch/master/README_CN.md