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 details
dsn := "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 main
import (
"fmt"
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Product struct {
gorm.Model
Code string
Price uint
}
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(&Product{})
}
简单的增删查改
package main
import (
"fmt"
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Product struct {
gorm.Model
Code string
Price uint
}
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.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{})
//create
db.Create(&Product{Code: "D42", Price: 100})
//read
var product Product
db.First(&product, 1) //根据整形主键查找
// fmt.Println(product)
db.First(&product, "code=?", "D42") //查找code=D42的记录
//UPDATE
db.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)
//Delete
db.Delete(&product, 1)
}
通过NullString解决不能更新零值的问题
当updates函数传递的是结构体时,gorm只更新非零,在更新过程中可以通过传递仅包含个别字段的结构更新字段,就造成了不能直接通过设置各字段的默认值更新内容。解决仅更新非零值有两个解决方法:第一种指针形式,第二种sql.NulXXX
package main
import (
"database/sql"
"fmt"
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Product struct {
gorm.Model
Code sql.NullString
Price uint
}
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.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{})
//create
db.Create(&Product{Code: sql.NullString{"D42", true}, Price: 100})
//read
var product Product
db.First(&product, 1) //根据整形主键查找
// fmt.Println(product)
db.First(&product, "code=?", "D42") //查找code=D42的记录
//UPDATE
db.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)
//Delete
db.Delete(&product, 1)
}
表结构细节设计
package main
import (
"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 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.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 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{})
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 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 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 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{})
//通过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 []User
result := 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 main
import (
"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 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
Deleted gorm.DeletedAt
}
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(&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 []NewUser
result := db.Find(&users)
for _, user := range users {
fmt.Println(user.ID)
}
fmt.Println(result.RowsAffected)
fmt.Println(result.Error)
}
原文地址:https://blog.csdn.net/weixin_44575660/article/details/142718074
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!