GROM学习-CRUD | 青训营

63 阅读13分钟

ORM简介

对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库(如mysql数据库)存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中

查询

func main() {
	db = conn.Conn()
	db.Set("gorm:table_options","ENGINE=InnoDB").AutoMigrate(&model.AdminUser{})

	defer db.Close()
	// 1.查询单条记录
	// getOne()
	// 2.查询多条记录
	// getAll()
	// 3.简单的where条件查询
	// simpleWhereQuery()
	// 4.高级where条件查询
	// advancedWhereQuery()
	// 5.Not查询条件
	// notWhereQuery()
	// 6.单纯使用Find()函数进行的条件查询
	// findWhereQuery()
	// 7.Or查询条件
	// orWhereQuery()
	// 8.FirstOrInit()和FirstOrCreate()函数使用,以及这两个函数配合Assign()和Attrs()函数使用
	// firstOrInitQuery()
	// 9.Select()函数使用
	// selectQuery()
	// 10.Order()、Limit()、Offset()函数使用
	// pageQuery()
	// 11.获取记录总数
	// countQuery()
	// 12.使用指定的数据表来进行查询
	// tableQuery()
	// 13.Scan()函数使用
	// scanQuery()
	// 14.Pluck()函数使用
	// pluckQuery()
	// 15.Scopes()函数使用
	scopesQuery()

	fmt.Println("success")
}

查询单条记录

注意,不管是带条件或是没有带条件的查询,都需要配合Find()、First()、Last()这些函数来实现,这三个函数的应用区别:

①、查询单条记录多用First()或是Last()函数

②、查询多条记录,就需要配合Find()函数

func getOne()  {
	// 声明一个对象
	var adminuser model.AdminUser
	// 1.执行First(),就是执行SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL ORDER BY `jh_admin_users`.`id` ASC LIMIT 1
	db.First(&adminuser)
	fmt.Println("First",adminuser)
	//对日期进行格式化处理
	fmt.Println(adminuser.CreatedAt.Format(TIMEFORMATTER))
	// 2.执行Last(),就是执行SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL ORDER BY `jh_admin_users`.`id` DESC LIMIT 1
	var adminuser2 model.AdminUser
	db.Last(&adminuser2)
	fmt.Println("Last",adminuser2)
	// 3.查询指定ID的记录,就是执行SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`id` = 2)) ORDER BY `jh_admin_users`.`id` ASC LIMIT 1
	var adminuser3 model.AdminUser
	db.First(&adminuser3,2)
	fmt.Println("First ID 2",adminuser3)
	// 4.查询指定ID的记录,就是执行SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`id` = 2)) ORDER BY `jh_admin_users`.`id` DESC LIMIT 1
	var adminuser4 model.AdminUser
	db.Last(&adminuser4,2)
	fmt.Println("First ID 2",adminuser4)
	// 当使用First()和Last()函数进行查询的时候,传递第二个参数,其实这两个函数都可以随意使用。因为所达到的效果是一样的。
}

查询所有记录

func getAll()  {
	var adminusers []model.AdminUser
	// 直接调用Find()方法,就是执行SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL  
	db.Find(&adminusers)
	fmt.Println(adminusers)
}

最简单的带条件查询

下面的示例都是只提供了一个参数,如果又多个参数,就写多个参数就好了

func simpleWhereQuery()  {
	// 获取单个记录
	var adminuser model.AdminUser
	// SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((username = 'lisi')) ORDER BY `jh_admin_users`.`id` ASC LIMIT 1
	db.Where("username = ?","lisi").First(&adminuser)
	fmt.Println(adminuser)
	// 获取多个记录
	var adminusers []model.AdminUser
	// SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((status = 1))
	db.Where("status = ?",1).Find(&adminusers)
	fmt.Println(adminusers)
}

使用结构体、map数据结构、[]int(主键id)方式进行查询

需要注意一下:当使用结构体的时候,自然是用结构体的属性来设置属性值。但是当使用map数据结构的时候,那就需要用到定义在数据表的表字段来进行设置属性值了。

