当前位置: 首页 > news >正文

Go framework-GORM

目录

一、GORM

1、GORM连接数据库

2、单表的增删改查

3、结构体名和表名的映射规则

4、gorm.Model匿名字段

5、结构体标签gorm

6、多表操作

7、常用方法

8、支持原生SQL

9、Gin整合GORM


一、GORM

        ORM:即Object-Relational Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。

        GORM:gorm是go语言的一个orm框架,Golang 写的,开发人员友好的 ORM 库。

GORM官网网站

GORM github源码

安装GORM:

go get github.com/jinzhu/gorm

新建test_gorm项目

D:\GO_workspace_web>md test_gormD:\GO_workspace_web>cd test_gormD:\GO_workspace_web\test_gorm>go mod init test_gorm
go: creating new go.mod: module test_gormD:\GO_workspace_web\test_gorm>

使用GoLand打开项目,进入Terminal命令

PS D:\GO_workspace_web\test_gorm> go get github.com/jinzhu/gorm
go: downloading github.com/jinzhu/gorm v1.9.16
go: downloading github.com/jinzhu/inflection v1.0.0
go: added github.com/jinzhu/gorm v1.9.16
go: added github.com/jinzhu/inflection v1.0.0
PS D:\GO_workspace_web\test_gorm> 

1、GORM连接数据库

package mainimport (_ "github.com/go-sql-driver/mysql" //引入mysql的驱动"github.com/jinzhu/gorm"
)func main() {//连接数据库://Open传入两个参数://第一个参数:指定你要连接的数据库//第二个参数:指的是数据库的设置信息:用户名:密码@tcp(ip:port)/数据库名字?charset=utf8&parseTime=True&loc=Local//charset=utf8设置字符集//parseTime=True为了处理time.Time//loc=Local 时区设置,与本地时区保持一致db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()
}

2、单表的增删改查

package mainimport ("fmt"_ "github.com/go-sql-driver/mysql" //引入mysql的驱动"github.com/jinzhu/gorm"
)func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()db.CreateTable(&User{}) //创建表,默认表名后加s//db.Table("user").CreateTable(&User{}) //指定要创建的表名//flg1 := db.HasTable(&User{})  //判断是否有某张表//fmt.Println(flg1)flg2 := db.HasTable("users") //判断是否有某张表fmt.Println(flg2)//db.DropTable(&User{})  //删除表//db.DropTable("user")   //指定删除表名//增删改查//增加db.Create(&User{Name: "张无忌", Age: 30})//查询var muser Userdb.First(&muser, "age=?", 30)fmt.Println(muser)//更新:先查询再更新db.Model(&muser).Update("age", 40)fmt.Println(muser)db.Model(&muser).Update("name", "张翠山")fmt.Println(muser)//删除:先查询再删除db.Delete(&muser)fmt.Println(muser)
}type User struct {Name stringAge  int
}

3、结构体名和表名的映射规则

  1. 如果结构体名没有驼峰命名,那么表名就是:结构体名小写+复数形式: 如结构体名User-->表名users
  2. 如果结构体名有驼峰命名,那么表名就是:大写变小写并在前面加下划线,最后加复数形式:如结构体名UserInfo-->表名user_infos
  3. 如有结构体名有连续的大写字母,那么表名就是:连续的大写字母变小写,驼峰前加下划线,字母变小写,最后加复数形式:如结构体名:DBUserInfo-->表名db_user_infos
  4. 结构体中字段名称与表中列名的映射规则同上

自定义表名

package mainimport ("github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)
type User struct {Age  intName string
}
type UserInfo struct {Age  intName string
}
type DBUserInfo struct {Age  intName string
}
type MyUser struct {Age  intName string
}
func (MyUser) TableName() string {//自定义表名return "test_my_user"
}
func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()db.CreateTable(&User{})db.CreateTable(&UserInfo{})db.CreateTable(&DBUserInfo{})db.CreateTable(&MyUser{})
}

4、gorm.Model匿名字段

        只需要在自己的模型中指定gorm.Model匿名字段,即可在数据库表中包含四个字段:ID,CreatedAt,UpdatedAt,DeletedAt

ID:主键自增长
CreatedAt:用于存储记录的创建时间
UpdatedAt:用于存储记录的修改时间
DeletedAt:用于存储记录的删除时间

package mainimport ("github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)type MyTest struct {gorm.ModelAge  intName string
}func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()db.CreateTable(&MyTest{})
}

5、结构体标签gorm

通过结构体标签gorm来实现表的约束
gorm标签属性值:
(1)-: 忽略,不映射这个字段    eg: `gorm:"-"`  ,适合:一些冗余字段,不想在数据库中体现,只想在结构体中体现
(2)primary_key:主键     eg: `gorm:"primary_key"`
PS:如果是想要加联合主键,在每个字段后加入 `gorm:"primary_key"`即可
例如:即可将StuID和Name作为联合主键

StuID int `gorm:"primary_key"`
Name string `gorm:"primary_key"`

