文章目录
- [1. beego-orm](#1. beego-orm)
-
- [1.1 介绍](#1.1 介绍)
- [1.2 特性](#1.2 特性)
- [1.3 使用](#1.3 使用)
-
- [1.3.1 安装](#1.3.1 安装)
- [1.3.2 导入与初始化](#1.3.2 导入与初始化)
- [1.3.3 模型定义](#1.3.3 模型定义)
-
- [1.3.3.1 定义模型代码](#1.3.3.1 定义模型代码)
- [1.3.3.2 模型常用标签](#1.3.3.2 模型常用标签)
- [1.3.4 基本操作(CURD)](#1.3.4 基本操作(CURD))
-
- [1.3.4.1 创建orm实例](#1.3.4.1 创建orm实例)
- [1.3.4.2 插入数据](#1.3.4.2 插入数据)
- [1.3.4.3 查询数据](#1.3.4.3 查询数据)
- [1.3.4.4 更新数据](#1.3.4.4 更新数据)
- [1.3.4.5 删除数据](#1.3.4.5 删除数据)
- [1.3.5 高级查询(QueryTable)](#1.3.5 高级查询(QueryTable))
- [1.3.6 关联关系](#1.3.6 关联关系)
-
- [1.3.6.1 一对一](#1.3.6.1 一对一)
- [1.3.6.2 一对多](#1.3.6.2 一对多)
- [1.3.6.3 多对多](#1.3.6.3 多对多)
- [1.3.6.4 关联操作](#1.3.6.4 关联操作)
- [1.3.7 事务处理(Begin&Rollback&Commit)](#1.3.7 事务处理(Begin&Rollback&Commit))
- [1.3.8 支持原生sql(Raw)](#1.3.8 支持原生sql(Raw))
- [1.3.9 表结构同步](#1.3.9 表结构同步)
- [1.3.10 连接池配置](#1.3.10 连接池配置)
- [1.3.11 性能优化](#1.3.11 性能优化)
- [1.3.12 调试](#1.3.12 调试)
- [1.3.13 常见问题](#1.3.13 常见问题)
-
- [1.3.13.1 表名冲突](#1.3.13.1 表名冲突)
- [1.3.13.2 字段映射问题](#1.3.13.2 字段映射问题)
- [1.3.13.3 时区问题](#1.3.13.3 时区问题)
1. beego-orm
1.1 介绍
Beego ORM是Beego框架的官方对象关系映射组件,提供了一种面向对象的方式来操作数据库
1.2 特性
- 支持多种数据库:MySQL、PostgreSQL、SQLite、Oracle、MSSQL
- 自动表结构生成(Syncdb)
- 链式查询构建器(QuerySeter)
- 关联关系(一对一、一对多、多对多)
- 事务支持
- 连接池管理
- 原生SQL支持
1.3 使用
1.3.1 安装
go
go get github.com/beego/beego/v2
1.3.2 导入与初始化
go
import (
"github.com/beego/beego/v2/adapter/orm"
_ "github.com/go-sql-driver/mysql" // 导入对应数据库驱动,例如mysql
)
func init() {
// 注册驱动(可选)
orm.RegisterDriver("mysql", orm.DRMySQL)
// 注册默认数据库
orm.RegisterDataBase("default", "mysql", "user:password@tcp(127.0.0.1:3306)/db_name?charset=utf8")
// 注册模型
orm.RegisterModel(new(User))
}
1.3.3 模型定义
1.3.3.1 定义模型代码
go
type User struct {
Id int `orm:"auto;pk"`
Username string `orm:"size(100);unique"`
Password string `orm:"size(100)"`
Age int `orm:"default(18)"`
Created time.Time `orm:"auto_now_add;type(datetime)"`
Updated time.Time `orm:"auto_now;type(datetime)"`
}
// 自定义表名
func (u *User) TableName() string {
return "users"
}
1.3.3.2 模型常用标签
标签 | 描述 | 示例 |
---|---|---|
auto | 自增字段 | orm:"auto" |
pk | 主键 | orm:"pk" |
size | 字段大小 | orm:"size(100)" |
default | 默认值 | orm:"default(0)" |
null | 允许NULL | orm:"null" |
index | 创建索引 | orm:"index" |
unique | 唯一约束 | orm:"unique" |
auto_now | 更新时间 | orm:"auto_now" |
auto_now_add | 创建时间 | orm:"auto_now_add" |
type | 字段类型 | orm:"type(text)" |
1.3.4 基本操作(CURD)
1.3.4.1 创建orm实例
go
o := orm.NewOrm()
1.3.4.2 插入数据
go
user := User{
Username: "xujie",
Password: "111111",
Age: 29,
}
// 插入数据语句
id, err := o.Insert(&user)
if err != nil {
logs.Error("插入数据失败!!!")
return
}
1.3.4.3 查询数据
go
// 通过主键查询
user := User{Id: 1}
_ := o.Read(&user)
// 通过指定字段查询
user := User{Username: "test"}
_ := o.Read(&user, "Username")
// 通过Filter方法查询多个
var users []*User
// 在user表中查询年龄大于20岁的用户
num, err := o.QueryTable("user").Filter("age__gt", 20).All(&users)
if err != nil {
logs.Error("查询数据失败!!!")
return
}
1.3.4.4 更新数据
go
user := User{Id: 1}
if err := o.Read(&user); err == nil {
user.Age = 30
num, err := o.Update(&user)
if err != nil {
logs.Error("更新数据失败!!!")
return
}
}
1.3.4.5 删除数据
go
// 根据id字段删除数据
num, _ := o.Delete(&User{Id: 1})
1.3.5 高级查询(QueryTable)
go
qs := o.QueryTable("user")
// 条件查询
qs = qs.Filter("username", "test") // WHERE username = 'test'
qs = qs.Filter("age__gt", 18) // WHERE age > 18
qs = qs.Filter("age__in", 18, 20, 22) // WHERE age IN (18, 20, 22)
qs = qs.Filter("username__contains", "test") // WHERE username LIKE '%test%'
qs = qs.Filter("username__startswith", "test") // WHERE username LIKE 'test%'
qs = qs.Filter("username__endswith", "test") // WHERE username LIKE '%test'
qs = qs.Filter("profile__isnull", true) // WHERE profile_id IS NULL
// 排序
qs = qs.OrderBy("age", "-username") // ORDER BY age ASC, username DESC
// 分页
qs = qs.Limit(10).Offset(20) // LIMIT 10 OFFSET 20
// 聚合
count, _ := qs.Count() // SELECT COUNT(*) FROM user
sum, _ := qs.Sum("age") // SELECT SUM(age) FROM user
avg, _ := qs.Avg("age") // SELECT AVG(age) FROM user
min, _ := qs.Min("age") // SELECT MIN(age) FROM user
max, _ := qs.Max("age") // SELECT MAX(age) FROM user
1.3.6 关联关系
1.3.6.1 一对一
go
type Profile struct {
Id int
Age int
User *User `orm:"reverse(one)"`
}
type User struct {
Id int
Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
}
1.3.6.2 一对多
go
type Post struct {
Id int
Title string
User *User `orm:"rel(fk)"`
}
type User struct {
Id int
Posts []*Post `orm:"reverse(many)"`
}
1.3.6.3 多对多
go
type User struct {
Id int
Roles []*Role `orm:"rel(m2m)"`
}
type Role struct {
Id int
Users []*User `orm:"reverse(many)"`
}
1.3.6.4 关联操作
go
// 一对多
user := User{Id: 1}
posts := []*Post{
{Title: "Post 1"},
{Title: "Post 2"},
}
o.InsertMulti(len(posts), posts)
// 多对多
role := Role{Id: 1}
m2m := o.QueryM2M(&role, "Users")
m2m.Add(&User{Id: 1})
1.3.7 事务处理(Begin&Rollback&Commit)
go
o := orm.NewOrm()
err := o.Begin()
// 事务操作
user := User{Username: "test"}
_, err = o.Insert(&user)
if err != nil {
o.Rollback()
return err
}
profile := Profile{User: &user}
_, err = o.Insert(&profile)
if err != nil {
o.Rollback()
return err
}
return o.Commit()
1.3.8 支持原生sql(Raw)
go
// 执行原生SQL
o.Raw("UPDATE user SET name = ? WHERE id = ?", "test", 1).Exec()
// 查询
var users []User
num, err := o.Raw("SELECT * FROM user WHERE age > ?", 18).QueryRows(&users)
// 单行查询
var user User
err := o.Raw("SELECT * FROM user WHERE id = ?", 1).QueryRow(&user)
1.3.9 表结构同步
go
// 自动创建表
// force: 是否强制删除重建
// verbose: 是否打印执行日志
_ = orm.RunSyncdb("default", false, true)
1.3.10 连接池配置
go
// 设置最大空闲连接
orm.SetMaxIdleConns("default", 30)
// 设置最大打开连接
orm.SetMaxOpenConns("default", 100)
1.3.11 性能优化
- 使用 Filter 替代 Exclude,后者性能较差
- 批量操作时使用 InsertMulti
- 避免 N+1 查询,使用 RelatedSel 预加载关联数据
- 复杂查询考虑使用原生 SQL
- 合理设置连接池大小
1.3.12 调试
go
// 开启调试模式
orm.Debug = true
// 查看最后执行的SQL
lastQuery := o.LastQuery()
1.3.13 常见问题
1.3.13.1 表名冲突
实现 TableName 方法自定义表名:
go
func (u *User) TableName() string {
return "users"
}
1.3.13.2 字段映射问题
确保数据库字段名与结构体字段名一致,或使用 column 标签
go
type User struct {
UserName string `orm:"column(username)"`
}
1.3.13.3 时区问题
go
orm.RegisterDataBase("default", "mysql", "user:password@tcp(127.0.0.1:3306)/db_name?charset=utf8&loc=Local")