func advancedWhereQuery()  {
	// 1.使用结构体来构建的where查询条件
	var adminusers []model.AdminUser
	whereStruct := model.AdminUser{
		Status:1,
		LoginFails:2,
	}
	// SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`status` = 1) AND (`jh_admin_users`.`login_fails` = 2))
	db.Where(whereStruct).Find(&adminusers)
	fmt.Println(adminusers)

	// 2.使用map方式构建的where查询条件。下面map结构体中定义的key都是数据表对应的字段名
	var adminusers2 []model.AdminUser
	whereMap := map[string]interface{}{
		"status":1,
		"login_fails":2,
	}
	// SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`status` = 1) AND (`jh_admin_users`.`login_fails` = 2))
	db.Where(whereMap).Find(&adminusers2)
	fmt.Println(adminusers2)

	// 3.使用主键ID来构建where查询条件
	var adminusers3 []model.AdminUser
	wherePrimarykey := []int{1,3,5}
	// SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`id` IN (1,3,5)))
	db.Where(wherePrimarykey).Find(&adminusers3)
	fmt.Println(adminusers3)
}

Not条件查询

在Not()函数中,依然可以接受普通字符串、结构体、map数据结构、[]int(主键id)这几种方式

func notWhereQuery()  {

  // 1.使用普通字符串进行的查询。

  var adminusers []model.AdminUser

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND (NOT (login_fails > 1))

  db.Not("login_fails > ?",1).Find(&adminusers)

  fmt.Println(adminusers)



  // 2.使用结构体进行的查询。

  var adminusers2 []model.AdminUser

  whereStruct := model.AdminUser{

​    Status:1,

​    LoginFails:2,

  }

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`status` <> 1) AND (`jh_admin_users`.`login_fails` <> 2))

  db.Not(whereStruct).Find(&adminusers2)

  fmt.Println(adminusers2)



  // 3.使用map结构

  var adminusers3 []model.AdminUser

  whereMap := map[string]interface{}{

​    "status":1,

​    "login_fails":2,

  }

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`status` <> 1) AND (`jh_admin_users`.`login_fails` <> 2))

  db.Not(whereMap).Find(&adminusers2)

  fmt.Println(adminusers3)



  // 4.使用主键ID来构建where查询条件

  var adminusers4 []model.AdminUser

  wherePrimarykey := []int{1,3,5}

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`id` NOT IN (1,3,5)))

  db.Not(wherePrimarykey).Find(&adminusers4)

  fmt.Println(adminusers4)

}


不依赖于Where()或是Not()方法,而是直接使用Find()函数的第二个参数来进行多类型条件查询

func findWhereQuery()  {

  // 1.使用普通字符串进行的查询。

  var adminusers []model.AdminUser

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((login_fails > 1))

  db.Find(&adminusers,"login_fails > ?",1)

  fmt.Println(adminusers)



  // 2.使用结构体进行的查询。

  var adminusers2 []model.AdminUser

  whereStruct := model.AdminUser{

​    Status:1,

​    LoginFails:2,

  }

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`status` = 1) AND (`jh_admin_users`.`login_fails` = 2))

  db.Find(&adminusers2,whereStruct)

  fmt.Println(adminusers2)



  // 3.使用map结构

  var adminusers3 []model.AdminUser

  whereMap := map[string]interface{}{

​    "status":1,

​    "login_fails":2,

  }

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`status` = 1) AND (`jh_admin_users`.`login_fails` = 2))

  db.Find(&adminusers2,whereMap)

  fmt.Println(adminusers3)



  // 4.使用主键ID来构建where查询条件

  var adminusers4 []model.AdminUser

  wherePrimarykey := []int{1,3,5}

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`id` IN (1,3,5)))

  db.Find(&adminusers4,wherePrimarykey)

  fmt.Println(adminusers4)



  // 5.查询单个记录

  var adminuser model.AdminUser

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`id` = 2))

  db.Find(&adminuser,2)

  fmt.Println(adminuser)

}

Or条件查询

使用Or()函数进行查询,在该函数中依然可以接受普通字符串、结构体、map数据结构、[]int(主键id)这几种方式

从下面的的这个用法示例中,我们可以发现Where()、Or()、Not()这些函数是可以配合使用的,使用查询链的方式来进行组合。