(3)AUTO_INCREMENT:自增    eg:  `gorm:"AUTO_INCREMENT"`
(4)not null:不为空,默认为空    eg: `gorm:"not null"`
(5)index:索引,  eg: `gorm:"index"`
创建索引并命名:eg: `gorm:"index:idx_name_code"`
(6)unique_index:唯一索引     eg: `gorm:"unique_index"`
唯一性索引unique index和一般索引normal index最大的差异就是在索引列上增加了一层唯一约束。添加唯一性索引的数据列可以为空,但是只要存在数据值,就必须是唯一的。
(7)unique:唯一   eg: `gorm:"unique"`
(8)column:指定列名   eg: `gorm:"column:user_name"`
(9)size:字符串长度,默认为255   eg:`gorm:"size:10"`
(10)default `default:'男'` 默认值
(11)type:设置sql类型  eg: `gorm:"type:int(2)"` 
PS:多个属性值之间用分号分隔

type Student struct {StuID   int    `gorm:"primary_key;AUTO_INCREMENT"`Name    string `gorm:"not null"`Age     int    `gorm:"unique_index"`Email   string `gorm:"unique"`Sex     string `gorm:"column:gender;size:10"`Desc    string `gorm:"-"`Classno string `gorm:"type:int"`
}

6、多表操作

6.1、一对一关系

//1、
type User struct{UserId int `gorm:"primary_key;AUTO_INCREMENT"`Age intName string
}
type UserInfo struct {InfoID int `gorm:"primary_key;AUTO_INCREMENT"`Pic stringAddress stringEmail string//关联关系User User//指定外键UserId int
}//2、通过gorm标签来指定外键:(属于关系:关系和外键的指定在同一方)
type User struct{UserId int `gorm:"primary_key;AUTO_INCREMENT"`Age intName string
}
type UserInfo struct {InfoID int `gorm:"primary_key;AUTO_INCREMENT"`Pic stringAddress stringEmail string//关联关系User User `gorm:"ForeignKey:MyUserID;AssociationForeignKey:UserId"`//指定外键:MyUserID int
}//3、通过gorm标签来指定外键:(包含关系:关系和外键的指定不在同一方)
type User struct {UserId int `gorm:"primary_key;AUTO_INCREMENT"`Age    intName   stringIID    int
}type UserInfo struct {InfoID  int `gorm:"primary_key;AUTO_INCREMENT"`Pic     stringAddress stringEmail   stringUser    User `gorm:"ForeignKey:IID;AssociationForeignKey:InfoID"` //关联关系
}

操作:

package mainimport ("fmt""github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)type User struct {UserId int `gorm:"primary_key;AUTO_INCREMENT"`Age    intName   stringIID    int
}type UserInfo struct {InfoID  int `gorm:"primary_key;AUTO_INCREMENT"`Pic     stringAddress stringEmail   stringUser    User `gorm:"ForeignKey:IID;AssociationForeignKey:InfoID"` //关联关系
}func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()db.DropTable(&User{})db.DropTable(&UserInfo{})db.CreateTable(&User{})db.CreateTable(&UserInfo{})fmt.Println("===========关联添加==============")//关联添加数据: (因为关联关系在UserInfo表中,所以添加操作从UserInfo来入手)userinfo := UserInfo{Pic:     "/upload/1.jpg",Address: "北京海淀区",Email:   "124234@126.com",User: User{Age:  19,Name: "丽丽",},}db.Create(&userinfo)fmt.Println("===========关联查询==============")//关联查询:Association方式查询:Association方式查询缺点:先First查询,再Association查询var userinfo1 UserInfo//如果只是执行下面这步操作,那么关联的User信息是查询不到的:db.First(&userinfo1, "info_id = ?", 1)fmt.Println(userinfo1)//如果想要查询到User相关内容,必须执行如下操作://Model参数:要查询的表数据,Association参数:关联到的具体的模型:模型名字User(字段名字)//Find参数:查询的数据要放在什么字段中&userinfo.Userdb.Model(&userinfo1).Association("User").Find(&userinfo1.User)fmt.Println(userinfo1)//关联查询:Preload方式查询:var userinfo2 UserInfo//查询info_id=1的数据放入userinfo中,并关联查询到User字段对应的数据db.Preload("User").Find(&userinfo2, "info_id = ?", 1)fmt.Println(userinfo2)//关联查询:Related方式查询var userinfo3 UserInfodb.First(&userinfo3, "info_id = ?", 1)fmt.Println(userinfo3)var user User//通过userinfo模型查出来的User字段的信息放入新的容器user中:db.Model(&userinfo3).Related(&user, "User")fmt.Println(user)fmt.Println(userinfo3)fmt.Println("===========关联更新==============")//关联更新//先查询var userinfo11 UserInfodb.Preload("User").Find(&userinfo11, "info_id = ?", 1)fmt.Println(userinfo11)//再更新:注意:Update的参数age可以用结构体中字段Age也可以用数据库age字段db.Model(&userinfo11.User).Update("age", 31)fmt.Println(userinfo11)fmt.Println("===========关联删除==============")//关联删除//先查询var userinfo12 UserInfodb.Preload("User").Find(&userinfo12, "info_id = ?", 1)fmt.Println(userinfo12)//再删除:借助userinfo模型删除User记录db.Delete(&userinfo12.User) //UserInfo中信息没有被删除,删除的是关联的User表中的记录db.Delete(&userinfo12)
}

