golang_gorm代码段

本文详细介绍了GORM库在Go语言中进行数据库CRUD操作,包括创建、读取、更新和删除,以及高级查询技巧如SQL原生和GORM方法的对比,关联查询,模糊搜索,分页查询,以及如何处理空值和事务管理。

u := User{
	Username:"codebaoku",
	Password:"123456",
	CreateTime:time.Now().Unix(),
}

db.Create(&u)
// 等价于 SQL 语句:INSERT INTO `users` (`username`,`password`,`createtime`) VALUES ('codebaoku','123456','1540824823')


u.ID           // 返回主键 ID,默认主键名为 ID,也可以通过 gorm 标签定义
u.Error        // 返回 error
u.RowsAffected // 返回插入记录的条数

 Scan取结果要传入指针的地址并在试用期前进行非空校验

Raw&Row&Rows&Scan

原生sql:

有结果要取用raw, 反之用Exec

sql = ""
args = make([]string, 0)
var res string


//单个结果使用Raw执行sql后用Scan取出结果
r1 := db.Raw(sql, args)
row.Scan(&res)


//单个结果使用Raw执行sql后使用Row再用Scan取出结果
r1 := db.Raw(sql, args)
row := r1.Row()
row.Scan(&res)


//单个结果使用Raw执行sql后使用Rows后须调用Next方法再用Scan取出结果
r1 := db.Raw(sql, args)
rows, err := r1.Rows()
rows.Next()
rows.Scan(&res)


//多个结果使用Raw执行sql后使用Rows后须,循环调用Next方法用Scan取出结果
r1 := db.Raw(sql, args)
rows, err := r1.Rows()
for rows.Next(){
    rows.Scan(&res)
}

gorm:

//单个结果使用row
row := db.Select("ziduan").Table("aaa").Where("conditation").Row()
row.Scan(&res)


//单个结果直接scan
db.Select("ziduan").Table("aaa").Where("condition").Scan(&res)


//多个结果使用gorm架构直接赋值给数组
res := make([]string, 0)
db.Select("ziduan").Table("aaa").Where("conditation").Find(&res)


//多个结果使用Raw执行sql后使用Rows后须,循环调用Next方法用Scan取出结果
rows, err := db.Select("ziduan").Table("aaa").Rows()
for rows.Next(){
    rows.Scan(&res)
}

First&Last&Take&Find&Pluck

food := Food{}  //用于存放结果的结构体
var foods []Food

// 查询一条记录,根据主键ID排序(正序),返回第一条记录。
// 等价于:SELECT * FROM `foods` ORDER BY `foods`.`id` ASC LIMIT 1    
db.First(&food)

// 查询一条记录, 根据主键ID排序(倒序),返回第一条记录。
// 等价于:SELECT * FROM `foods`  ORDER BY `foods`.`id` DESC LIMIT 1   
db.Last(&food)


// 等价于:SELECT * FROM `foods` LIMIT 1  
db.Take(&food)

// 查询多条记录,Find函数返回的是一个数组。
db.Find(&foods)


// 查询一列值。
var val []string
db.Model(&Food{}).Pluck("title", &titles)
// Pluck提取了title字段,保存到titles变量
// Model函数是为了绑定一个模型实例,可以从里面提取表名。

======================================================================================
// Save 


// 先查询一条记录, 保存在模型变量food
food := Food{}
db.Where("id = ?", 2).Take(&food)
// 等价于: SELECT * FROM `foods`  WHERE (id = '2') LIMIT 1

// 修改food模型的值
food.Price = 100

// 将传入结构体的主键作为条件进行筛选后更新所有字段
db.Save(&food)
// 等价于: UPDATE `foods` SET `title` = '可乐', `type` = '0',
// `price` = '100', `stock` = '26', `create_time` = '2018-11-06 11:12:04' 
// WHERE `foods`.`id` = '2'

===============================================
// Update


// 通过 food 模型的主键 id 的值作为 where 条件,更新 price 字段值。
db.Model(&food).Update("price", 25)
// 等价于: UPDATE `foods` SET `price` = '25' 
// WHERE `foods`.`id` = '2'


// 注意这里的 Model 参数
// 使用的是 Food{},新生成一个空白的模型变量
// 没有绑定任何记录。
// 因为 Food{} 的 id 为空,gorm库就不会以 id 作为条件
// where 语句就是空的
db.Model(&Food{}).Update("price", 25)
// 等价于: UPDATE `foods` SET `price` = '25'

// 根据自定义条件更新记录,而不是根据主键 id
db.Model(&Food{}).Where("create_time > ?", "2018-11-06 20:00:00").
   Update("price", 25)
// 等价于: UPDATE `foods` SET `price` = '25' 
// WHERE (create_time > '2018-11-06 20:00:00') 

===============================================
// Updates


