当前位置: 首页 > 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 请求 用户在浏览器里…...

docker之Consul环境的部署

目录 一.Docker consul的介绍 1.1template模板(更新) 1.2registrator&#xff08;自动发现&#xff09; 1.3agent(代理) 二.consul的工作原理 三.Consul的特性 四.Consul的使用场景 五.搭建Consul的集群 5.1需求 5.2部署consul 5.3主服务器[192.168.40.20] 5.4client部署&…...

服务机器人,正走向星辰大海

大数据产业创新服务媒体 ——聚焦数据 改变商业 国内机器人联盟&#xff08;IFR&#xff09;将机器人划分为工作机器人、服务机器人、特种机器人三类。服务机器人广泛应用于餐饮场景、酒店场景&#xff0c;早已构成一道靓丽的风景。行业数据显示&#xff0c; 作为服务机器人发…...

SciencePub学术 | 计算机及交叉类重点SCIE征稿中

SciencePub学术 刊源推荐: 计算机及交叉类重点SCIE征稿中&#xff01;信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 计算机土地类重点SCIE 【期刊简介】IF&#xff1a;1.0-1.5&#xff0c;JCR4区&#xff0c;中科院4区&#xff1b; 【版面类型】正刊…...

Java面试题--SpringCloud篇

一、Spring Cloud 1. 什么是微服务架构&#xff1f; 微服务架构就是将单体的应用程序分成多 个应用程序&#xff0c;这多个应用程序就成为微服 务&#xff0c;每个微服务运行在自己的进程中&#xff0c;并 使用轻量级的机制通信 这些服务围绕业务能力来分&#xff0c;并通过自…...

【linux】常用的互斥手段及实例简述

文章目录 10. 原子变量(atomic_t)20. 自旋锁(spinlock_t)21. 读写锁(rwlock_t)22. 顺序锁(seqlock_t) 10. 原子变量(atomic_t) 头文件 #include <linux/types.h> // -> <linuc/atomic.h> // -> <asm-generic/atomic64.h>结构体 /* 32bit */ typedef …...

STM32 F103C8T6学习笔记12:红外遥控—红外解码-位带操作

今日学习一下红外遥控的解码使用&#xff0c;红外遥控在日常生活必不可少&#xff0c;它的解码与使用也是学习单片机的一个小过程&#xff0c;我们将通过实践来实现它。 文章提供源码、测试工程下载、测试效果图。 目录 红外遥控原理&#xff1a; 红外遥控特点&#xff1a; …...

linux 环境收集core文件步骤

Linux环境下进程发生异常而挂掉&#xff0c;通常很难查找原因&#xff0c;但是一般Linux内核给我们提供的核心文件&#xff0c;记录了进程在崩溃时候的信息&#xff0c;在C语言类的大型项目中&#xff0c;有助于深入定位。其配置流程如下&#xff1a; 1 查看生成core文件开关是…...

Git企业开发控制理论和实操-从入门到深入(一)|为什么需要Git|Git的安装

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总https://blog.csdn.net/yu_cblog/cate…...

上篇——税收大数据应用研究

财税是国家治理的基础和重要支柱&#xff0c;税收是国家治理体系的重要组成部分。我们如何利用税收数据深入挖掘包含的数据价值&#xff0c;在进行数据分析&#xff0c;提升税收治理效能&#xff0c;推进税收现代化。 1. 定义与特点 对于“大数据”&#xff08;Big data&#…...

疲劳驾驶检测和识别4:C++实现疲劳驾驶检测和识别(含源码,可实时检测)

疲劳驾驶检测和识别4&#xff1a;C实现疲劳驾驶检测和识别(含源码&#xff0c;可实时检测) 目录 疲劳驾驶检测和识别4&#xff1a;C实现疲劳驾驶检测和识别(含源码&#xff0c;可实时检测) 1.疲劳驾驶检测和识别方法 2.人脸检测方法 3.疲劳驾驶识别模型(Python) &#xf…...

Android WakefulBroadcastReceiver的使用

