文章目录
一 xorm简介
xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。xorm的目标并不是让你完全不去学习SQL,我们认为SQL并不会为ORM所替代,但是ORM将可以解决绝大部分的简单SQL需求。xorm支持两种风格的混用。
官方文档:https://xorm.io/zh/docs/
1.1 特性
- 支持 Struct 和数据库表之间的灵活映射,并支持自动同步
- 事务支持
- 同时支持原始SQL语句和 ORM 操作的混合执行
- 使用连写来简化调用
- 支持使用ID, In, Where, Limit, Join, Having, Table, SQL, Cols等函数和结构体等方式作为条件
- 支持级联加载 Struct
- Schema支持(仅Postgres)
- 支持缓存
- 通过 xorm.io/reverse 支持根据数据库自动生成 xorm 结构体
- 支持记录版本(即乐观锁)
- 通过 xorm.io/builder 内置 SQL Builder 支持
- 上下文缓存支持
- 支持日志上下文
1.2 驱动支持
- Mysql5.* / Mysql8.* / Mariadb / Tidb
- Postgres / Cockroach
- SQLite
- MsSql
- Oracle
- github.com/mattn/go-oci8 (试验性支持)
二 第一个xorm应用
2.1 安装库
go get xorm.io/xorm
go get github.com/go-sql-driver/mysql
2.2 创建数据库
C:\Users\Mechrevo>mysql -uroot -p
Enter password: ******
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 20
Server version: 8.0.19 MySQL Community Server - GPL
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create database test_xorm;
Query OK, 1 row affected (0.48 sec)
mysql> use test_xorm;
Database changed
2.3 连接数据库
package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"xorm.io/xorm"
)
var engine *xorm.Engine
func main() {
var err error
engine, err = xorm.NewEngine("mysql", "root:960690@/test_xorm?charset=utf8")
if err != nil {
fmt.Printf("err : %v\n", err)
} else {
err2 := engine.Ping()
if err2 != nil {
fmt.Printf("err2 : %v\n", err2)
} else {
print("数据库连接成功!")
}
}
}
运行结果:
[Running] go run "e:\golang开发学习\go_pro\test.go"
[xorm] [info] 2022/08/11 17:04:41.129767 PING DATABASE mysql
数据库连接成功!
[Done] exited with code=0 in 2.191 seconds
2.4 创建结构体
type User struct {
Id int64
Name string
Salt string
Age int
Passwd string `xorm:"varchar(200)"`
Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"`
}
2.5 创建表
// 创建表
err3 := engine.Sync(new(User))
if err3 != nil {
fmt.Printf("err2 : %v\n", err3)
} else {
fmt.Println("表创建成功!")
}
数据库查看:
2.6 添加数据
// 添加数据
user := User{
Id: 1,
Name: "Psych",
Salt: "salt",
Age: 18,
Passwd: "666",
}
i, err4 := engine.Insert(&user)
if err4 != nil {
fmt.Printf("err : %v\n", err4)
} else {
fmt.Printf("创建记录数量: %v\n", i)
}
数据库查看:
2.7 完整代码
package main
import (
"fmt"
"time"
_ "github.com/go-sql-driver/mysql"
"xorm.io/xorm"
)
var engine *xorm.Engine
type User struct {
Id int64
Name string
Salt string
Age int
Passwd string `xorm:"varchar(200)"`
Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"`
}
func main() {
var err error
engine, err = xorm.NewEngine("mysql", "root:960690@/test_xorm?charset=utf8")
if err != nil {
fmt.Printf("err : %v\n", err)
} else {
err2 := engine.Ping()
if err2 != nil {
fmt.Printf("err2 : %v\n", err2)
} else {
print("数据库连接成功!")
}
}
// 创建表
err3 := engine.Sync(new(User))
if err3 != nil {
fmt.Printf("err2 : %v\n", err3)
} else {
fmt.Println("表创建成功!")
}
// 添加数据
user := User{
Id: 1,
Name: "Psych",
Salt: "salt",
Age: 18,
Passwd: "666",
}
i, err4 := engine.Insert(&user)
if err4 != nil {
fmt.Printf("err : %v\n", err4)
} else {
fmt.Printf("创建记录数量: %v\n", i)
}
}
三 xorm定义表结构体
3.1 表名称映射规则
跟名称相关的函数包含在 xorm.io/xorm/names
下。名称映射规则主要负责结构体名称到表名和结构体 field 到表字段的名称映射。由 names.Mapper
接口的实现者来管理,xorm 内置了三种 Mapper
实现:names.SnakeMapper
, names.SameMapper
和names.GonicMapper
。
- SnakeMapper:支持struct为驼峰式命名,表结构中为下划线命名之间的转换。该种规则为xorm默认的Maper;
- SameMapper:映射规则支持结构体名称和对应的表名称以及结构体field名称与对应的表字段名称相同的命名;
- GonicMapper:该映射规则和驼峰式命名类似,但是对于特定词支持性更好,比如ID将会翻译成id,而不是驼峰式的i_d。
当前SnakeMapper为默认值,如果需要改变时,在engine创建完成后使用
engine.SetMapper(names.GonicMapper{
})
另外,可以设置表名和表字段分别为不同的映射规则:
engine.SetTableMapper(names.SameMapper{})
engine.SetColumnMapper(names.SnakeMapper{})
测试:
package main
import (
"fmt"
"time"
_ "github.com/go-sql-driver/mysql"
"xorm.io/xorm"
"xorm.io/xorm/names"
)
var engine *xorm.Engine
type LoginUser struct {
Id int64
Name string
Salt string
Age int
Passwd string `xorm:"varchar(200)"`
Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"`
}
func init() {
var err error
engine, err = xorm.NewEngine("mysql", "root:960690@/test_xorm?charset=utf8")
if err != nil {
fmt.Printf("err : %v\n", err)
} else {
err2 := engine.Ping()
if err2 != nil {
fmt.Printf("err2 : %v\n", err2)
} else {
print("数据库连接成功!")
}
}
}
func main() {
engine.ShowSQL(true)
// engine.SetMapper(names.GonicMapper{})
engine.SetMapper(names.SnakeMapper{
})
// engine.SetMapper(names.SameMapper{})
// 创建表
err := engine.Sync(new(LoginUser))
if err != nil {
fmt.Printf("err : %v\n", err)
} else {
fmt.Println("表创建成功!")
}
}
数据库查看:
3.2 前缀映射,后缀映射和缓存映射
- 通过
names.NewPrefixMapper(names.SnakeMapper{}, "prefix")
可以创建一个在 SnakeMapper 的基础上在命名中添加统一的前缀,当然也可以把 SnakeMapper{} 换成 SameMapper 或者你自定义的 Mapper。
例如,如果希望所有的表名都在结构体自动命名的基础上加一个前缀而字段名不加前缀,则可以在 engine 创建完成后执行以下语句:
tbMapper := names.NewPrefixMapper(names.SnakeMapper{
}, "prefix_")
engine.SetTableMapper(tbMapper)
执行之后,结构体 type User struct
默认对应的表名就变成了 prefix_user
了,而之前默认的是 user
- 通过
names.NewSuffixMapper(names.SnakeMapper{}, "suffix")
可以创建一个在 SnakeMapper 的基础上在命名中添加统一的后缀,当然也可以把SnakeMapper换成SameMapper或者你自定义的Mapper。 - 通过
names.NewCacheMapper(names.SnakeMapper{})
可以创建一个组合了其它的映射规则,起到在内存中缓存曾经映射过的命名映射。
测试:
package main
import (
"fmt"
"time"
_ "github.com/go-sql-driver/mysql"
"xorm.io/xorm"
"xorm.io/xorm/names"
)
var engine *xorm.Engine
type LoginUser struct {
Id int64
Name string
Salt string
Age int
Passwd string `xorm:"varchar(200)"`
Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"`
}
func init() {
var err error
engine, err = xorm.NewEngine("mysql", "root:960690@/test_xorm?charset=utf8")
if err != nil {
fmt.Printf("err : %v\n", err)
} else {
err2 := engine.Ping()
if err2 != nil {
fmt.Printf("err2 : %v\n", err2)
} else {
print(