1 gorm简介
Github:github.com/go-gorm/gor…
中文文档:gorm.io/zh_CN/docs/
特性(摘自官网):
- 全功能 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…
- 每个特性都经过了测试的重重考验
- 开发者友好
2 为什么要引入ORM框架
2.1 概念
ORM一般指对象关系映射。 对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
2.2 引入orm之前的CRUD
var mysqlCon *sql.DB func InitMySQL(cnf *model.MySQLConfig) { var err error source := cnf.GetUserName() + ":" + cnf.PassWord + "@tcp(" + cnf.Host + ":" + cnf.GetPort() + ")/" + cnf.GetDBName() + "?charset=utf8" mysqlCon, err = sql.Open("mysql", source) if err != nil { panic("连接失败") } log.Info("MySQL Server is connected...") } func (dao LogMessageDaoImpl) SaveLogMessage(ctx context.Context, ms model.LogMessage) bool { tx, err := mysqlCon.Begin() stmt, err := tx.Prepare("INSERT INTO tb_log_message(id,create_time,time_stamp,log_user_id,log_user_role,topic_id,topic_name,operation,state,user_token,ip_address,os,browser) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)") if err != nil { fmt.Println("save err") } stmt.Exec(ms.Id, ms.CreateTime, ms.TimeStamp, ms.LogUserId, ms.LogUserRole, ms.TopicId, ms.TopicName, ms.Operation, ms.State, ms.UserToken, ms.IpAddress, ms.OS, ms.Browser) tx.Commit() return false } 复制代码
2.3 使用orm框架进行CRUD
func main() { // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情 dsn := "root:12345678@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic(err) } //ORM操作 GormCreate(db) } func GormCreate(db *gorm.DB) { //create student := Student{Name: "sss", Age: 10, Address: "Guangzhou"} res := db.Create(&student) fmt.Println(student.Id) fmt.Println(res.Error) } 复制代码
2.4 原因
- 操作对象,就相当于直接操作数据库表,不需要占位符
- 代码量少不易出错
3 gorm简单使用
package main import ( "fmt" "gorm.io/driver/mysql" "gorm.io/gorm" "time" ) type Student struct { Id int Name string Age int Address string } // TableName 实现接口就可以更改表名 func (stu Student) TableName() string { return "student" } func main() { // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情 dsn := "root:12345678@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic(err) } //ORM操作 //GormCreate(db) GormUpdate(db) } func GormCreate(db *gorm.DB) { //create student := Student{Name: "sss", Age: 10, Address: "Guangzhou"} res := db.Create(&student) fmt.Println(student.Id) fmt.Println(res.Error) } func GormRead(db *gorm.DB) { //Select var stu Student db.First(&stu, 1) fmt.Println(stu) } func GormUpdate(db *gorm.DB) { stu := Student{Id: 1} // Update - 将 product 的 price 更新为 200 db.Model(&stu).Update("age", 200) // Update - 更新多个字段 db.Model(&stu).Updates(Student{Name: "ZhangSan", Address: "F42"}) // 仅更新非零值字段 //db.Model(&stu).Updates(map[string]interface{}{"Price": 200, "Code": "F42"}) } func GormDelete(db *gorm.DB) { stu := Student{} // Delete - 删除 product db.Delete(&stu, 1) }