使用grom操作数据库

grom官方网站

https://gorm.io

安装grom和mysql驱动

go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

测试链接

import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main() {
  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{})
  if err != nil {
		fmt.Printf("err: %v\n", err)
	}
	fmt.Printf("db: %v\n", db)
}

输出结果表示运行成功

db: &{0xc000116510 <nil> 0 0xc0001c6380 1}

GORM模型定义

GORM 定义一个 gorm.Model 结构体,其包括字段 ID、CreatedAt、UpdatedAt、DeletedAt

// gorm.Model 的定义
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}

创建模型,根据模型生成数据库表

type User struct {
	gorm.Model   //内嵌gorm.Model
	Name         string
	Age          sql.NullInt64 //零值类型
	Birthday     *time.Time
	Email        string  `gorm:"type:varchar(100);unique_index"`
	Role         string  `gorm:"size:255"`        //设置字段大小为255
	MemberNumber *string `gorm:"unique;not null"` //设置会员号,唯一并且不为空
	Num          int     `gorm:"AUTO_INCREMENT"`  //设置num为自增类型
	Address      string  `gorm:"index:addr"`      //给address字段创建名为addr的索引
	IgnoreMe     int     `gorm:"-"`               //忽略本字段
}

func main() {
	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{})
	if err != nil {
		fmt.Printf("err: %v\n", err)
	}

	db.AutoMigrate(&User{})
}

结构体中属性名的大驼峰对应数据库中下划线分割的字段
结构体的名字的复数对应数据库名字

+---------------+-----------------+------+-----+---------+----------------+
| Field         | Type            | Null | Key | Default | Extra          |
+---------------+-----------------+------+-----+---------+----------------+
| id            | bigint unsigned | NO   | PRI | NULL    | auto_increment |
| created_at    | datetime(3)     | YES  |     | NULL    |                |
| updated_at    | datetime(3)     | YES  |     | NULL    |                |
| deleted_at    | datetime(3)     | YES  | MUL | NULL    |                |
| name          | longtext        | YES  |     | NULL    |                |
| age           | bigint          | YES  |     | NULL    |                |
| birthday      | datetime(3)     | YES  |     | NULL    |                |
| email         | varchar(100)    | YES  |     | NULL    |                |
| role          | varchar(255)    | YES  |     | NULL    |                |
| member_number | varchar(191)    | NO   | UNI | NULL    |                |
| num           | bigint          | YES  |     | NULL    |                |
| address       | varchar(191)    | YES  | MUL | NULL    |                |
+---------------+-----------------+------+-----+---------+----------------+

指定表明

func (User)TableName() string{
	return "user_table"
}

创建表 插入数据

type User struct {
	ID   int64
	Name string
	Age  int64
}

func main() {
	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{})
	if err != nil {
		fmt.Printf("err: %v\n", err)
	}

	//2,把模型与数据库中的表对应起来
	db.AutoMigrate(&User{})

	//3,创建记录
	user := User{Name: "poole", Age: 23}
	db.Create(&user)
}

通过tag设置字段,当该属性为空的时候,将值赋为默认值

type User struct {
	ID   int64
	Name string
	Age  int64 `gorm:"default:20"`
}

注意:对于所有字段的零值,包括0""nil 都不会保存到数据库,使用的是他们的默认值,使用指针将避免此情况

type User struct {
	ID   int64
	Name string
	Age  int64 `gorm:"default:20"`
}

结构体中传入的是一个空的指针,然后将在数据表中写入0值

user := User{Name: "poole", Age: new(int64)}
db.Create(&user)

查询

检索单个对象

GORM 提供了FirstTakeLast方法,以便从数据库中检索单个对象。 当查询数据库时它添加了LIMIT 1条件,且没有找到记录时,它会返回 错误ErrRecordNotFound

//获取第一条数据,主键升序
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;

// 获取一条记录,没有指定排序字段
db.Take(&user)
// SELECT * FROM users LIMIT 1;

// 获取最后一条记录(主键降序)
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;

result := db.First(&user)
result.RowsAffected // 返回找到的记录数
result.Error        // returns error or nil
根据主键检索
db.First(&user, 3)
// SELECT * FROM users WHERE id = 3;