func orWhereQuery()  {

  // 1.使用普通字符串进行的查询。

  var adminusers []model.AdminUser

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((status = 1) OR (login_fails > 1))

  db.Where("status = ?",1).Or("login_fails > ?",1).Find(&adminusers)

  fmt.Println(adminusers)



  // 2.使用结构体进行的查询。

  var adminusers2 []model.AdminUser

  whereStruct := model.AdminUser{

​    LoginFails:2,

  }

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((status = 1) OR (`jh_admin_users`.`login_fails` = 2))

  db.Where("status = ?",1).Or(whereStruct).Find(&adminusers2)

  fmt.Println(adminusers2)



  // 3.使用map结构

  var adminusers3 []model.AdminUser

  whereMap := map[string]interface{}{

​    "login_fails":2,

  }

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((status = 1) OR (`jh_admin_users`.`login_fails` = 2))

  db.Where("status = ?",1).Or(whereMap).Find(&adminusers2)

  fmt.Println(adminusers3)



  // 4.使用主键ID来构建where查询条件

  var adminusers4 []model.AdminUser

  wherePrimarykey := []int{1,3,5}

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((status = 1) OR (`jh_admin_users`.`id` IN (1,3,5)))

  db.Where("status = ?",1).Or(wherePrimarykey).Find(&adminusers4)

  fmt.Println(adminusers4)

}


FirstOrInit()和FirstOrCreate()函数。这两个函数所能接收的参数只能是struct或是map

FirstOrInit():获取第一个匹配的记录,或者使用给定的条件初始化一个新的记录。如果查询到记录,就会把查询的结果映射到对应的变量上面;如果没有查询到结果,那只会把查询的结果字段映射到对应的变量上面

FirstOrCreate():获取第一个匹配的记录。查询到记录,那和FirstOrInit()做的功能一致。如果没有查询到记录,则会先插入一条记录,然后查询当前被插入的记录信息,然后把该记录信息映射到相应的变量上面。

所以,当使用FirstOrCreate()这个函数来获取一条不存在的记录的时候,是需要执行三条SQL的:①、执行查询。②、执行插入。③、在执行查询(最后根据主键ID来查询)

func firstOrInitQuery()  {

  // 1.用法一:使用结构体方式

  var adminuser model.AdminUser

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`username` = 'guolin')) ORDER BY `jh_admin_users`.`id` ASC LIMIT 1

  db.FirstOrInit(&adminuser,model.AdminUser{Username:"guolin"})

  fmt.Println(adminuser)



  // 2.用法二:使用map方式

  var adminuser2 model.AdminUser

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`username` = 'guolin')) ORDER BY `jh_admin_users`.`id` ASC LIMIT 1

  // 下面的语句用到了Assign()函数,这个会不管是否查询到结果,都会将adminuser2对象的Status属性值映射为Assign()函数里面设定的值

  db.Assign(model.AdminUser{Status:10}).FirstOrInit(&adminuser2,map[string]interface{}{"username":"guolin"})

  fmt.Println(adminuser2)

  // ---------------------FirstOrCreate()使用---------------------------

  // 1.用法一:使用结构体方式

  var adminuser3 model.AdminUser

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`username` = 'guolin')) ORDER BY `jh_admin_users`.`id` ASC LIMIT 1

  db.FirstOrCreate(&adminuser3,model.AdminUser{Username:"guolin"})

  fmt.Println(adminuser3)



  // 2.用法二:使用map方式

  var adminuser4 model.AdminUser

  // SQL查询语句:

  // SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`username` = 'guolin')) ORDER BY `jh_admin_users`.`id` ASC LIMIT 1

  // INSERT  INTO `jh_admin_users` (`created_at`,`updated_at`,`deleted_at`,`uuid`,`username`,`status`,`login_fails`) VALUES ('2019-08-27 10:13:06','2019-08-27 10:13:06',NULL,'b3139e4c-5816-405e-a5a3-2e62de6f4684','zhengzexi',10,20)

  // SELECT `age` FROM `jh_admin_users`  WHERE (id = 8)

  // 下面这个语句用到了Attrs()函数,就是当使用FirstOrCreate()函数进行查询的时候,如果没有发现该记录,在新插入的记录的时候,有些字段的值会设置为Attrs()函数设定的值。

  db.Attrs(model.AdminUser{Status:10,LoginFails:20}).FirstOrCreate(&adminuser4,map[string]interface{}{"username":"zhengzexi"})

  fmt.Println(adminuser4)



  // 2.用法二:使用map方式

  var adminuser5 model.AdminUser

  // 下面这个语句同时用到了Attrs()和Assign()函数。其实最终生效的还是Assign()函数定义的值。这就说明,Assign()函数优先级高于Attrs()函数。

  db.Attrs(model.AdminUser{Status:10,LoginFails:20}).Assign(model.AdminUser{Status:5,LoginFails:5}).FirstOrCreate(&adminuser5,map[string]interface{}{"username":"liudekai"})

  fmt.Println(adminuser5)

}