// 通过结构体变量设置更新字段
updataFood := Food{
	Price:100,
	Title:"aa",
}
// 根据 food 模型更新数据库记录
// Updates 会忽略掉 updataFood 结构体变量的零值字段
// 所以生成的 sql 语句只有 price 和 title 字段。
db.Model(&food).Updates(&updataFood)
// 等价于: UPDATE `foods` SET `price` = '100',
// `title` = 'aa'  WHERE `foods`.`id` = '2'
// 可传入空的Food结构体,使用Where语句筛选需要更新的记录

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Updates 会忽略掉结构体变量的零值字段
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


// 使用 map 类型更新传入的包括零值的所有字段值
// 定义 map 类型,key 为字符串,value 为 interface{} 类型
// 方便保存任意值
data := make(map[string]interface{})
data["stock"] = 0 //零值字段
data["price"] = 35

db.Model(&Food{}).Where("id = ?", 2).Updates(data)
// 等价于: UPDATE `foods` SET `price` = '35', `stock` = '0'  WHERE (id = '2')

======================================================================================
// 使用gorm.Expr函数进行表达式形式的更新

db.Model(&food).Update("stock", gorm.Expr("stock + 1"))
// 等价于: UPDATE `foods` SET `stock` = stock + 1  WHERE `foods`.`id` = '2'

// 删除模型数据一般用于删除之前查询出来的模型变量绑定的记录。

 food := Food{}
// 先查询一条记录, 保存在模型变量 food
db.Where("id = ?", 2).Take(&food)
// 等价于: SELECT * FROM `foods`  WHERE (id = '2') LIMIT 1

// 删除 food 对应的记录,通过主键 Id 标识记录
db.Delete(&food)
// 等价于: DELETE from `foods` where id=2;


==========================================================================
// 根据 Where 条件删除数据
//db.Where(条件表达式).Delete(空模型变量指针)

// 必须传空结构体指针到Delete中指定表名
db.Where("type = ?", 5).Delete(&Food{})
// 等价于:DELETE from `foods` where (`type` = 5);

Group

(Group函数必须搭配Select函数一起使用)

// 统计每个商品分类下面有多少个商品
// 定一个Result结构体类型,用来保存查询结果
type Result struct {
    Type  int
    Total int
}

var results []Result
// 等价于: 
// SELECT type, count(*) as  total FROM `foods`
// GROUP BY type HAVING (total > 0)

db.Model(Food{}).Select("type, count(*) as  total").
Group("type").Having("total > 0").Scan(&results)

// scan类似Find都是用于执行查询语句,然后把查询结果赋值给结构体变量
// 区别在于scan不会从传递进来的结构体变量提取表名.
// 这里因为我们重新定义了一个结构体用于保存结果
// 但是这个结构体并没有绑定foods表,所以这里只能使用scan查询函数。

事务

// ==============================================================
// 自动事务处理
db.Transaction(func(tx *gorm.DB) error{
	// 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
	if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
		// 返回任何错误都会回滚事务
		return err
	}
	
	if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
		return err
	}
	
	// 返回 nil 提交事务
	return nil
})

// ==============================================================
// 手动事务处理

tx := db.Begin() //开启事务

// 操作1
if err := tx.Create(&food).Error; err != nil {
	tx.Rollback() // 失败则调用该函数进行回滚
	return
}

// 操作2
if err := tx.Delete(&food).Error; err != nil {
	tx.Rollback() // 失败则调用该函数进行回滚
	return
}

tx.Commit() //执行事务

Tips

结构体定义映射的表名和字段名

type test struct{
    TestId string `gorm:"column:id" json:"nativename"`
    Nnn    string `gorm:"column:n"`
    Mmm    string `gorm:"column:m"`
}

func (t test) TableName() string{
    retrun "tb_test"
}

空值NULL相关的判断和更新

// 判断
db.Select("id").Where("flag is null")

// 更新
sql := "update tb_name set flag = NULL WHERE id = ?"
db.Exec(sql, 2)

db.Table("tb_test").
   Where("id = ?",1).
   Updates(map[string]interface{}{"m":1, "n":nil})
//golang的nil映射为数据库的NULL

联查&模糊匹配&页码查询&取值

sql := "a.id = ?"
serchId = "xxxxxx"
serchKeyword = "aaa"
ss := "%"+serchKeyword+"%"
var c *int64

db := db.Debug().Select("a.id, b.name, c.xxx").
    Table("tb1 a").
    Joins("left join tb2 b").
    Joins("left join tb3 c").Where(sql, serchId).
    Where("a.ppp like ? or b.ppp like ?", ss, ss).
    Order("a.id desc").  //降序排列
    Offset( ( page - 1 ) * pagesize).Limit(pagesize)

db.Count(&c)
rows, err := db.Rows()

for rows.Next(){
    rows.Scan(...)
}

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值