这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战」
前言
经过前几篇文章的铺垫,在Go语言中实现结构体反射实现数据库操作已经开始得心应手起来了,且由于数据修改和之前的数据插入类似,数据删除也有不少共通之处,因此将两个操作合并讲解。
数据修改
很数据插入操作类似,我们需要实现将数据中值为空的数据对应的字段提取出来,先构建一个map对象存储,然后通过字符串拼接的方式构建需要的sql语句,因此在这部分,代码和之前完全一致:
t := reflect.TypeOf(model)
mp := make(map[string]string)
for i := 0; i < t.Elem().NumField(); i++ {
field := t.Elem().Field(i)
name := field.Name
value := reflect.ValueOf(model).Elem().FieldByName(name).String()
if value == "" {
continue
}
mp[name] = value
}
复制代码
和数据插入不同,我们在执行插入操作是,主键是由我们自己决定的,但是修改和删除操作,需要获取到主键,通过添加WHERE查询条件,才能定位数据,实现修改和删除。
当然,由于之前建表的时候我们已经将主键的信息存在Tags内了,因此我们只需要反射使用field.Tag.Get读取标签,遍历搜索主键名,然后再使用reflect.ValueOf,实现主键值的获取。
此部分代码实现如下:
// getPrimaryKey 获取结构体主键名和对应值
func getPrimaryKey(model interface{}) (name string, value string, err error) {
// 反射获取主键名和对应值
t := reflect.TypeOf(model)
for i := 0; i < t.Elem().NumField(); i++ {
field := t.Elem().Field(i)
constraint := field.Tag.Get("constraint")
if strings.Contains(constraint, "PRIMARY KEY") {
name = field.Tag.Get("json")
value = reflect.ValueOf(model).Elem().FieldByName(name).String()
}
}
if name != "" && value != "" {
return
}
err = errors.New("PRIMARY KEY NO FOUND")
return
}
复制代码
另外,数据修改和数据插入操作一大不同是sql语句结构的不同,因此,在字符串拼接实现上,存在较大差异。
数据修改操作,完整代码实现如下:
name, value, err := getPrimaryKey(model)
if err != nil {
return err
}
tableName := strings.Split(t.String(), ".")[1]
sql := "UPDATE " + tableName + " SET\n"
tmp := 0
for k, v := range mp {
sql += fmt.Sprintf("\t%s = '%s'", k, v)
tmp++
if tmp != len(mp) {
sql += ",\n"
}
}
复制代码
使用方法如下:
err := models.Update(&models.Role{
Id: "1",
Name: "Admin666",
Introduction: "管理员666",
})
fmt.Println(err)
复制代码
生成的sql语句:
UPDATE Role SET
Id = '1',
Name = 'Admin666',
Introduction = '管理员666'
WHERE Id = 1;
复制代码
数据删除
数据删除比较简单,一个删除语句如下:
DELETE FROM Role
WHERE id = 1;
复制代码
可以看到,除表名外,我们只需要主键和主键名,就可以实现删除了。
凑巧的是,这两参数,我们在实现上面数据修改的时候已经完成了,因此直接写出代码:
func Delete(model interface{}) error {
t := reflect.TypeOf(model)
tableName := strings.Split(t.String(), ".")[1]
sql := "DELETE FROM " + tableName
name, value, err := getPrimaryKey(model)
if err != nil {
return err
}
sql += fmt.Sprintf("\nWHERE %s = %s;", name, value)
logrus.Debugln(sql)
_, err = db.Exec(sql)
return err
}
复制代码
使用方式如下:
err := models.Delete(&models.Role{
Id: "1",
})
fmt.Println(err)
复制代码
生成的sql语句就是上面展示的那个。




近期评论