查询指定字段值.

Select()函数多接受字符串或是字符串切片格式数据



func selectQuery()  {

  var adminuser model.AdminUser

  // SQL语句:SELECT username,uuid,status,age FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((username = 'lisi')) ORDER BY `jh_admin_users`.`id` ASC LIMIT 1

  db.Select("username,uuid,status,age").Where("username = ?","lisi").First(&adminuser)

  //或是下面这种方式:

  //db.Select([]string{"username","uuid","status","age"}).Where("username = ?","lisi").First(&adminuser)

  fmt.Println(adminuser)

}

Order()、Limit()、Offset()函数使用

如果在Order()函数中只是说明了字段,并没有指定何种排序(ASC|DESC),那默认就是采用的是ASC方式排序

func pageQuery()  {

  var adminusers []model.AdminUser

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((status =1)) ORDER BY `status`,id desc LIMIT 10 OFFSET 0

  db.Where("status =?",1).Order("status").Order("id desc").Limit(10).Offset(0).Find(&adminusers)

  fmt.Println(adminusers)

}

获取记录总数。使用Count()函数

func countQuery()  {

  var count int

  // SQL查询语句:SELECT count(*) FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL

  db.Model(model.AdminUser{}).Count(&count)

  fmt.Println(count)

}

指定要查询的数据表。使用Table()函数

需要注意的是,Table()函数中必须要写完整的表名称,当然就包含了表前缀(如果有的话)和表后缀(如果有的话)

 

func tableQuery()  {

  var adminuser model.AdminUser

  // SQL查询语句:SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`id` = 1))

  db.Table("jh_admin_users").Find(&adminuser,1)

  fmt.Println(adminuser)

}

Scan()函数的使用

将查询的结果扫描到另外一个结构体中。下面定义了一个简单的SimpleAdminUser结构体,这个结构体只是包含了model.AdminUser这个结构体的部分字段。



type SimpleAdminUser struct {

  ID int

  Username string

  Age int

  Uuid string

  CreatedAt time.Time

  UpdatedAt time.Time

}



func scanQuery()  {

  var simpleAdminUser []SimpleAdminUser

  // SQL查询语句:SELECT id,username,age,uuid,created_at,updated_at FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((id > 3))

  db.Model(&model.AdminUser{}).Select("id,username,age,uuid,created_at,updated_at").Where("id > ?",3).Scan(&simpleAdminUser)

  fmt.Println(simpleAdminUser)

}

查询单列字段信息



func pluckQuery()  {

  var status []int

  db.Model(model.AdminUser{}).Where("id > ?",2).Pluck("status",&status)

  fmt.Println(status)

}

Scopes()函数使用

简单的说,就是在Scopes()中根据实际需要组合多种查询条件。而这些查询条件都会事先预定好。但是这种条件限定的比较死板(无法接受更多额外业务相关参数),所以个人觉得这个实际应用场景不会太大

func scopesQuery()  {

  var adminusers []model.AdminUser

  // 最后的SQL查询语句: SELECT * FROM `jh_admin_users`  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((status = 1) AND (login_fails > 5) AND (age > 25))

  db.Scopes(statusContion,loginFailsContion,ageContion).Find(&adminusers)

  fmt.Println(adminusers)

}

func statusContion(db *gorm.DB) *gorm.DB {

  return db.Where("status = ?",1)

}

func loginFailsContion(db *gorm.DB) *gorm.DB{

  return db.Where("login_fails > ?",5)

}

func ageContion(db *gorm.DB) *gorm.DB{

  return db.Where("age > ?",25)

}

/**

  TODO:Group()、Having()的使用

 */

func groupHavingQuery()  {



}



/**

  TODO:Join()使用

 */



func joinQuery()  {



}



/**

  TODO:Preload()使用

 */

func preloadQuery()  {



}

删除

func main() {

  db = conn.Conn()

  db.Set("gorm:table_options","ENGINE=InnoDB").AutoMigrate(&model.AdminUser{})



  defer db.Close()

  // 1.删除单条记录

  // singleDelete()

  // 2.批量删除记录

   batchDelete()

  // 3.物理删除记录(这个不管当前被删除的记录是否被软删除,都会被直接删掉)

  //physicalDelete()



}

单一删除