6.2、一对多关系

type Author struct {AID int `gorm:"primary_key;AUTO_INCREMENT"`Name stringAge intSex stringArticle []Article `gorm:"ForeignKey:AuId;AssociationForeignKey:AID"`//关联关系
}type Article struct {ArId int `gorm:"primary_key;AUTO_INCREMENT"`Title stringContent stringDesc stringAuId int//设置外键
}

操作:

package mainimport ("fmt""github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)type Author struct {AID  int `gorm:"primary_key;AUTO_INCREMENT"`Name stringAge  intSex  string//关联关系:Article []Article `gorm:"ForeignKey:AuId;AssociationForeignKey:AID"`
}
type Article struct {ArId    int `gorm:"primary_key;AUTO_INCREMENT"`Title   stringContent stringDesc    string//设置外键:AuId int
}func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()db.DropTable(&Author{})db.DropTable(&Article{})db.CreateTable(&Author{})db.CreateTable(&Article{})fmt.Println("===========关联添加==============")//关联添加数据:author := Author{Name: "张三",Age:  30,Sex:  "男",Article: []Article{{Title:   "HTML入门",Content: "HTML******",Desc:    "非常好",},{Title:   "CSS入门",Content: "CSS******",Desc:    "此书不错",},},}db.Create(&author)fmt.Println("===========关联查询==============")//关联查询:Association方式查询:Association方式查询缺点:先First查询,再Association查询var author1 Author//如果只是执行下面这步操作,那么关联的User信息是查询不到的:db.First(&author1, "a_id = ?", 1)fmt.Println(author1)//如果想要查询到Article相关内容,必须执行如下操作://Model参数:要查询的表数据,Association参数:关联到的具体的模型:模型名字Article(字段名字)//Find参数:查询的数据要放在什么字段中&author.Articledb.Model(&author1).Association("Article").Find(&author1.Article)fmt.Println(author1)//关联查询:Preload方式查询:var author2 Author//查询a_id=1的数据放入author中,并关联查询到Article字段对应的数据db.Preload("Article").Find(&author2, "a_id = ?", 1)fmt.Println(author2)//关联查询:Related方式查询var author3 Authordb.First(&author3, "a_id = ?", 1)fmt.Println(author3)var as []Article//通过author模型查出来的Article字段的信息放入新的容器as中:db.Model(&author3).Related(&as, "Article")fmt.Println(as)fmt.Println(author3)fmt.Println("===========关联更新==============")//关联更新//先查询//Preload方式查询:var author4 Author//查询a_id=1的数据放入author中,并关联查询到Article字段对应的数据db.Preload("Article").Find(&author4, "a_id = ?", 1)fmt.Println(author4)//再更新://如果直接Update操作那么关联的文章的记录就会被全部更改//所以你要改动指定的记录必须加入限定条件:db.Model(&author.Article).Where("ar_id = ?", 1).Update("title", "JS入门")fmt.Println("===========关联删除==============")//关联删除//先查询//Preload方式查询:var author5 Author//查询a_id=1的数据放入author中,并关联查询到Article字段对应的数据db.Preload("Article").Find(&author5, "a_id = ?", 1)fmt.Println(author5)db.Where("ar_id = ?", 2).Delete(&author5.Article)
}

6.3、多对多关系

type Student struct {SId int `gorm:"primary_key"`SNo intName stringSex stringAge intCourse []Course `gorm:"many2many:Student2Course"`//关联表
}type Course struct {CId int `gorm:"primary_key"`CName stringTeacherName stringRoom string
}

操作:

package mainimport ("fmt""github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)type Student struct {SId  int `gorm:"primary_key"`SNo  intName stringSex  stringAge  int//关联表:Course []Course `gorm:"many2many:Student2Course"`
}
type Course struct {CId         int `gorm:"primary_key"`CName       stringTeacherName stringRoom        string
}func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()db.DropTable(&Student{})db.DropTable(&Course{})db.CreateTable(&Student{})db.CreateTable(&Course{})fmt.Println("===========关联添加==============")//关联添加数据:stu := Student{SNo:  1001,Name: "丽丽",Sex:  "女",Age:  18,Course: []Course{{CName:       "c++",TeacherName: "张三",Room:        "s-103",},{CName:       "高数",TeacherName: "李四",Room:        "s-801",},},}db.Create(&stu)fmt.Println("===========关联查询==============")//关联查询:Association方式查询:Association方式查询缺点:先First查询,再Association查询var student Student//如果只是执行下面这步操作,那么关联的User信息是查询不到的:db.First(&student, "s_id = ?", 1)fmt.Println(student)//如果想要查询到Article相关内容,必须执行如下操作://Model参数:要查询的表数据,Association参数:关联到的具体的模型:模型名字Article(字段名字)//Find参数:查询的数据要放在什么字段中&student.Coursedb.Model(&student).Association("Course").Find(&student.Course)fmt.Println(student)//关联查询:Preload方式查询:var student1 Studentdb.Preload("Course").Find(&student1, "s_id = ?", 1)fmt.Println(student1)//关联查询:Related方式查询var student2 Studentdb.First(&student2, "s_id = ?", 1)fmt.Println(student2)var course []Course//通过author模型查出来的Article字段的信息放入新的容器as中:db.Model(&student2).Related(&course, "Course")fmt.Println(course)fmt.Println(student2)fmt.Println("===========关联更新==============")//关联更新//先查询//Preload方式查询:var student3 Studentdb.Preload("Course").Find(&student3, "s_id = ?", 1)fmt.Println(student3)//再更新://如果直接Update操作那么关联的文章的记录就会被全部更改//所以你要改动指定的记录必须加入限定条件:db.Model(&student3.Course).Where("c_id = ?", 1).Update("c_name", "Java")fmt.Println("===========关联删除==============")//关联删除//先查询//Preload方式查询:var student4 Studentdb.Preload("Course").Find(&student4, "s_id = ?", 1)fmt.Println(student4)db.Where("c_id = ?", 2).Delete(&student4.Course)
}

