go-zero&go web集成gorm实战

前言

上一篇:go-zero&go web集成redis实战

从零开始基于go-zero搭建go web项目实战-04集成gorm实战
源码仓库地址 源码 https://gitee.com/li_zheng/treasure-box

golang gorm

官网地址:https://gorm.io/zh_CN/docs/index.html

GORM介绍

Gorm是Go语言目前比较热门的数据库ORM库,API简单明了,上手容易,使用简单,主要把struct类型和数据库表记录进行映射,操作数据库的时候不需要直接手写SQL,面向结构体,同时也支持手动编写sql进行调优。

特性

  • 全功能 ORM
  • 关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)
  • Create,Save,Update,Delete,Find 中钩子方法
  • 支持 Preload、Joins 的预加载
  • 事务,嵌套事务,Save Point,Rollback To Saved Point
  • Context、预编译模式、DryRun 模式
  • 批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD
  • SQL 构建器,Upsert,数据库锁,Optimizer/Index/Comment Hint,命名参数,子查询
  • 复合主键,索引,约束
  • Auto Migration
  • 自定义 Logger
  • 灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…
  • 每个特性都经过了测试的重重考验
  • 开发者友好

GORM 官方支持的数据库类型有:MySQL, PostgreSQL, SQLite, SQL Server 和 TiDB

安装

这里使用MySQL数据库进行测试
安装依赖包

// 安装MySQL依赖
go get gorm.io/driver/mysql@v1.3.5
// 安装Gorm依赖
go get gorm.io/gorm@v1.25.4

简单入门

创建mysql数据库连接

import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main() {
  //连接本地数据库bd01,用户名:root,密码:123456
  dsn := "root:123456@tcp(127.0.0.1:3306)/db01?charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}
  • mysql.Open(dsn) 根据提供的连接信息打一个mysql连接器
  • gorm.Open() 在给定 dialector 的基础上开启一个 db session
  • gorm.Config{} 可选配置

声明一个模型struct,对应数据的一张表,User继承了gorm.Model,拥有gorm.Model的字段信息。

type User struct {
	gorm.Model
	Name    string
	Sex     int8
}
// 指定表名 t_user
func (User) TableName() string {
	return "t_user"
}

// gorm.Model 的定义,提供默认的字段和类型,GORM 约定使用 CreatedAt、UpdatedAt 追踪创建/更新时间。如果您定义了这种字段,GORM 在创建、更新时会自动填充 当前时间
type Model struct {
ID uint gorm:"primaryKey"
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt gorm:"index"
}

操作数据库,这里给出几个例子,更多操作方式见官网

  // 迁移 schema
  db.AutoMigrate(&User{})

  // Create
  db.Create(&User{Name: "张三", Sex: 1})

  // Read
  var user User
  db.First(&user, 1) // 根据整型主键查找
  db.First(&user, "name = ?", "张三") // 查找 code 字段值为 D42 的记录

  // Update
  db.Model(&user).Update("Name", "李四")
  // Update - 更新多个字段
  db.Model(&user).Updates(User{Name: "王五", Sex: 2}) // 仅更新非零值字段
  db.Model(&user).Updates(map[string]interface{}{"Name": '王五', "Sex": 2})

  // Delete - 删除 product
  db.Delete(&user, 1)

Web集成

新增配置struct

在项目原有基础上新增一个数据配置结构体,添加到全局配置 Config 中

type DbConf struct {
	Host                     string
	Port                     int
	Username                 string
	Password                 string
	Db                       string
	ParamStr                 string `json:",optional"`
	MaxOpenConns             int    `json:",default=10"`
	MaxIdleConns             int    `json:",default=5"`
	ConnMaxIdleTime          int    `json:",default=60"`
	ConnMaxLifetime          int    `json:",default=60"`
	SlowThresholdMillisecond int64  `json:",default=1000"`
}

type Config struct {
	rest.RestConf
	Redis redis.RedisConf `json:",optional"`
	Auth  struct {
		AccessSecret string
		AccessExpire int64
	}
	Db DbConf `json:",optional"`
}

yaml中配置数据库

Db:
  Host: localhost
  Port: 3306
  Username: root
  # 这里密码如果是纯数字需要加引号
  Password: "123456"
  # 数据库名
  Db: test01
  #连接参数字符串拼接形式
  ParamStr: charset=utf8mb4&parseTime=True&loc=Asia%2FShanghai
  #设置打开数据库连接的最大数量
  MaxOpenConns: 10
  #设置空闲连接池中连接的最大数量
  MaxIdleConns: 5
  #连接最大空闲时间 单位秒
  ConnMaxIdleTime: 60
  #设置连接可复用的最大时间 单位秒
  ConnMaxLifetime: 60

项目启动加载配置

这里使用的是go-zero的conf.MustLoad(configFile, &c)方法加载yaml配置,其他方式可自行根据情况进行配置读取,例如使用 gopkg.in/yaml.v2 进行读取。

conf.MustLoad(configFile, &c)

在这里插入图片描述
gopkg.in/yaml.v2 读取例子


func LoadAppConf(filePath string, out interface{}) error {
	file, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}
	err = yaml.Unmarshal(file, out)
	if err != nil {
		return err
	}
	if conf.Logging.PrintConf {
		fmt.Println("------------------------------------------", filePath, " Start------------------------------------------>")
		fmt.Println(string(file))
		fmt.Println()
	}

	return nil
}

