当前位置: 首页 > news >正文

golang gorm

ORM

ORM(Object Relational Mapping对象关系映射),其主要作用是在编程中,把面向对象的概念跟数据库中表的概念对应起来。举例来说就是,我定义一个对象,那就对应着一张表,这个对象的实例,就对应着表中的一条记录。对于数据来说,最重要最常用的是表:表中有列, orm就是将一张表映射成一个类,表中的列映射成类中的一个类。java 、python,但是针对go语言而言,struct,就是列如何映射,是因为列可以映射成struct中的类型,int->int,但是有另一个问题? 就是数据库中的列具备很好的描述性,但是struct有tag。执行sql, 需要我们有足够的sql语句基础、需要我们懂得不同的数据的sql。
常见的orm:
gorm
facebook开发的ent
sqlx

orm的优缺点

优点:
1提高了开发效率。
2屏蔽sql细节。可以自动对实体Entity对象与数据库中的Table进行字段与属性的映射;不用直接SQL编码
3屏蔽各种数据库之间的差异

缺点:

1orm会牺牲程序的执行效率和会固定思维模式
2太过依赖orm会导致sql理解不够
3对于固定的orm依赖过重,导致切换到其他的orm代价高

如何正确看待orm和sql之间的关系

1sql为主,orm为辅
2orm主要目的是为了增加代码可维护性和开发效率