7、常用方法

【1】First:按照条件查询,并且升序排列,查询出一条记录
【2】FirstOrCreate:有数据就查询出来,没有就创建一条记录
【3】Last:按照条件查询,并且降序排列,查询出一条记录
【4】Take:按照条件查询,查询出一条记录
【5】Find:按照条件查询

package mainimport ("fmt""github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)type User struct {UserId int `gorm:"primary_key;AUTO_INCREMENT"`Age    intName   stringIID    int
}func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()db.DropTable(&User{})db.CreateTable(&User{})//增加:Execdb.Exec("insert into users (age,name) values (?,?)", 18, "张无忌")//First:var user Userdb.Debug().First(&user, 1) //-->默认情况查询的是主键fmt.Println(user)db.Debug().First(&user, "user_id = ?", 1)fmt.Println(user)db.Debug().Where("user_id = ?", 1).First(&user)fmt.Println(user)//FirstOrCreate:SELECT * FROM `users`  WHERE `users`.`user_id` = 1 AND ((user_id = 1)) ORDER BY `users`.`user_id` ASC LIMIT 1user2 := User{ //这里定义的结构体的实例的数值其实就是FirstOrCreate的查询条件UserId: 2,Age:    20,Name:   "菲菲",IID:    1,}//如果有对应的数据,就查询出来,如果没有对应的数据,就会帮我们创建新的记录db.FirstOrCreate(&user, user2)fmt.Println(user)//Last:SELECT * FROM `users`  WHERE `users`.`user_id` = 2 AND ((`users`.`user_id` = 1)) ORDER BY `users`.`user_id` DESC LIMIT 1db.Debug().Last(&user, 1)fmt.Println(user)//Take:SELECT * FROM `users`  WHERE `users`.`user_id` = 2 AND ((`users`.`user_id` = 1)) LIMIT 1db.Debug().Take(&user, 1)fmt.Println(user)//Find:SELECT * FROM `users`  WHERE `users`.`user_id` = 2 AND ((`users`.`user_id` IN (1,2)))user_id_arr := []int{1, 2}db.Debug().Find(&user, user_id_arr)fmt.Println(user)
}

【6】Where:加入指定条件:
具体条件为:=,like,in,and,between....
【7】Select:筛选查询出来的字段
【8】Create:添加数据
【9】Save:添加数据
【10】Update:更新数据
【11】Delete:删除数据

package mainimport ("fmt""github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)type User struct {UserId int `gorm:"primary_key;AUTO_INCREMENT"`Age    intName   stringIID    int
}func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()db.DropTable(&User{})db.CreateTable(&User{})//增加:Execdb.Exec("insert into users (age,name) values (?,?)", 18, "张无忌")//Wherevar user Userdb.Debug().Where("user_id = ?", 1).First(&user)fmt.Println(user)db.Debug().Where("user_id in (?)", []int{1, 2}).First(&user)fmt.Println(user)//Selectdb.Debug().Select("name,age").Where("user_id = ?", 1).First(&user)fmt.Println(user)//Create:操作只可以插入一条技能,不能批量操作user2 := User{Age:  26,Name: "小明",IID:  1,}db.Create(&user2)//Saveuser3 := User{Age:  14,Name: "莎莎",IID:  1,}db.Save(&user3)//Update更新:先查询再更新:var user4 User//(1)先查询,再通过Model进行操作,再Update操作:db.Where("user_id = ?", 1).First(&user4)db.Model(&user4).Update("age", 29)fmt.Println(user4)//(2)直接在查询之后进行操作:db.Where("user_id = ?", 1).First(&user4).Update("name", "露露")fmt.Println(user4)//(3)直接在查询之后进行操作,传入结构体示例,更新多个字段db.Where("user_id = ?", 1).First(&user4).Update(User{Age:  11,Name: "小刚",})fmt.Println(user4)//(4)直接在查询之后进行操作,传入map,更新多个字段db.Where("user_id = ?", 1).First(&user4).Update(map[string]interface{}{"age":  21,"name": "小花",})fmt.Println(user4)//Delete:删除数据:// (1)先查询再删除:var user5 Userdb.Where("user_id = ?", 1).First(&user5)db.Delete(&user5)//(2)通过条件直接进行删除:var user6 Userdb.Where("user_id = ?", 2).Delete(&user6)
}