db.First(&user, "10")
// SELECT * FROM users WHERE id = 10;

db.Find(&users, []int{1,2,3})
// SELECT * FROM users WHERE id IN (1,2,3);

对于传入的主键ID数据,将它放入User中,直接传递给First

user := User{ID: 2}
db.First(&user)

查询多个对象

查询全部对象:

db.Find(&users)
// SELECT * FROM users;

条件查询

string条件

获取第一个匹配的记录

db.Where("name=?", "green").First(&user)           
//SELECT * FROM users WHERE name = 'green' ORDER BY id LIMIT 1;

获取所有匹配的记录,所有不等于poole的数据

db.Where("name <> ?", "poole").Find(&users)
//SELECT * FROM users WHERE name <> 'poole';

IN

db.Where("name IN ?", []string{"green", "poole"}).Find(&users)
// SELECT * FROM users WHERE name IN ('green','poole');

LIKE

db.Where("name LIKE ?", "%jin%").Find(&users)
// SELECT * FROM users WHERE name LIKE '%jin%';

AND

db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
struct & map 条件

struct

db.Where(&User{Name: "poole", Age: 23}).First(&user)
//SELECT * FROM users WHERE name = "poole" AND age = 23 ORDER BY id LIMIT 1;

map

db.Where(map[string]interface{}{"name": "poole", "age": 23}).Find(&users)
// SELECT * FROM users WHERE name = "poole" AND age = 23;

slice:切片中数据的主键查询

db.Where([]int64{2, 3, 5}).Find(&users)
// SELECT * FROM users WHERE id IN (2, 3, 5);

需要注意的是,查询条件有零元素的时候,需要使用map的形式,而不是struct的形式

//struct
db.Where(&User{Name: "poole", Age: 0}).Find(&users)
// SELECT * FROM users WHERE name = "poole";
//map
db.Where(map[string]interface{}{"Name": "poole", "Age": 0}).Find(&users)
// SELECT * FROM users WHERE name = "poole" AND age = 0;
内联条件

查询条件可以内联到FirstFind等方法中,其方式与 Where 类似。

//二者是等价的
db.Where("id=?", 2).First(&user)
db.First(&user, "id=?", 2)
Not条件
db.Not("name=?", "looney").Find(&users)
//select * from users where not name ="looney" order by id;
Or条件
db.Where("name=?", "looney").Or("name=?", "poole").Find(&users)
//select * from users where name ="looney" or name ="poole";

选择特定字段

db.Select("name", "age").Find(&users)
//select name,age from users;

排序

db.Order("age desc, name").Find(&users)
//select * from users order by age desc,name;
db.Order("age desc").Order("name").Find(&users)
//select * from users order by age desc,name;

Limit & Offset

db.Limit(3).Find(&users)
//select * from users limit 3;
db.Limit(2).Offset(1).Find(&users)
//select * from users limit 2 offset 1;

高级查询

智能选取字段

GORM 允许通过 Select 方法选择特定的字段,如果您在应用程序中经常使用此功能,你也可以定义一个较小的结构体,以实现调用 API 时自动选择特定的字段,例如:

type User struct {
	ID   int64
	Name string
	Age  int64
}

type ApiUser struct {
	ID   int64
	Name string
}

users := []ApiUser{}
db.Model(&User{}).Limit(3).Find(&users)
fmt.Printf("%v\n", users)
//select id,name from users limit 3;
//[{1 poole} {2 looney} {3 green}]

子查询

子查询可以嵌套在查询中,GORM 允许在使用 *gorm.DB 对象作为参数时生成子查询

db.Where("amount > (?)", db.Table("orders").Select("AVG(amount)")).Find(&orders)
//SELECT * FROM "orders" WHERE amount > (SELECT AVG(amount) FROM "orders");

更新

保存所有字段

Save 会保存所有的字段,即使字段是零值

user := User{}
db.First(&user)
user.Name = "poole"
db.Save(&user)

更新单列

使用Update更新单列时,需要有一些条件,否则将会引起错误 ErrMissingWhereClause

//条件更新
db.Model(&User{}).Where("id=?", 2).Update("age", 26)
//update users set age =26 where id =2;

//根据user的值进行更新
user := User{ID: 2}
db.Model(&user).Update("name", "Kevin Rooney")
//update users set name="Kevin Rooney" where id =2;

