这里将总结出使用gorm中的方法
开始连接
这里我们将开始学习使用gorm连接数据库,这里我们要知道后面我们使用的方法都是通过连接获取的对象进行操作的。那么下面我们就开始创建这个连接。
当然最开始我们肯定是要导入gorm包的,这里我们就不再展示了
这里在连接的时候,我们这里肯定是要先书写连接dns
dsn := "用户名:密码@tcp(ip:3306)/数据库名称?charset=utf8mb4&parseTime=True&loc=Local"
写好了这个连接名过后,使用 gorm.Open()进行连接的创建
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
上面我们就创建好了这个连接对象,然后后面的操作我们将在这个基础上进行。
基础使用的设置
配置彩色打印与日志级别
在前面我们说到,我们可能会对sql敏感度会降低,这里我们将解决这个尴尬的问题,我们这里可以让执行的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(记录未找到)错误
Colorful: true, // 禁用彩色打印
},
)
//这里这个db就是生成的对象
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
这里我们就配置好了彩色打印。
这里我们设置的是全局的配置,也就是说,会打印出所有的语句。
设置表名
在开发的时候,我们知道在gorm中,我们添加表我们是先写好一个结构体,然后结构体的名称会影响最后生成表名的名称。这里我们有个需求也就是自定义表名的需求那么我们如何完成呢。这里我们将介绍两个办法。
通过方法进行修改
通过实现一个接口去实现对表名称的修改:
func(Language) TableName()string{
return "my_language"
}
在这里返回的值就是最后表的名称
通过配置完成名称前缀的添加
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
TablePrefix: "mwwx",
},
Logger: newLogger,
})
这里我们使用的是在生成连接对象的地方进行添加,我们在gorm.Open()中我们配置NamingStrategy: schema.NamingStrategy{}进行配置。这里我们添加的是表的前缀
需要注意的地方
这里我们需要注意的是。前面两个方法只能使用一个两个不能同时的使用,这里是需要我们注意的点。
基本的curd
创建表
在对数据进行操作之前,我们肯定是要先进行数据表的创建的,这里我们看一下我们如何使用gorm进行数据表的创建。
使用的方法是:AutoMigrate()
db.AutoMigrate(&表结构体{})
这里需要注意的是我们这里使用的是结构体的
添加数据
有了数据表过后那么我们就要开始添加数据。
添加单条数据
//下面我们将会演示一个特殊的操作
user := User{
Name: "lzz",
}
//这里我们需要注意的点,也就是这里我们在创建的时候使用的是地址
//然后我们这里是有返回值的
result := db.Create(&user)
//下面的步骤我们必须是有上面的操作过后才会有的操作。
fmt.Println(user.ID)
fmt.Println(result.Error)//错误
fmt.Println(result.RowsAffected)//返回更新的条数
在这里我们可以看到添加单条数据的方法,然后我们可以看到最后的有三行代码,从中我们可以学习到,创建完对象过后我们可以做的操作和可以得到的数据。
批量添加数据
在批量添加数据中我们有两种方式可以完成。
使用create
这里我们使用到的方式是create
var users = []User{
{Name: "lzz1"},{Name: "lzz2"},{Name: "lzz3"},
}
result := db.Create(&users)
这里我们可以清楚的看到,我们首先是创建了一个切片,然后我们使用切片去插入数据
使用CreateInBatches
这里我们使用的方法是使用CreateInBatches,为什么要使用这个方法呢,是因为上面的方法和这个方法的sql中我们就要看出差距,我们首先要知道的是,sql语句的长度是有限制的,但是上面的方法,在批量插入的时候,把所有的值都放到了一个sql里面,那么问题就来了这样的话当数据量很大的时候,由于sql是有限制的所有就会出错。这个时候我们就使用CreateInBatches这个方法,因为这个方法可以设定批量每一条sql的数量。
//这里可以设置提交几个数据,然后这里就是分批次进行创建
//那么我们为什么要用这个呢?是因为sql语句是有长度限制的,也就是数据量大的时候我们是没有办法
//进行传输的。这里进行限制的时候后面的数字代表的是一次创建创建几个数据。
db.CreateInBatches(users,2)
从上面我们就可以看出我们使用的方式。
查询
在使用gorm查询的时候,我们也有很多的点需要注意,在这里进行一个总结。
基本查询
在基本的查询中,我们使用的方法有first和find这个两个,对于这个两个方法,第一个查询的时候是根据主键进行排序的,返回第一条数据。然后find呢是返回的所有数据。
var product Product
db.First(&product, 1) // 根据整形主键查找
db.First(&product, "code = ?", "D42") // 查找 code 字段值为 D42 的记录
find方式:
//使用find会检索所有的对象。
var users []User
result := db.Find(&users)
fmt.Println("总共记录:",result.RowsAffected)
当然肯定是不只是这些方式的:
对于其他的方式我们可以直接查看官方的文档。在我前一篇博客中有书写。
在查询中需要使用的where
//在实际的开发中我们会加入很多的where语句的
db.Where("name = ?","lzz").First(&users)
//对于这里我们还可以这样去做查询,这样可以屏蔽很多的细节
db.Where(&User{Name: "lzz"}).First(&users)
fmt.Println(users.ID)
//在文档里面我们可以知道,我们还可以使用map,map和slice不同在于哪里?
//在于map不会屏蔽零值
/**
查询方式条件我们有三种方式:
1. string
2. struct
3. map
在这里面我们优先选择后两种。可读性更强
*/
需要注意的点
这里我们需要注意的是。我们使用的时候我们需要注意,因为我们使用的是地址,所以最后返回回来的数据,就在变量里面
在这里我们要是处理的时候我们没有查找到数据,是会有报错的
在这里我们使用最正规的的报错方式,这个方式可以准确的判断是不是没有找到数据
更新
更新这一板块也有很多常用的知识和需要注意的点
基础的更新
db.Model(&product).Update("Price", 200)
这里是我们更新product表中的pricei字段为200
上面就是我们最基本的更新操作。
更新的时候遇见零值问题
这里我们需要注意的是,在gorm更新操作的时候,默认是不更新零值字段的。但是我们在实际的开发中肯定是有相关需求的,那么我们如何来解决这个问题呢?
首先使用内置的函数sql.nullXXX
在gorm中我们是有相关的解决函数的,这里我们演示string类型字段零值的更新操作
db.Model(&product).Updates(Product{Price: 200, Code: sql.NullString{
String: "",
Valid: true,
}})
如果接收更新零值我们这里第二个参数一定要改成true这样我们的方法才会生效。
改变字段结构体的类型
这里我们将字段的string类型改成了*string类型,那么他是可以更新零值的。
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
//这里更新操作是会更新零值的
db.Model(&User{ID: 1}).Update("Name","")
批量更新
批量更新的时候我们使用的是updates这个方法,
db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})
需要注意的点
这里我们需要注意的是update会更新零值,但是updates不会更新零值。
删除
对于删除我们需要知道的点就是软删除和物理删除两个
在目前的市场上我们现在做到一般都是软删除,很少物理删除了,这里我们说一下gorm的软删除和物理删除。
在gorm中,我们需要进行软删除的换,我们需要在结构体里面嵌套一个,gorm.model结构体,主要的是DeletedAt gorm.DeletedAt字段,这个字段必须是gorm.DeletedAt这个类型的,这样我们删除的时候就是软删除了。
那么我们需要物理删除我们应该怎么做呢?
db.Unscoped().Delete(&NewUser{ID: 2})
}
使用这个方法我们就可以进行物理删除了。
结尾
最后我们这里总结的是一些基本的时候,和我们常用的curd使用的方法,当然总结的不是很到位,希望大家多多指教,后面我将会更新连表和钩子函数的总结。随后我也会把demo放在github上供大家查看。