【12】Not:排除某个具体条件的查询操作
【13】Or:多个条件的查询
【14】Order:进行升序或者降序的排列
【15】Limit:指定获取记录的最大数量
【16】Offset:设置偏移
【17】Scan:将结果扫描到另一个结构体中
【18】Count:计数
【19】GROUP:进行分组
【20】Having:分组后进行过滤

package mainimport ("fmt""github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)type User struct {UserId int `gorm:"primary_key;AUTO_INCREMENT"`Age    intName   stringIID    int
}func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()db.DropTable(&User{})db.CreateTable(&User{})//增加:Execdb.Exec("insert into users (age,name) values (?,?)", 28, "张无忌")db.Exec("insert into users (age,name) values (?,?)", 26, "赵敏")db.Exec("insert into users (age,name) values (?,?)", 25, "小昭")//Not:var users []Userdb.Not("user_id = ?", 1).Find(&users)fmt.Println(users)var users1 []Userdb.Debug().Not(User{Age:  18,Name: "丽丽",}).Find(&users1)fmt.Println(users1)//Or :var users2 []Userdb.Where("user_id = ?", 1).Or("user_id = ?", 3).Find(&users2)fmt.Println(users2)//Order:var users3 []Userdb.Where("age = ?", 26).Order("user_id asc").Find(&users3)fmt.Println(users3)//Limit:var users4 []Userdb.Limit(2).Find(&users4)fmt.Println(users4)//Offset://注意:Offset中设置的偏移数字为第几条记录,从0开始,0、1、2、、、、//注意:Offset必须和Limit结合使用var users5 []Userdb.Offset(1).Limit(2).Find(&users5)fmt.Println(users5)//Scantype UserDemo struct { //你要扫描的结构体的字段的名字和User中的字段名字必须一致才可以扫描Name stringAge  int}var userdemo UserDemovar user Userdb.Where("user_id=?", 1).Find(&user).Scan(&userdemo)fmt.Println(user)fmt.Println(userdemo)//Count:var users6 []User//定义一个变量接收计数的数量:var count intdb.Find(&users6).Count(&count)fmt.Println(users6)fmt.Println(count)//Group:var users7 []User//定义一个新的结构体:type GroupData struct {Age   intCount int}var group_date []GroupData//Having:在分组以后进行过滤db.Debug().Select("age,count(*) as count").Group("age").Find(&users7).Having("age > 18").Scan(&group_date)fmt.Println(users7)fmt.Println(group_date)
}

【21】Join :左连接、右连接:
【22】LogMod:
Gorm内置的日志记录器,显示详细日志
PS :利用Debug只能逐条打印对应日志信息,但是设置LogMod(true)相当于设置了全局打印,所有执行的逻辑日志都会帮我们输出打印

package mainimport ("fmt""github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)type User struct {UserId int `gorm:"primary_key;AUTO_INCREMENT"`Age    intName   stringIID    int
}type UserInfo struct {InfoID  int `gorm:"primary_key;AUTO_INCREMENT"`Pic     stringAddress stringEmail   stringUser    User `gorm:"ForeignKey:IID;AssociationForeignKey:InfoID"` //关联关系
}func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()//开启打印日志:db.LogMode(true)db.DropTable(&User{})db.DropTable(&UserInfo{})db.CreateTable(&User{})db.CreateTable(&UserInfo{})//增加:Execdb.Exec("insert into users (age,name) values (?,?)", 28, "张无忌")db.Exec("insert into users (age,name) values (?,?)", 26, "赵敏")db.Exec("insert into users (age,name) values (?,?)", 25, "小昭")//Joins://定义一个新的结构体用于Scan:type NewUserInfo struct {User_Id intName    stringI_Id    intInfo_Id intAddress string}var newUser []NewUserInfovar users []Userdb.Select("users.user_id,users.name,users.i_id,user_infos.info_id,user_infos.address").Joins("left join user_infos on users.i_id = user_infos.info_id").Find(&users).Scan(&newUser)fmt.Println(users)fmt.Println(newUser)
}

8、支持原生SQL

package mainimport ("fmt""github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)type User struct {Name stringAge  int
}func main() {db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}defer db.Close()//开启打印日志:db.LogMode(true)db.CreateTable(&User{})//增加:Execdb.Exec("insert into users (age,name) values (?,?)", 18, "张无忌")//查询操作:Rawvar users []Userdb.Raw("select * from users where age = ?", 18).Find(&users)fmt.Println(users)//删除、修改:Execdb.Exec("update users set name = ? where age = ?", "明明", 18)db.Exec("delete from users where age = ?", 18)
}

运行结果

