gorm在创建表时使用CreateTable方法进行处理,其参数可以是结构体变量的地址形式,也可以是结构体的地址形式。
例如:
var t Tecent
db.CreateTable(&t)或者db.CreateTable(&Tecent{})。即使类的地址形式中初始化了一些字段,在创建表之后也不会自动添加到表中。如果表已经创建并且表中有数据,再次执行该方法不会再次创建表也不会清除数据。
同理,在创建插入数据时一样可以使用结构体变量地址或者结构体自身的实例化。其实直接使用变量本身也没问题,只不过有些回调函数是使用指针类型调用的,那么就无法调用了。
db.Create(&Tecent{id:1,name:"csdn"})
在插入数据操作时,如果插入数据表的主键为空那么在插入操作后可以使用NewRecord方法判断是否成功,但是如果插入之前就给主键赋值,那该方法就无法判断是否插入成功。因为该方法只是判断主键是否为空。
- type Nxin struct {
- Cid int `gorm:"primary_key""`
- Cname string
- Caddress string
- }
- nn:=Nxin{2,"xiaodai","17ceng"}
- fmt.Println(db.NewRecord(nn))
- er:=db.Create(&nn)
- fmt.Println(db.NewRecord(nn))
- if er.Error!=nil{
- panic("primary key is existing")
- }
gorm的文档中提供了一个回调函数BeforeCreate,这个方法可以在插入数据之前调用,如果在这个方法调用之前列已经赋值,那么该方法会覆盖掉原来的值。前提是该方法的调用者是指针类型。
删除操作与其他语言的orm的删除不同,默认的删除方式是软删除,只是修改了字段delete_at字段为当前时间,然后在查询时再也查不到,但是在数据库中依然存在。如果模型继承自gorm.Model,那么Delete方法则软删除,如果不继承那么就是硬删除(清空数据)。
db.Delete(&Nxin{})是删除表中所有的数据。但是是硬删除。Nxin结构体不继承自gorm.Model。
db.Delete(&Dbn{}})软删除。
匹配删除有两种方式:
db.Where("cid=?",8).Delete(&Nxin{})
db.Delete(&Nxin{},"cid=?",9)
修改数据的方式有很多种,以下一一列出比较常见的几种方式:
第一种,先查询在修改最后保存。
- var nxi Nxin
- db.First(&nxi)
- nxi.Caddress="biejing"
- db.Save(&nxi)
但是这个方法无法完美的在继承自gorm.Model的结构体中使用。如果对该类型的struct修改,就会导致表中create_at等字段被重置。目前我还没办法解决这个问题,希望有解决办法的读者下面留言告诉我,多谢。
第二种,更新表中所有记录某个字段的值。直接针对某个表的模型进行操作,然后更新。
- db.Model(&Nxin{}).Update("caddress","jp")
- <span style="white-space:pre;"> </span>db.Model(&Nxin{}).Where("cid=?",26).Update("caddress","china")//条件写在where里面
- <span style="white-space:pre;"> </span>db.Model(&Nxin{}).Where("cid in (?)",[]int{10,11}).Update("caddress","haidian")
- db.Where("cid=?",37).Model(&Nxin{}).Update("caddress","korean")//where与model先后顺序对结果没影响
- db.Where("cid=?",38).Update("caddress","englist").Model(&Nxin{})//但是model不能放在最后
- var nnn Nxin
- nnn=Nxin{Cid:17}//初始化的时候给某些字段赋值,更新时可以直接作为查询匹配条件的记录,然后修改。
- db.Model(&nnn).Update("caddress","franch")
- db.Model(nnn).Update("caddress","german")//此处可以看到地址类型与变量类型对结果没有影响
- db.Model(&nnn).Update(map[string]interface{}{"cname":"newtest","caddress":"italy"})//同时修改多个字段
- db.Model(&nnn).Update(Nxin{Cname:"nxin",Caddress:"haidian"})
- db.Model(&nnn).Update(map[string]interface{}{"cname":"newtest","caddress":"italy"})//caddress被设置成italy
- db.Model(&nnn).Update(Nxin{Cname:"nxin",Caddress:""})//此处caddress的值并没有被修改成""
- db.Model(&nnn).Update(map[string]interface{}{"cname":"newtest","caddress":""})//caddress被设置成""
查询
第一种,根据gorm自带first,last方法查询。
- <span style="white-space:pre;"> </span>var nx Nxin
- nx=Nxin{Cid:19}//查询的条件可以直接写在结构体对象里面
- //db.First(&nx)
- //fmt.Println(nx.Caddress)
- db.First(&nx)
- fmt.Println(nx.Caddress)
- <span style="white-space:pre;"> </span>var nx2 []Nxin
- db.Where("cid in (?)",[]int{18,19}).Find(&nx2)
- fmt.Println(nx2)
将返回的值放在nx2数组里。这种办法无法把查询条件写在结构体变量里了,只能写在where里。
- <span style="white-space:pre;"> </span>var nx3 Nxin
- nx3=Nxin{Cid:20}
- db.Where("caddress=?","dd").Find(&nx3)
- <span style="white-space:pre;"> </span>db.Find(&nx3)//select * from nxins where cid=20
- <span style="white-space:pre;"> </span>db.Find(&nx3,Nxin{caddress:"jp"})//select * from nxins where cid=20 and caddress="jp"
- <span style="white-space:pre;"> </span>db.Find(&nx3,map[string]interface{}{"caddress":"wang",cname:"wang"})
- <span style="white-space:pre;"> </span>db.Find(&nx3,"caddress=? and cname=?","bj","wang")
- fmt.Println(nx3)
这种方式为在变量中添加条件,where中再添加一条条件,那么就相当于使用and把两个条件合并。即cid=20 and caddress=dd
- <span style="white-space:pre;"> </span>var nx3 Nxin
- nx3=Nxin{Cid:20}
- db.Where("caddress=?","dd").Find(&nx3)
- fmt.Println(nx3)
- var nx4 Nxin
- db.Where(&Nxin{Cid:32,Caddress:"jp"}).First(&nx4)
- fmt.Println(nx4)
- var nx5 []Nxin
- defer db.Close()
- db.Where(map[string]interface{}{"caddress":"jp"}).Find(&nx5)
- fmt.Println(nx5)
与where条件类似的还有Not条件语句。如果使用or作为查询条件,那么就要使用or语句了,不过Or语句的用法与where一样,只不过在生成的sql语句中使用的or连接,
- var nx6 []Nxin
- db.Where(map[string]interface{}{"caddress":"jp3"}).Or(map[string]interface{}{"cid":56}).Find(&nx6)
- fmt.Println(nx6)
- var nx7 []Nxin
- db.Or(map[string]interface{}{"cid":56}).Where(map[string]interface{}{"caddress":"jp3"}).Find(&nx7)
- fmt.Println(nx7)
一些小的查询技巧:
db.Limit(10).where()....//限制只去前10个记录,相当于select * from xxx limit 10
db.Select("name,age").Find(&user)//只查询name,age字段,相当于select name,age from user
db.Select([]string{"name","age"}).Find(&user)
var c int
db.Model(&User{}).Count(&c)//获取表数据行数
对一些复杂业务进行查询时,可以使用join进行连接。
db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results)
对于已经获取的结果,应该保存在一个结构体的变量中。
如果只是想获得某个表中某个字段的值可以使用Pluck方法。但是返回的结果必须存放在数组中。
var age []int
db.Model(&User{}).Pluck("age",&age)
如果使用model类型进行查询,那么结果会自动填写到类似&user之类的变量中。但是如果使用
db.Table("user")。。。。。。这种类型,结果需要使用scan方法赋值到对应的参数变量中。