初始化数据库连接

在项目上下文中初始化数据库连接信息,internal/svc/ctx.go 中的 initDb 方法会在服务启动时候调用,进行数据库的初始化,具体代码如下,调用细节可以参考:https://gitee.com/li_zheng/treasure-box 下对应的文件代码

func initDb() {
	dbConf := sCtx.Config.Db
	if len(dbConf.Host) == 0 {
		return
	}
	logx.Infof("Initializing db ...")
	//if len(dbConf.ParamStr) == 0 {
	//	dbConf.ParamStr = getParamStr(dbConf.ConnParams)
	//}
	dbUrl := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?%s",
		dbConf.Username,
		dbConf.Password,
		dbConf.Host,
		dbConf.Port,
		dbConf.Db,
		dbConf.ParamStr)
	logx.Infof("DSN: %s", dbUrl)
	dialector := mysql.New(mysql.Config{
		DSN:                       dbUrl, // data source name
		DefaultStringSize:         256,   // string 类型字段的默认长度
		DisableDatetimePrecision:  true,  // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
		DontSupportRenameIndex:    true,  // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
		DontSupportRenameColumn:   true,  // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
		SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
	})

	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)
		logger.Config{
			SlowThreshold:             time.Duration(dbConf.SlowThresholdMillisecond) * time.Millisecond, // 慢 SQL 阈值
			LogLevel:                  logger.Info,                                                       // 日志级别
			IgnoreRecordNotFoundError: true,                                                              // 忽略ErrRecordNotFound(记录未找到)错误
			Colorful:                  true,                                                              // 禁用彩色打印
		},
	)

	option := &gorm.Config{
		//禁用默认全局事务
		SkipDefaultTransaction: true,
		//开启预编译sql
		PrepareStmt: true,
		Logger:      newLogger,
	}
	db, err := gorm.Open(dialector, option)
	if err != nil {
		logx.Must(err)
	}
	sqlDb, err := db.DB()
	if err != nil {
		logx.Must(err)
	}
	sqlDb.SetMaxOpenConns(dbConf.MaxOpenConns)
	sqlDb.SetMaxIdleConns(dbConf.MaxIdleConns)
	sqlDb.SetConnMaxIdleTime(time.Second * time.Duration(dbConf.ConnMaxIdleTime))
	sqlDb.SetConnMaxLifetime(time.Second * time.Duration(dbConf.ConnMaxLifetime))
	sCtx.Db = db
	logx.Infof("%+v", sqlDb.Stats())
	logx.Infof("DB Initialized.")
}

项目中使用

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值