(D:/GO_workspace_web/test_gorm/part04/main.go:23) 
[2023-08-19 21:48:51]  [40.40ms]  CREATE TABLE `users` (`name` varchar(255),`age` int )  
[0 rows affected or returned ] (D:/GO_workspace_web/test_gorm/part04/main.go:26)
[2023-08-19 21:48:51]  [5.56ms]  insert into users (age,name) values (18,'张无忌')
[1 rows affected or returned ](D:/GO_workspace_web/test_gorm/part04/main.go:29)
[2023-08-19 21:48:51]  [0.63ms]   select * from users where age = 18
[1 rows affected or returned ]
[{张无忌 18}](D:/GO_workspace_web/test_gorm/part04/main.go:32)
[2023-08-19 21:48:51]  [4.09ms]  update users set name = '明明' where age = 18
[1 rows affected or returned ](D:/GO_workspace_web/test_gorm/part04/main.go:33)
[2023-08-19 21:48:51]  [10.08ms]  delete from users where age = 18
[1 rows affected or returned ]Process finished with the exit code 0

9、Gin整合GORM

DB操作提取

package dbopeimport ("github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql"
)var Db *gorm.DB
var Err errorfunc init() {Db,Err = gorm.Open("mysql","root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")if Err != nil {panic(Err)}
}

main.go

package mainimport ("test_gorm/part12/dbope""github.com/gin-gonic/gin"
)type Student struct {Id   int `gorm:"primary_key"`Name stringAge  int
}func AddStu(context *gin.Context) {stu := Student{Name: "露露",Age:  21,}dbope.Db.DropTable(&stu)dbope.Db.CreateTable(&stu)//添加操作dbope.Db.Create(&stu)//关闭资源:dbope.Db.Close()
}func main() {r := gin.Default()r.GET("/addStu", AddStu)r.Run()
}

Web framework-Gin

Golang学习+深入(一)

人必须要成长!

如今一道为尊,万道相和,几乎很难破。最可怕的是苍穹!

相关文章:

Go framework-GORM

目录 一、GORM 1、GORM连接数据库 2、单表的增删改查 3、结构体名和表名的映射规则 4、gorm.Model匿名字段 5、结构体标签gorm 6、多表操作 7、常用方法 8、支持原生SQL 9、Gin整合GORM 一、GORM ORM:即Object-Relational Mapping,它的作用是在…...

FirmAE 工具安装(解决克隆失败 网络问题解决)

FirmAE官方推荐使用Ubuntu 18.04系统进行安装部署,FirmAE工具的安装部署十分简单,只需要拉取工具仓库后执行安装脚本即可。 首先运行git clone --recursive https://kgithub.com/pr0v3rbs/FirmAE命令 拉取FirmAE工具仓库,因为网络的问题&…...

css实现九宫格布局

要使用CSS实现九宫格布局,可以创建一个包含九个元素的容器,并使用display: grid属性将其设置为网格布局。然后,使用grid-template-columns和grid-template-rows属性来定义网格的行和列布局。接下来,使用grid-gap属性来设置网格的行…...

linux下系统问题排查基本套路

文章目录 总结常用命令原文GC相关网络TIME_WAITCLOSE_WAIT 总结常用命令 top 查找cpu占用高的进程ps 找到对应进程的pidtop -H -p pid 查找cpu利用率较高的线程printf ‘%x\n’ pid 将线程pid转换为16进制得到 nidjstack pid |grep ‘nid’ -C5 –color 在jstack中找到对应堆栈…...

想解锁禁用的iPhone?除了可以使用电脑之外,这里还有不需要电脑的方法!

多次输入错误的密码后,iPhone将显示“iPhone已禁用”。这种情况看起来很棘手,因为你现在不能用iPhone做任何事情。对于这种情况,我们提供了几种有效的方法来帮助你在最棘手的问题中解锁禁用的iPhone。你可以选择使用或不使用电脑来解锁禁用的iPhone。 一、为什么你的iPhone…...

基于Springboot+Thymeleaf学生在线考试管理系统——LW模板

摘 要 随着当前大数据时代的飞速发展,信息技术以及数据科学不断的普及,教育界也随之更新换代。无粉尘黑板以及电子化考试都已经是在各种学校中普及使用,而且因为操作简单以及对环境没有任何影响,这也将是未来发展的重大趋势。而由…...

STM32f103c6t6/STM32f103c8t6寄存器开发

目录 资料 寻址区 2区 TIMx RTC WWDG IWDG SPI I2S USART I2C USB全速设备寄存器 bxCAN BKP PWR DAC ADC ​编辑 EXTI ​编辑 GPIO AFIO SDIO DMA CRC RCC FSMC USB_OTG ETH(以太网) 7区 配置流程 外部中断 硬件中断 例子 点灯 …...

MySQL Connection not available.

Mysql 报错 最近部署在服务器上的mysql总是报这种错。 但是在服务器上,使用命令行是可以登录进mysq的。 cursor db.cursor() File “/home/ubuntu/miniconda3/envs/chatbot_env/lib/python3.9/site-packages/mysql/connector/connection_cext.py”, line 700, in …...

PHP反序列化 字符串逃逸

