【golang】ORM框架操作数据库

文章目录

  • [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 特性

  1. 支持多种数据库:MySQL、PostgreSQL、SQLite、Oracle、MSSQL
  2. 自动表结构生成(Syncdb)
  3. 链式查询构建器(QuerySeter)
  4. 关联关系(一对一、一对多、多对多)
  5. 事务支持
  6. 连接池管理
  7. 原生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 性能优化

  1. 使用 Filter 替代 Exclude,后者性能较差
  2. 批量操作时使用 InsertMulti
  3. 避免 N+1 查询,使用 RelatedSel 预加载关联数据
  4. 复杂查询考虑使用原生 SQL
  5. 合理设置连接池大小

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")
相关推荐
CTRA王大大41 分钟前
【golang】制作linux环境+golang的Dockerfile | 如何下载golang镜像源
linux·开发语言·docker·golang
#include>44 分钟前
【Golang】有关垃圾收集器的笔记
笔记·golang
秦禹辰7 小时前
本地Docker部署开源Web相册图库Piwigo与在线远程访问实战方案
开发语言·后端·golang
省四收割者1 天前
Go语言入门(10)-数组
数据结构·经验分享·笔记·vscode·算法·golang
君万1 天前
【LeetCode每日一题】56. 合并区间
算法·leetcode·golang
学历真的很重要1 天前
Eino 开源框架全景解析 - 以“大模型应用的搭积木指南”方式理解(一)
后端·语言模型·面试·golang·ai编程·eino
bing.shao1 天前
gRPC 选型 etcd 的核心优势分析
数据库·微服务·云原生·golang·etcd
He1955012 天前
Go初级二
开发语言·后端·golang
王伯爵2 天前
go语言中的select的用法和使用场景
开发语言·数据库·golang