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、结构体名和表名的映射规则
- 如果结构体名没有驼峰命名,那么表名就是:结构体名小写+复数形式: 如结构体名User-->表名users
- 如果结构体名有驼峰命名,那么表名就是:大写变小写并在前面加下划线,最后加复数形式:如结构体名UserInfo-->表名user_infos
- 如有结构体名有连续的大写字母,那么表名就是:连续的大写字母变小写,驼峰前加下划线,字母变小写,最后加复数形式:如结构体名:DBUserInfo-->表名db_user_infos
- 结构体中字段名称与表中列名的映射规则同上
自定义表名
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反序列化 字符串逃逸
前言 最近在打西电的新生赛,有道反序列化的题卡了很久,今天在NSS上刷题的时候突然想到做法,就是利用字符串逃逸去改变题目锁死的值,从而实现绕过 为了研究反序列化的字符串逃逸 我们先简单的测试下 原理 <?php class escape…...

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

斯坦福大学医学院教授:几年内ChatGPT之类的AI将纳入日常医学实践
注意:本信息仅供参考,分享此内容旨在传递更多信息之目的,并不意味着赞同其观点或证实其说法。 在一项新研究中,斯坦福大学研究人员发现,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:Bash、Zsh、Ksh、Csh、Tcsh和Fish的简介2.1、Bash、Zsh、Ksh、Csh、Tcsh和Fish的特点和用途2.2、语法差异是常见Shell之间的主要区别 三、变量和环境设置的语法差异3.1、变量定义和使用的不同语法…...
Python3 基础语法
Python3 基础语法 编码 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的编码: # -*- coding: cp-1252 -*- 上述定义允许在源文件中使用 Windows-1252 字符集中的字符编码&…...

spring boot分装通用的查询+分页接口
背景 在用spring bootmybatis plus实现增删改查的时候,总是免不了各种模糊查询和分页的查询。每个数据表设计一个模糊分页,这样代码就造成了冗余,且对自身的技能提升没有帮助。那么有没有办法实现一个通用的增删改查的方法呢?今天…...
【OpenCV】OpenCV环境搭建,Mac系统,C++开发环境
OpenCV环境搭建,Mac系统,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笔记本键盘失灵处理方法
问题描述: 联想小新Pro 16新笔记本开机准备激活,到连接网络的时候就开始触控板、键盘失灵,但是有意思的是键盘的背光灯是可以调节关闭的;外接鼠标是正常可以移动的,但是只要拔掉外接鼠标再插回去的时候就不能用了&…...

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)# 关闭连接(可选) r.close()...

使用 wxPython 和 pymupdf进行 PDF 加密
PDF 文件是一种常见的文档格式,但有时候我们希望对敏感信息进行保护,以防止未经授权的访问。在本文中,我们将使用 Python 和 wxPython 库创建一个简单的图形用户界面(GUI)应用程序,用于对 PDF 文件进行加密…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...