前言 最近在打西电的新生赛&#xff0c;有道反序列化的题卡了很久&#xff0c;今天在NSS上刷题的时候突然想到做法&#xff0c;就是利用字符串逃逸去改变题目锁死的值&#xff0c;从而实现绕过 为了研究反序列化的字符串逃逸 我们先简单的测试下 原理 <?php class escape…...

DockerFile解析

1. 是什么 Dockerfile是田来构建Docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚本 1.1 概述 1.2 官网 Dockerfile reference | Docker Documentation 1.3 构建三步骤 1. 编写dockerfile文件 2. docker build命令构建镜像 3. docker run依镜像运…...

斯坦福大学医学院教授:几年内ChatGPT之类的AI将纳入日常医学实践

注意&#xff1a;本信息仅供参考&#xff0c;分享此内容旨在传递更多信息之目的&#xff0c;并不意味着赞同其观点或证实其说法。 在一项新研究中&#xff0c;斯坦福大学研究人员发现&#xff0c;ChatGPT在复杂临床护理考试题中可以胜过一、二年级的医学生。此项研究显示&#…...

golang 命令行 command line (flag,os,arg,args)

目录 1. golang 命令行 command line1.1. Introduction1.2. Parsing Arguments from the command line (os package)1.2.1. Get the number of args1.2.2. Iterate over all arguments 1.3. Using flags package1.3.1. Parse Typed Flags1.3.2. Set flags from the script1.3.3…...

Shell语法揭秘:深入探讨常见Linux Shell之间的语法转换

深入探讨常见Linux Shell之间的语法转换 一、引言二、Linux常用Shell&#xff1a;Bash、Zsh、Ksh、Csh、Tcsh和Fish的简介2.1、Bash、Zsh、Ksh、Csh、Tcsh和Fish的特点和用途2.2、语法差异是常见Shell之间的主要区别 三、变量和环境设置的语法差异3.1、变量定义和使用的不同语法…...

Python3 基础语法

Python3 基础语法 编码 默认情况下&#xff0c;Python 3 源码文件以 UTF-8 编码&#xff0c;所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的编码&#xff1a; # -*- coding: cp-1252 -*- 上述定义允许在源文件中使用 Windows-1252 字符集中的字符编码&…...

spring boot分装通用的查询+分页接口

背景 在用spring bootmybatis plus实现增删改查的时候&#xff0c;总是免不了各种模糊查询和分页的查询。每个数据表设计一个模糊分页&#xff0c;这样代码就造成了冗余&#xff0c;且对自身的技能提升没有帮助。那么有没有办法实现一个通用的增删改查的方法呢&#xff1f;今天…...

【OpenCV】OpenCV环境搭建,Mac系统,C++开发环境

OpenCV环境搭建&#xff0c;Mac系统&#xff0c;C开发环境 一、步骤VSCode C环境安装运行CMake安装运行OpenCV 安装CMakeList 一、步骤 VSCode C环境安装CMake 安装OpenCV 安装CmakeList.txt VSCode C环境安装运行 访问官网 CMake安装运行 CMake官网 参考文档 OpenCV 安…...

node安装node-sass依赖失败(版本不一致)

1.官网对应node版本 https://www.npmjs.com/package/node-sass2.node-sass版本对应表...

联想小新Pro 16笔记本键盘失灵处理方法

问题描述&#xff1a; 联想小新Pro 16新笔记本开机准备激活&#xff0c;到连接网络的时候就开始触控板、键盘失灵&#xff0c;但是有意思的是键盘的背光灯是可以调节关闭的&#xff1b;外接鼠标是正常可以移动的&#xff0c;但是只要拔掉外接鼠标再插回去的时候就不能用了&…...

python 连接Redis 数据库

pip install redis python代码 import redis# 连接数据库 r redis.Redis(host192.168.56.15, port6379, db0)# 存储数据 #r.set(key, value) r.set(name, zaraNet)# 获取数据 value r.get(name) print(value)# 关闭连接&#xff08;可选&#xff09; r.close()...

使用 wxPython 和 pymupdf进行 PDF 加密

PDF 文件是一种常见的文档格式&#xff0c;但有时候我们希望对敏感信息进行保护&#xff0c;以防止未经授权的访问。在本文中&#xff0c;我们将使用 Python 和 wxPython 库创建一个简单的图形用户界面&#xff08;GUI&#xff09;应用程序&#xff0c;用于对 PDF 文件进行加密…...

Mysql性能优化:什么是索引下推?

导读 索引下推&#xff08;index condition pushdown &#xff09;简称ICP&#xff0c;在Mysql5.6的版本上推出&#xff0c;用于优化查询。 在不使用ICP的情况下&#xff0c;在使用非主键索引&#xff08;又叫普通索引或者二级索引&#xff09;进行查询时&#xff0c;存储引擎…...

Pytorch建立MyDataLoader过程详解