func singleDelete()  {

  // 1.根据查询的记录来删除

  var adminuser model.AdminUser

  //db.Where("id=?",1).Find(&adminuser)

  // 执行的SQL语句:UPDATE `jh_admin_users` SET `deleted_at`='2019-08-27 15:58:49'  WHERE `jh_admin_users`.`deleted_at` IS NULL AND `jh_admin_users`.`id` = 1

  //db.Delete(&adminuser)



  // 2.根据查询条件来进行删除

  // 上面的删除一条记录执行了两次查询操作,使用这种方式,只需要执行一次就好了。

  // 执行的SQL语句:UPDATE `jh_admin_users` SET `deleted_at`='2019-08-27 16:01:29'  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((`jh_admin_users`.`username` = 'sipotian'))

  //db.Delete(&adminuser,model.AdminUser{Username:"sipotian"})



  // 3.根据主键ID来进行删除

  // 如果是依据主键来进行删除,Delete()的第二个参数还可以直接写主键ID

  db.Delete(&adminuser,3)

}

批量删除



func batchDelete()  {

  // 删除status值为0的记录

  // 执行SQL:UPDATE `jh_admin_users` SET `deleted_at`='2019-08-27 16:07:00'  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((status = 0))

  db.Where("status = ?",0).Delete(model.AdminUser{})

  fmt.Println(db.RowsAffected)

}


物理删除

需要使用Unscoped()方法

func physicalDelete()  {

  // 永久的删除记录

  // 执行的SQL语句:DELETE FROM `jh_admin_users`  WHERE (`jh_admin_users`.`id` = 3)

  db.Unscoped().Delete(model.AdminUser{},3)

} 

修改

func main() {

  db = conn.Conn()

  db.Set("gorm:table_options","ENGINE=InnoDB").AutoMigrate(&model.AdminUser{})



  defer db.Close()



  // 1.更新所有字段值

  // updateAllFiled()

  // 2.只是更新设定的字段

  // updateModifyFiled()

  // 3.更新特定的字段或屏蔽某些字段

  // updateSpecifiedField()

  // 4.批量更新操作

  // batchUpdate()

  // 5.gorm.Expr()使用

  exprUpdate()

}

Save()方法。更新所有字段。这个操作在实际应用中应该会很少

下面的操作会执行下面两条语句:

SELECT * FROM jh_admin_users WHERE jh_admin_users.deleted_at IS NULL AND ((jh_admin_users.id = 1)) ORDER BY jh_admin_users.id ASC LIMIT 1

UPDATE jh_admin_users SET created_at = '2019-08-26 07:41:46', updated_at = '2019-08-26 07:41:46', deleted_at = NULL, uuid = '5964f734-a5b7-42c8-998c-09166bc84a64', username = 'chendalei', age = 35, status = 0, login_fails = 0 WHERE jh_admin_users.deleted_at IS NULL AND jh_admin_users.id = 1

func updateAllFiled()  {

  var adminuser model.AdminUser

  db.First(&adminuser,1)

  adminuser.Username = "chendalei"

  adminuser.Age = 35

  db.Save(adminuser)

}


Update()和Updates()方法

Update():只能更新单个字段值

Updates():这个可以更新多个字段值

需要注意的是,还有两个方法UpdateColumn()和UpdateColumns()方法,这两个方法和Update()和Updates()方法类似,都是用来更新字段的。

但是不同的是,Update()和Updates()方法会触发模型的BeforeUpdate, AfterUpdate方法,所以,在进行更新的时候,会自动把模型的updated_at字段值进行更新。

如果不想这样的话,就使用UpdateColumn()和UpdateColumns()方法这两个方法

func updateModifyFiled()  {

  var adminuser model.AdminUser

  db.First(&adminuser,1)

  // 1.下面是修改单个字段值

  // 执行的SQL语句:UPDATE `jh_admin_users` SET `updated_at` = '2019-08-27 11:33:09', `username` = 'chengerlei'  WHERE `jh_admin_users`.`deleted_at` IS NULL AND `jh_admin_users`.`id` = 1

  //db.Model(&adminuser).Update("username","chengerlei")



  // 2.更新多个字段,这就需要用到结构体或是map的数据结构了

  var adminuser2 model.AdminUser

  db.First(&adminuser2,2)

  // 执行的SQL语句:UPDATE `jh_admin_users` SET `login_fails` = 10, `status` = 2, `updated_at` = '2019-08-27 11:38:28', `username` = 'sipotian'  WHERE `jh_admin_users`.`deleted_at` IS NULL AND `jh_admin_users`.`id` = 2

  db.Model(&adminuser2).Updates(map[string]interface{}{"username":"sipotian","status":2,"login_fails":10})



  //结构体的使用就不做例子,上面的更新操作和下面的这个是一样的

  //db.Model(&adminuser2).Updates(model.AdminUser{Username:"sipotian",Status:2,LoginFails:10})

}

