使用 GORM连接数据库——更多的用法| 豆包MarsCode AI 刷题

98 阅读3分钟

数据实体

对于Gorm来说,数据Model不仅仅可以是像type User struct { ID int; Name string;} 这种常规方式去定义结构体,也可以做一些特殊操作,如下:

type User struct {         
  Email        *string        
  Birthday     *time.Time     
  MemberNumber sql.NullString 
  ActivatedAt  sql.NullTime   
  CreatedAt    time.Time       
}

*string 和 *time.Time类型的指针表示可空字段,来自sql.NullString和sql.NullTime用于处理可空字符串和时间。CreatedAt是特殊字段,当记录被创建或更新时,GORM 会自动向内填充当前时间。

另外go的结构体还支持用``来标注字段,来让结构体转化为JSON时,key为指定的其它值而不是字段原本的名称。不过这个并不是gorm提供的专属功能。

``符号还有一些妙用,可以用来做权限控制。代码说明如下:

type User struct {
  Name string `gorm:"<-:create"` // 允许读和创建
  Name string `gorm:"<-:update"` // 允许读和更新
  Name string `gorm:"<-"`        // 允许读和写(创建和更新)
  Name string `gorm:"<-:false"`  // 允许读,禁止写
  Name string `gorm:"->"`        // 只读(除非有自定义配置,否则禁止写)
  Name string `gorm:"->;<-:create"` // 允许读和写
  Name string `gorm:"->:false;<-:create"` // 仅创建(禁止从 db 读)
  Name string `gorm:"-"`  // 通过 struct 读写会忽略该字段
  Name string `gorm:"-:all"`        // 通过 struct 读写、迁移会忽略该字段
  Name string `gorm:"-:migration"`  // 通过 struct 迁移会忽略该字段
}

以上代码来自官网文档。

增删改查

增加

前一篇文章说过,Create方法可以用来插入数据。实际上create也可以批量插入数据,形如:

users := []*User{
    {Name: "Jinzhu", Age: 18, Birthday: time.Now()},
    {Name: "Jackson", Age: 19, Birthday: time.Now()},
}
result := db.Create(users)

注意这里传入的参数是切片。

另外还可以只插入指定数据,例如db.Select("Name", "Age", "CreatedAt").Create(&user)就只会插入"Name", "Age", "CreatedAt"三个属性。

查询

GORM 提供了 First、Take、Last 方法,它们本质上都是在查询语句后面加了一个 LIMIT 1.

First和Last方法会按主键排序找到第一条记录和最后一条记录。而Take则没有指定。

要想查询全部对象,可以使用Find方法。

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

另外这个例子还展示了gorm独特的查询语句构造方法,内容较多,具体可参阅官方文档。

此外还有Order()、Limit()、Group()等方法,相信一看名字就很好理解了。

修改

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

db.First(&user)

user.Name = "jinzhu 2"
user.Age = 100
db.Save(&user)

这一段代码会把First()找到的user更新为如上的数据。save是一个组合函数。如果保存值不包含主键,将执行Create,否则执行Update。

使用Update可以更新单列,Updates方法支持 struct和map[string]interface{}参数更新多列。

删除

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

// Email 的 ID 是 `10`
db.Delete(&email)
// DELETE from emails where id = 10;

// 带额外条件的删除
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";

本质上删除操作还是查询,只不过最后执行了Delete方法而已。