简介 torch.utils.data.DataLoader(dataset, batch_size1, shuffleNone, samplerNone, batch_samplerNone, num_workers0, collate_fnNone, pin_memoryFalse, drop_lastFalse, timeout0, worker_init_fnNone, multiprocessing_contextNone, generatorNone, *, prefetch_factorN…...

十问华为云 Toolkit:开发插件如何提升云上开发效能

众所周知&#xff0c;桌面集成开发环境&#xff08;IDE&#xff09;已经融入到开发的各个环节&#xff0c;对开发者的重要性和广泛度是不言而喻的&#xff0c;而开发插件更是建立在IDE基础上的功能Buff。 Huawei Cloud ToolKit作为华为云围绕其产品能力向开发者桌面上的延伸&a…...

NO.06 自定义映射resultMap

1、前言 在之前的博客中&#xff0c;实体类的属性名和数据库表的字段名是一致的&#xff0c;因此能正确地查询出所需要的数据。当实体类的属性名与数据库表的字段名不一致时&#xff0c;会导致查询出来的数据为空指针。要解决这个问题就需要使用resultMap自定义映射。 使用的…...

国产精品:讯飞星火最新大模型V2.0

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…...

网络综合布线实训室方案(2023版)

综合布线实训室概述 随着智慧城市的蓬勃发展,人工智能、物联网、云计算、大数据等新兴行业也随之崛起,网络布线系统作为现代智慧城市、智慧社区、智能建筑、智能家居、智能工厂和现代服务业的基础设施和神经网络,发挥着重要作用。实践表明,网络系统故障的70%发生在布线系统,直接…...

Qt应用开发(基础篇)——文本编辑窗口 QTextEdit

一、前言 QTextEdit类继承于QAbstractScrollArea&#xff0c;QAbstractScrollArea继承于QFrame&#xff0c;用来显示富文本和纯文本的窗口部件。 框架类 QFramehttps://blog.csdn.net/u014491932/article/details/132188655滚屏区域基类 QAbstractScrollAreahttps://blog.csdn…...

NineData中标移动云数据库传输项目(2023)

近日&#xff0c;玖章算术NineData智能数据管理平台成功中标《2023年移动云数据库传输服务软件项目》&#xff0c;中标金额为406万。这标志着玖章算术NineData平台已成功落地顶级运营商行业&#xff0c;并在数据管理方面实现了大规模应用实践。 NineData中标2023移动云数据库传…...

Java面向对象三大特性之多态及综合练习

1.1 多态的形式 多态是继封装、继承之后&#xff0c;面向对象的第三大特性。 多态是出现在继承或者实现关系中的。 多态体现的格式&#xff1a; 父类类型 变量名 new 子类/实现类构造器; 变量名.方法名(); 多态的前提&#xff1a;有继承关系&#xff0c;子类对象是可以赋…...

HTTPS 握手过程

HTTPS 握手过程 HTTP 通信的缺点 通信使用明文&#xff0c;内容可能被窃听(重要密码泄露)不验证通信方身份&#xff0c;有可能遭遇伪装(跨站点请求伪造)无法证明报文的完整性&#xff0c;有可能已遭篡改(运营商劫持) HTTPS 握手过程 客户端发起 HTTPS 请求 用户在浏览器里…...

高校网站建设需求单/泉州网站建设优化

策略模式【Strategy Pattern】刘备要到江东娶老婆了&#xff0c;走之前诸葛亮给赵云&#xff08;伴郎&#xff09;三个锦囊妙计&#xff0c;说是按天机拆开解决棘手问题&#xff0c;嘿&#xff0c;还别说&#xff0c;真是解决了大问题&#xff0c;搞到最后是周瑜陪了夫人又折兵…...

网站制作模板/什么是软文文案

Golang GDB print global variable在使用GDB工具调试golang程序时&#xff0c;需要print一个全局变量&#xff0c;遇到各种报错&#xff0c;没办法打印出来&#xff0c;这里记录一下解决方法。我的包名叫“monitor”&#xff0c;全局变量名叫“DefaultDevice”&#xff0c;代码…...

安居客房产官方网站/重庆森林电影高清在线观看

昨天有学员咨询这个SolidWorks艺术立方体怎么绘制&#xff0c;他在自己绘制的过程中出现一点小问题&#xff0c;今天就给大家分享一下SolidWorks练习题&#xff0c;比较的简单&#xff0c;都是SolidWorks常规的命令练习&#xff0c;一起来看一下怎么建模吧。SolidWorks艺术立方…...

成都如何做网站/十大搜索引擎入口

没啥实质性的内容&#xff0c;纯粹的图片 布局参考“淘宝网”的会员中心&#xff0c;布局框架用的是YUI3的cssgrid 提取了bootstrap部分样式和控件&#xff0c;从按钮上能看出bootstrap的影子 对话框用的是artDialog&#xff0c;这个无需考虑&#xff0c;用了很久的控件 编辑器…...

品牌建设总要求/如何把一个关键词优化到首页

RocketMQ是阿里开源的分布式消息中间件&#xff0c;跟其它中间件相比&#xff0c;RocketMQ的特点是纯JAVA实现&#xff1b;集群和HA实现相对简单&#xff1b;在发生宕机和其它故障时消息丢失率更低。 一、RocketMQ专业术语 先讲专业术语的含义&#xff0c;后面会画流程图来更…...

wordpress 怎么传网站/seo 网站排名

Qt是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 点击获取Qt组件下载 …...