//根据条件和user的值进行更新
db.Model(&user).Where("age=?", 26).Update("name", "looney")
//update users set name="looney" where id =2 and age =26;

更新多列

Updates方法支持structmap[string]interface{}参数

//根据 struct 更新属性,只会更新非零值的字段
user := User{ID: 3}
db.Model(&user).Updates(User{Name: "Kevin", Age: 27})
//update users set name ="Kevin",age =27 where id =3;

//根据map更新属性
db.Model(&user).Updates(map[string]interface{}{"name": "green", "age": 32})
//update users set name ="green",age =32 where id =3;

更新选定字段

如果您想要在更新时选定、忽略某些字段,您可以使用 SelectOmit

//选定某些字段
db.Model(&user).Select("age").Updates(User{Name: "green", Age: 27})
//update users set age =27 where id = 3;

//忽略某些字段
db.Model(&user).Omit("name").Updates(User{Name: "green", Age: 27})
//update users set age =27 where id = 3;

批量更新

db.Model(User{}).Where("age=?", 23).Updates(User{Name: "super start"})
//update users set name = "super start" where age = 23; 
阻止全局更新

如果在没有任何条件的情况下执行批量更新,默认情况下,GORM 不会执行该操作,并返回ErrMissingWhereClause 错误

db.Model(&User{}).Update("name", "poole").Error // gorm.ErrMissingWhereClause

db.Model(&User{}).Where("1 = 1").Update("name", "poole")
// UPDATE users SET `name` = "poole" WHERE 1=1

db.Exec("UPDATE users SET name = ?", "poole")
// UPDATE users SET name = "poole"

db.Session(&gorm.Session{AllowGlobalUpdate: true}).Model(&User{}).Update("name", "poole")
// UPDATE users SET `name` = "poole"
更新记录数量
tx := db.Model(User{}).Where("age=?", 23).Updates(User{Name: "mvp"})
fmt.Printf("%v\n", tx.RowsAffected)

使用sql表达式更新

db.Model(&product).Update("price", gorm.Expr("price * ? + ?", 2, 100))
// UPDATE "products" SET "price" = price * 2 + 100 WHERE "id" = 3;

删除

删除一条记录

删除一条记录时,删除对象需要指定主键,否则会触发批量delelte

user := User{ID: 6}
db.Delete(&user)
//delete from users where id = 6;

//添加额外条件的删除
db.Where("name=?","green").Delete(&user)
//delete from users where id = 6 and name = "green"

根据主键删除

//主键可以使用数字或者字符串
db.Delete(&User{}, 7)
//delete from users where id =7;
db.Delete(&User{}, "7")
//delete from users where id =7;

db.Delete(&users, []int{1,2,3})
//delete from users where id in (1,2,3);

批量删除

如果指定的值不是主键,那么gorm会执行批量删除,它将删除所有匹配的记录

db.Where("name like ?", "%zhang%").Delete(&User{})
//delete from users where name like "%zhang%";

db.Delete(&User{}, "email like ?", "%zhang%")
//deleye from users where name like "%zhang%"

阻止全局删除

如果在没有任何条件的情况下执行批量删除,GORM 不会执行该操作,并返回 ErrMissingWhereClause 错误

db.Delete(&User{}).Error // gorm.ErrMissingWhereClause

db.Where("1 = 1").Delete(&User{})
// delete from `users` where 1=1;

db.Exec("DELETE FROM users")
// delete from  users;

db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{})
// delete from  users;

软删除

如果您的模型包含了一个 gorm.deletedat 字段(gorm.Model 已经包含了该字段),它将自动获得软删除的能力!

user := User{ID: 7}
db.Delete(&user)
// update users set deleted_at="1999-10-29 23:23" where id = 7;

//查询时会忽略被软删除的记录
db.Where("age=20").Find(&user)
//select * from users where age = 20 and delete_at is null;

查询被软删除的记录

可以使用Unscoped找到被软删除的记录

db.Unscoped().Where("age = 20").Find(&users)
// select * from users where age = 20;

永久删除

使用Unscoped永久删除匹配的记录

db.Unscoped().Delete(&user)
// delete from users where id=10;
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值