当前位置: 首页 > 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 文件进行加密…...

会话搜索服务器实战:从架构设计到生产部署的完整指南

1. 项目概述与核心价值最近在折腾一个挺有意思的玩意儿&#xff0c;叫session_search_server。这名字乍一看有点抽象&#xff0c;但如果你做过聊天机器人、客服系统&#xff0c;或者任何需要处理多轮对话、历史记录查询的应用&#xff0c;那你肯定遇到过类似的痛点&#xff1a;…...

中性原子量子计算架构:原理、优势与应用

1. 中性原子量子计算架构概述量子计算作为后摩尔时代最具潜力的计算范式之一&#xff0c;其核心优势在于利用量子比特&#xff08;Qubit&#xff09;的叠加态和纠缠态实现并行计算。在众多物理实现方案中&#xff0c;中性原子量子架构近年来异军突起&#xff0c;展现出独特的工…...

VSCode + Cline + Codeium + OpenSpec + DeepSeek 完整配置指南

VSCode Cline Codeium OpenSpec DeepSeek 完整配置指南 &#x1f4cb; 最终方案概述 组件用途费用VSCode代码编辑器免费Codeium (Windsurf)Tab 补全 生成注释免费ClineAI Agent&#xff08;复杂任务、多文件操作&#xff09;免费OpenSpec规范驱动开发&#xff08;复杂功…...

Midjourney V6 acrylic paint提示词工程:从模糊描述到精准输出的12个专业级Prompt模板(含色彩层厚/笔触硬度/画布纹理三重控制)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Midjourney V6丙烯画风格的核心演进与底层渲染机制 Midjourney V6 对丙烯画&#xff08;Acrylic Painting&#xff09;风格的建模已脱离早期依赖纹理叠加与后处理滤镜的粗粒度模拟&#xff0c;转向基于…...

为什么92%的AI企业还没部署TEE for AI?,20年系统安全专家亲历的4类认知盲区与2026合规倒计时应对清单

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI原生可信执行环境&#xff1a;2026奇点智能技术大会TEE for AI 在2026奇点智能技术大会上&#xff0c;TEE for AI&#xff08;AI-Native Trusted Execution Environment&#xff09;正式成为下一代AI…...

CTR预估实战:DeepFM模型在Criteo数据集上的调参避坑指南(附PyTorch代码)

DeepFM模型在Criteo数据集上的调优实战&#xff1a;从79%到81% AUC的进阶之路 当CTR预估模型的AUC指标卡在79%的瓶颈时&#xff0c;真正的挑战才刚刚开始。本文将以工业级数据集Criteo为战场&#xff0c;分享如何通过系统化的调参策略和特征工程技巧&#xff0c;将DeepFM模型的…...

计算机毕业设计:Python智慧医疗数据可视化与疾病预测系统 Flask框架 随机森林 机器学习 疾病数据 智慧医疗 深度学习(建议收藏)✅

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ > &#x1f345;想要获取完整文章或者源码&#xff0c;或者代做&#xff0c;拉到文章底部即可与…...

CSS 混合模式完全指南

CSS 混合模式完全指南 引言 CSS 混合模式&#xff08;Blend Modes&#xff09;是一种强大的视觉效果工具&#xff0c;它允许你控制多个元素或图层如何混合在一起。本文将深入探讨各种混合模式的用法和高级技巧。 混合模式类型 基础混合模式 模式效果描述normal默认模式&#xf…...

Excel+ChatGPT函数实战:零代码实现语义理解与智能数据处理

1. 为什么说“在Excel里直接调用ChatGPT”不是噱头&#xff0c;而是真正在改写数据处理的工作流 你有没有过这样的时刻&#xff1a;盯着Excel表格里一列杂乱的客户反馈&#xff0c;想快速标出哪些是投诉、哪些是表扬&#xff0c;却卡在手动翻查、复制粘贴、反复试错公式上&…...

开源工具phantom-secrets:轻量级秘密管理方案,助力安全开发与CI/CD

1. 项目概述&#xff1a;一个用于秘密管理的开源工具 最近在整理自己的开发环境时&#xff0c;发现各种API密钥、数据库密码、配置文件里的敏感信息散落在各个角落&#xff0c;管理起来非常头疼。用文本文件记不安全&#xff0c;用密码管理器又觉得和开发流程有点脱节。直到我发…...