连接
import ("gorm.io/driver/mysql""gorm.io/gorm"
)func main() {// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for detailsdsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}
通过迁移生成表结构
package mainimport ("fmt""log""os""time""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger"
)type Product struct {gorm.ModelCode  stringPrice uint
}func main() {// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for detailsdsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"//日志配置//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sqlnewLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writerlogger.Config{SlowThreshold:             time.Second, // 慢速 SQL 阈值LogLevel:                  logger.Info, // 日志级别IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数Colorful:                  true,        // 禁用颜色},)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {fmt.Println(err)}//定义表结构//迁移 schema_ = db.AutoMigrate(&Product{})
}
简单的增删查改
package mainimport ("fmt""log""os""time""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger"
)type Product struct {gorm.ModelCode  stringPrice uint
}func main() {// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for detailsdsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"//日志配置//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sqlnewLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writerlogger.Config{SlowThreshold:             time.Second,   // 慢速 SQL 阈值LogLevel:                  logger.Silent, // 日志级别IgnoreRecordNotFoundError: true,          // 忽略记录器的 ErrRecordNotFound 错误ParameterizedQueries:      true,          // 不要在 SQL 日志中包含参数Colorful:                  true,          // 禁用颜色},)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {fmt.Println(err)}//定义表结构//迁移 schema_ = db.AutoMigrate(&Product{})//createdb.Create(&Product{Code: "D42", Price: 100})//readvar product Productdb.First(&product, 1) //根据整形主键查找// fmt.Println(product)db.First(&product, "code=?", "D42") //查找code=D42的记录//UPDATEdb.Model(&product).Update("price", 200)//update多个字短db.Model(&product).Updates(Product{Price: 2000, Code: "F42"}) //仅更新非零值字段db.Model(&product).Updates(map[string]interface{}{"price": 2000, "code": "DD42"})fmt.Println(product)//Deletedb.Delete(&product, 1)
}
通过NullString解决不能更新零值的问题

当updates函数传递的是结构体时,gorm只更新非零,在更新过程中可以通过传递仅包含个别字段的结构更新字段,就造成了不能直接通过设置各字段的默认值更新内容。解决仅更新非零值有两个解决方法:第一种指针形式,第二种sql.NulXXX

package mainimport ("database/sql""fmt""log""os""time""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger"
)type Product struct {gorm.ModelCode  sql.NullStringPrice uint
}func main() {// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for detailsdsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"//日志配置//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sqlnewLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writerlogger.Config{SlowThreshold:             time.Second,   // 慢速 SQL 阈值LogLevel:                  logger.Silent, // 日志级别IgnoreRecordNotFoundError: true,          // 忽略记录器的 ErrRecordNotFound 错误ParameterizedQueries:      true,          // 不要在 SQL 日志中包含参数Colorful:                  true,          // 禁用颜色},)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {fmt.Println(err)}//定义表结构//迁移 schema_ = db.AutoMigrate(&Product{})//createdb.Create(&Product{Code: sql.NullString{"D42", true}, Price: 100})//readvar product Productdb.First(&product, 1) //根据整形主键查找// fmt.Println(product)db.First(&product, "code=?", "D42") //查找code=D42的记录//UPDATEdb.Model(&product).Update("price", 200)//update多个字短db.Model(&product).Updates(Product{Price: 2000, Code: sql.NullString{"", true}}) //仅更新非零值字段// db.Model(&product).Updates(map[string]interface{}{"price": 2000, "code": "DD42"})fmt.Println(product)//Deletedb.Delete(&product, 1)
}
表结构细节设计
package mainimport ("fmt""log""os""time""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger"
)type User struct {UserID uint   `gorm:"primarykey"`Name   string `gorm:"column:user_name;type:varchar(50);index:idx_user_name;unique;default:'bobby'"`// Code   sql.NullString// Price  uint
}func main() {// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for detailsdsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"//日志配置//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sqlnewLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writerlogger.Config{SlowThreshold:             time.Second,   // 慢速 SQL 阈值LogLevel:                  logger.Silent, // 日志级别IgnoreRecordNotFoundError: true,          // 忽略记录器的 ErrRecordNotFound 错误ParameterizedQueries:      true,          // 不要在 SQL 日志中包含参数Colorful:                  true,          // 禁用颜色},)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {fmt.Println(err)}//定义表结构//迁移 schema_ = db.AutoMigrate(&User{})db.Create(&User{})
}
create
package mainimport ("database/sql""fmt""log""os""time""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger"
)type User struct {ID           uint           // Standard field for the primary keyName         string         // A regular string fieldEmail        *string        // A pointer to a string, allowing for null valuesAge          uint8          // An unsigned 8-bit integerBirthday     *time.Time     // A pointer to time.Time, can be nullMemberNumber sql.NullString // Uses sql.NullString to handle nullable stringsActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fieldsCreatedAt    time.Time      // Automatically managed by GORM for creation timeUpdatedAt    time.Time      // Automatically managed by GORM for update time
}func main() {// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for detailsdsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"//日志配置//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sqlnewLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writerlogger.Config{SlowThreshold:             time.Second, // 慢速 SQL 阈值LogLevel:                  logger.Info, // 日志级别IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数Colorful:                  true,        // 禁用颜色},)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {fmt.Println(err)}//定义表结构//迁移 schema_ = db.AutoMigrate(&User{})user := User{Name: "Bobby2",}result := db.Create(&user)fmt.Println(user.ID)fmt.Println(result.Error)fmt.Println(result.RowsAffected)//db.Model(&User{ID: 1}).Update("name", "")
}
批量插入
package mainimport ("database/sql""fmt""log""os""time""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger"
)type User struct {ID           uint           // Standard field for the primary keyName         string         // A regular string fieldEmail        *string        // A pointer to a string, allowing for null valuesAge          uint8          // An unsigned 8-bit integerBirthday     *time.Time     // A pointer to time.Time, can be nullMemberNumber sql.NullString // Uses sql.NullString to handle nullable stringsActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fieldsCreatedAt    time.Time      // Automatically managed by GORM for creation timeUpdatedAt    time.Time      // Automatically managed by GORM for update time
}func main() {// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for detailsdsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"//日志配置//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sqlnewLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writerlogger.Config{SlowThreshold:             time.Second, // 慢速 SQL 阈值LogLevel:                  logger.Info, // 日志级别IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数Colorful:                  true,        // 禁用颜色},)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {fmt.Println(err)}//定义表结构//迁移 schema_ = db.AutoMigrate(&User{})var users = []User{{Name: "jinzhu1"},{Name: "jinzhu2"},{Name: "jinzhu3"},}//单一的sql语句// db.Create(&users)//为什么不一次性提交所有的?//sql语句有长度限制,需要分批提交db.CreateInBatches(users, 2)//for简单插入for _, user := range users {fmt.Println(user.ID)}// batch insert from `[]map[string]interface{}{}`db.Model(&User{}).Create([]map[string]interface{}{{"Name": "jinzhu_1", "Age": 18},{"Name": "jinzhu_2", "Age": 20},})
}
select
package mainimport ("database/sql""fmt""log""os""time""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger"
)type User struct {ID           uint           // Standard field for the primary keyName         string         // A regular string fieldEmail        *string        // A pointer to a string, allowing for null valuesAge          uint8          // An unsigned 8-bit integerBirthday     *time.Time     // A pointer to time.Time, can be nullMemberNumber sql.NullString // Uses sql.NullString to handle nullable stringsActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fieldsCreatedAt    time.Time      // Automatically managed by GORM for creation timeUpdatedAt    time.Time      // Automatically managed by GORM for update time
}func main() {// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for detailsdsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"//日志配置//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sqlnewLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writerlogger.Config{SlowThreshold:             time.Second, // 慢速 SQL 阈值LogLevel:                  logger.Info, // 日志级别IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数Colorful:                  true,        // 禁用颜色},)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {fmt.Println(err)}//定义表结构//迁移 schema_ = db.AutoMigrate(&User{})//通过first查询单个数据(升序排序)// var user User// db.First(&user)// fmt.Println(user.ID)// 通过first查询单个数据(降序排序)// db.Last(&user)// fmt.Println(user)//通过主键查询// result := db.First(&user, 10)// if errors.Is(result.Error, gorm.ErrRecordNotFound) {// 	fmt.Println("未找到")// }// fmt.Println(user.ID)//通过主键查询// result := db.First(&user, "10")// if errors.Is(result.Error, gorm.ErrRecordNotFound) {// 	fmt.Println("未找到")// }// fmt.Println(user.ID)// //通过主键查询// result := db.First(&user, "abc")// if errors.Is(result.Error, gorm.ErrRecordNotFound) {// 	fmt.Println("未找到")// }// fmt.Println(user.ID)//通过主键查询// result := db.First(&user, []int{1, 3, 5, 13})// if errors.Is(result.Error, gorm.ErrRecordNotFound) {// 	fmt.Println("未找到")// }// fmt.Println(user.ID)//检索全部对象var users []Userresult := db.Find(&users)fmt.Println("总共影响了", result.RowsAffected)for _, user := range users {fmt.Println(user.ID)}
}
where条件查询
package main// import (
// 	"database/sql"
// 	"fmt"
// 	"log"
// 	"os"
// 	"time"// 	"gorm.io/driver/mysql"
// 	"gorm.io/gorm"
// 	"gorm.io/gorm/logger"
// )// type User struct {
// 	ID           uint           // Standard field for the primary key
// 	Name         string         // A regular string field
// 	Email        *string        // A pointer to a string, allowing for null values
// 	Age          uint8          // An unsigned 8-bit integer
// 	Birthday     *time.Time     // A pointer to time.Time, can be null
// 	MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
// 	ActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fields
// 	CreatedAt    time.Time      // Automatically managed by GORM for creation time
// 	UpdatedAt    time.Time      // Automatically managed by GORM for update time
// }// func main() {
// 	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
// 	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"// 	//日志配置
// 	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
// 	newLogger := logger.New(
// 		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
// 		logger.Config{
// 			SlowThreshold:             time.Second, // 慢速 SQL 阈值
// 			LogLevel:                  logger.Info, // 日志级别
// 			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
// 			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
// 			Colorful:                  true,        // 禁用颜色
// 		},
// 	)// 	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
// 		Logger: newLogger,
// 	})
// 	if err != nil {
// 		fmt.Println(err)
// 	}// 	//定义表结构
// 	//迁移 schema
// 	_ = db.AutoMigrate(&User{})// 	var user User
// 	var users []User
// 	// db.Where("name=?", "jinzhu1").Find(&user)
// 	db.Where(&User{Name: "jinzhu1"}).Find(&user)
// 	db.Where(&User{Name: "jinzhu1"}).Find(&users)
// 	fmt.Println(user)
// 	fmt.Println(users)
// 	//string(拼sql)更灵活 最后
// 	//struct屏蔽变量名和表的字段的对应关系 最优先
// 	//map不灵活,但是可以解决strct屏蔽零值的问题 优先// }
delete
package mainimport ("database/sql""fmt""log""os""time""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger"
)type NewUser struct {ID           uint           // Standard field for the primary keyName         string         // A regular string fieldEmail        *string        // A pointer to a string, allowing for null valuesAge          uint8          // An unsigned 8-bit integerBirthday     *time.Time     // A pointer to time.Time, can be nullMemberNumber sql.NullString // Uses sql.NullString to handle nullable stringsActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fieldsCreatedAt    time.Time      // Automatically managed by GORM for creation timeUpdatedAt    time.Time      // Automatically managed by GORM for update timeDeleted      gorm.DeletedAt
}func main() {// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for detailsdsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"//日志配置//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sqlnewLogger := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writerlogger.Config{SlowThreshold:             time.Second, // 慢速 SQL 阈值LogLevel:                  logger.Info, // 日志级别IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数Colorful:                  true,        // 禁用颜色},)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: newLogger,})if err != nil {fmt.Println(err)}//定义表结构//迁移 schema_ = db.AutoMigrate(&NewUser{})// var users = []NewUser{// 	{Name: "jinzhu1"},// 	{Name: "jinzhu2"},// 	{Name: "jinzhu3"},// }// db.Create(&users)// for _, user := range users {// 	fmt.Println(user.ID)// }//gorm软删除// db.Delete(&NewUser{}, 2)// var users []NewUser// result := db.Find(&users)// for _, user := range users {// 	fmt.Println(user.ID)// }// fmt.Println(result.RowsAffected)// fmt.Println(result.Error)//gorm硬删除db.Unscoped().Delete(&NewUser{}, 2)var users []NewUserresult := db.Find(&users)for _, user := range users {fmt.Println(user.ID)}fmt.Println(result.RowsAffected)fmt.Println(result.Error)
}

http://www.mrgr.cn/news/43570.html

相关文章:

  • 八大排序--01冒泡排序
  • 基于keras的停车场车位识别
  • GoogleNet原理与实战
  • 内存缓存和硬盘缓存
  • 如何实现事件流操作
  • Mysql数据库约束
  • 【信息系统项目管理师考题预测】整合管理
  • 如何在 SQL 中创建一个新的数据库?
  • 【Codeforces】CF 2019C
  • AtCoder Beginner Contest 374 E题 Sensor Optimization Dilemma 2(二分,贪心)
  • Qt教程(002):Qt项目创建于框架介绍
  • 保险丝基础知识
  • 【深度学习】矩阵操作万能函数 einsum-爱因斯坦求和
  • 如何使用CMD命令启动应用程序(二)
  • C0015.Clion中开发C++时,连接Mysql数据库方法
  • 【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,1-1
  • 《python语言程序设计》2018版第8章19题几何Rectangle2D类(下)-头疼的几何和数学
  • 传感器模块编程实践(三)舵机+超声波模块融合DIY智能垃圾桶模型
  • 常见的基础系统
  • 今天学的Word小技巧——批量设置图片格式,批量让题注居中