配合使用Select()和Omit()函数来实现更新或不更新某些字段.

当使用了Omit()函数后,即便在Updates()里面指定需要更新的字段,但是也会排除Omit()指定的字段值。

func updateSpecifiedField()  {

  var adminuser3 model.AdminUser

  db.First(&adminuser3,3)

  // 执行的SQL语句:UPDATE `jh_admin_users` SET `status` = 2, `updated_at` = '2019-08-27 11:47:15'  WHERE `jh_admin_users`.`deleted_at` IS NULL AND `jh_admin_users`.`id` = 3

  db.Model(&adminuser3).Omit("username","login_fails").Updates(map[string]interface{}{"username":"sipotian","status":2,"login_fails":10})

}

批量更新操作.

在批量更新时,Callbacks机制不会运行

func batchUpdate()  {

  // 执行的SQL语句:UPDATE `jh_admin_users` SET `login_fails` = 10, `status` = 1, `updated_at` = '2019-08-27 11:54:32'  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((id > 5))

  db.Model(&model.AdminUser{}).Where("id > ?",5).Updates(map[string]interface{}{"status":1,"login_fails":10})

}


gorm.Expr()使用

func exprUpdate()  {

  // 执行的SQL语句: UPDATE `jh_admin_users` SET `login_fails` = login_fails + 1, `updated_at` = '2019-08-27 14:00:44'  WHERE `jh_admin_users`.`deleted_at` IS NULL AND ((id=1))

  db.Model(&model.AdminUser{}).Where("id=?",1).Update("login_fails",gorm.Expr("login_fails + ?",1))

}

新增

func main() {

  mysqlSource := "root:jianghua@tcp(127.0.0.1:3306)/godb?charset=utf8&parseTime=true&loc=Local" //parseTime=true&loc=America%2FChicago

  db,err := gorm.Open("mysql",mysqlSource)

  if err != nil{

​    log.Print(err.Error())

  }

  gorm.DefaultTableNameHandler = DefaultTableNameSet

  db.Set("gorm:table_options","ENGINE=InnoDB").AutoMigrate(&AdminUser{})



  defer db.Close()

  //插入数据

  //insert(db)

  //获取数据

  var adminuser AdminUser

  db.First(&adminuser)

  fmt.Println(adminuser)



  var article Article

  db.Find(&article)

  fmt.Println(article)



  fmt.Println(time.Now().Format("2006-01-02 15:04:05"))

}
func insert(db *gorm.DB)  {

  user1 := AdminUser{Username:"sunli",Status:1,LoginFails:10}

  //user2 := AdminUser{Username:"lisi",Age:20}

  //user3 := AdminUser{Username:"wangmaz",Age:20}

  // 使用Create()函数,返回DB对象。函数需要传递引用地址。

  db.Create(&user1)

  //fmt.Println(db.RowsAffected,user1.ID)

  // 需要先创建模型的对象,在插入数据后通过NewRecord返回值判断是否插入成功,如果成功则返回false

  boolV := db.NewRecord(&user1)

  fmt.Println(boolV)

  if !boolV {

​    fmt.Println("success")

  }else{

​    fmt.Println("fail")

  }

}
type Article struct {

  ID int

  Title string

  Author string

  Status int

  Views int

}
type AdminUser struct {

  gorm.Model

  Uuid string

  Username string

  Age int `gorm:"default:'25'"`  // 这里设置,会将表结构的该字段值设置为25,后面在进行插入数据时候,不指定该字段值,就会用默认值

  Status int

  LoginFails int

}
//如果你想在BeforeCreate hook 中修改字段的值,可以使用scope.SetColumn

func (adminuser AdminUser) BeforeCreate(scope *gorm.Scope) error {

  uuidV := uuid.NewV4().String()

  fmt.Println(uuidV)

  if err := scope.SetColumn("uuid",uuidV);err != nil{

​    log.Println(err.Error())

  }

  return nil

}


func DefaultTableNameSet (db *gorm.DB, defaultTableName string) string {

  return "jh_"+defaultTableName

}