WakefulBroadcastReceiver 是一种特殊类型的广播接收器&#xff0c;为应用创建和管理 PARTIAL_WAKE_LOCK 。 简单来说&#xff0c; WakefulBroadcastReceiver 是持有系统唤醒锁的 BroadcastReceiver &#xff0c;用于执行需要保持CPU运转的场景。 注册 注册 Receiver &#…...

python知识:什么是字符编码?

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 我们的MySQL使用latin1的默认字符集&#xff0c; 也就是说&#xff0c;对汉字字段直接使用GBK内码的编码进行存储&#xff0c; 当需要对一些有汉字的字段进行拼音排序时&#xff08;特别涉及到类似于名字这样的字段时…...

Vue2中使用Pinia

Vue2中使用Pinia 1.初始化配置 # main.jsimport Vue from vue import App from ./App.vue import pinia from ./stores/index import { PiniaVuePlugin } from piniaVue.use(PiniaVuePlugin)new Vue({render: h > h(App),pinia, }).$mount(#app)2.模块化开发 新建stores文…...

Docker关于下载,镜像配置,容器启动,停止,查看等基础操作

系列文章目录 文章目录 系列文章目录前言一、安装Docker并配置镜像加速器二、下载系统镜像&#xff08;Ubuntu、 centos&#xff09;三、基于下载的镜像创建两个容器 &#xff08;容器名一个为自己名字全拼&#xff0c;一个为首名字字母&#xff09;四、容器的启动、 停止及重启…...

穿越网络迷雾的神奇通道 - WebSocket详解

WebSocket&#xff0c;作为一项前端技术&#xff0c;已经成为现代Web应用不可或缺的一部分。本文将深入解析WebSocket&#xff0c;介绍其工作原理和用途&#xff0c;并通过简单的代码示例&#xff0c;让你对这个神奇的网络通信协议有更深入的了解。 WebSocket是什么&#xff1…...

无脑入门pytorch系列(五)—— nn.Dropout

本系列教程适用于没有任何pytorch的同学&#xff08;简单的python语法还是要的&#xff09;&#xff0c;从代码的表层出发挖掘代码的深层含义&#xff0c;理解具体的意思和内涵。pytorch的很多函数看着非常简单&#xff0c;但是其中包含了很多内容&#xff0c;不了解其中的意思…...

Python土力学与基础工程计算.PDF-压水试验

Python 求解代码如下&#xff1a; 1. import math 2. 3. # 输入参数 4. L 2.0 # 试验段长度&#xff0c;m 5. Q 120.0 # 第三阶段计算流量&#xff0c;L/min 6. p 1.5 # 第三阶段试验段压力&#xff0c;MPa 7. r0 0.05 # 钻孔半径&#xff0c;m 8. 9. # 计算透…...

Linux入门

一、安装相关软件 1.下载vmware (很容易下载,搜一下官网 ) 在cmd敲入 ncpa.cpl &#xff0c;查看是否有vmware 2.下载centos 下面是镜像源网站&#xff0c;当然你可以选择其他的镜像源&#xff0c;像清华镜像源和阿里镜像源。 Index of /centos/7.9.2009/isos/x86_64/ | …...

适合国内用户的五款ChatGPT插件

众所周知使用ChatGPT3.5需要使用魔法且不稳定&#xff0c;订阅ChatGPT4.0每月需要支付20美元&#xff0c;并且使用次数有限制。对于那些不想每年花费240美元&#xff08;超过1500元人民币&#xff09;来使用GPT4.0的朋友们来说&#xff0c;还有别的办法吗&#xff1f; 答案是&…...

Dubbo Spring Boot Starter 开发微服务应用

环境要求 系统&#xff1a;Windows、Linux、MacOS JDK 8 及以上&#xff08;推荐使用 JDK17&#xff09; Git IntelliJ IDEA&#xff08;可选&#xff09; Docker &#xff08;可选&#xff09; 项目介绍 在本任务中&#xff0c;将分为 3 个子模块进行独立开发&#xff…...