赞
踩
即Object-Relational Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。
gorm 是 go语言的一个orm框架,golang写的,开发人员友好的orm库、
go get github.com/jinzhu/gorm
// 下面这个 有时候需要, 有时候不需要
go get github.com/jinzhu/gorm/dialects/mysql@v1.9.16
特别是这里导入的第二包,可以不用,但是不能没有
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql" // 引入mysql驱动
)
func main() {
// 1. 连接数据库。。
// 第一个参数: 指定要连接的数据库
// 第二个参数: 指的是数据库的设置信息: 用户名:密码@tcp(ip:端口号)/数据库名字?charset = utf8 & parseTime = True & loc = Local
// charset = utf8 设置字符集
// parseTime = True 为了处理time.Time
// loc = Local 时区设置,与本地时区保持一致
db, err := gorm.Open("mysql", "root:zhubao@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
if err != nil {
panic(err) // 如果出错,后续代码 没有必要执行,让程序中断
}
// 数据库资源的释放:
defer db.Close()
}
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/redis/go-redis/v9"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var Conn *gorm.DB
var Rdb *redis.Client
func NewMysql() {
my := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local","root","zhubao","127.0.0.1:3306","vote")
conn ,err := gorm.Open(mysql.Open(my), &gorm.Config{})
if err != nil {
fmt.Printf("err:%s\n", err)
panic(err)
}
Conn = conn
}
// 定义结构体:
type User struct {
Age int
Name string
}
// 创建表:通常情况下,数据库中新建的表的名字是结构体名字的小写复数形式,例如,结构体User,表名 users
db.CreateTable(&User{})
// 这种情况,可以 自己设定表的名字。
db.Table("user").CreateTable(&User{})
// 通过 &User{} 指定结构体,删除对应的表
db.DropTable(&User{})
// 通过指定 表名 删除对应的表
db.DropTable("users")
flag := db.HasTable(&User{})
flag1 := db.HasTable("user")
fmt.Println(flag, flag1) // 输出 true true
type User struct {
Age int
Name string
}
db.CreateTable(&User{})
func (User) TableName() string { // 给对应结构体返回的表 命名
return "user"
}
增加 : 要先创建对应表结构的 结构体,然后创建一个表映射函数,确定是哪个表,然后进行 添加
可以用 RecordNotFound 函数来确定查询结果是否为空
// 定义结构体:
type User struct {
Age int
Name string
}
func main() {
db, err := gorm.Open("mysql", "root:zhubao@tcp(localhost:3306)/testgormcharset=utf8&parseTime=True&loc=Local")
if err != nil {
panic(err) // 如果出错,后续代码 没有必要执行,让程序中断
}
// 数据库资源的释放:
defer db.Close()
// 增加
db.Create(&User{
Age: 18,
Name: "张三",
})
// 查询数据 : 第一个参数: 查询出来的数据的载体:
var myuser User
db.First(&myuser, "age = ?", 19)
fmt.Println(myuser)
// 更新数据
db.Model(&myuser).Update("age", 626)
db.Model(&myuser).Update("name", "菲菲")
//删除数据
db.Delete(&myuser)
}
func (User) TableName() string {
return "user"
}
在模型中添加 gorm.Mode匿名字段,就自动会在生成的数据库表中添加四个字段
ID : 主键自增长
CreatedAt : 用于存储记录的创建时间
UpdatedAt : 用于存储记录的修改时间
DeletedAt : 用于存储记录的删除时间
type Student struct {
gorm.Model
Age int
Name string
}
db.CreateTable(&Student{}) // 这样就创建出来了下面图片这样的表
通过结构体标签gorm实现对 一些字段的约束
(1) - : 忽略,不映射这个字段 gorm:"-"
(2) primary_key:主键 eg: gorm:"primary_key"
(3)AUTO_INCREMENT:自增 eg: 'gorm:“AUTO_INCREMENT”
(4) not null:不为空,默认为空 eg: 'gorm:“not null”
(5)index: 索引 eg:gorm:"index"
创建索引并命名: eg: gorm:"unique_index"
(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)type : 设置sql类型 eg:gorm:"type:int"
type Student struct {
Id int `gorm:"primary_key;AUTO_INCREMENT"`
Age int `gorm:"not null"`
Name string `gorm:"index:uname"` // 索引值可以自定义
DECS string `gorm:"-"`
Stuid int `gorm:"unique"`
Class string `gorm:"column:grade"`
Lover string `gorm:"size:25"`
Loser string `gorm:"type:int"`
}
type User struct {
UserId int `gorm:"primary_key;AUTO_INCREMENT"`
Age int
Name string
// 指定外键
IID int
}
type UserInfor struct {
InforID int `gorm:"primary_key;AUTO_INCREMENT"` // 添加数据的时候,不用管主键
Pic string
Address string
Email string
// 关联关系
User User `gorm:"ForeignKey:IID;AssociationForeignKey:InforID"`
}
infor := UserInfor{
Pic: "imgload",
Address: "河南省",
Email: "123456@qq.com",
User: User{
Age: 18,
Name: "张三",
},
}
先First查询,再Associatiion查询
// 关联查询操作: (关联关系在UserInfor表中,所以从UserInfor入手)
var userinformation UserInfor
// 如果只是执行下面这步操作, 那么关联的User信息时查询不到了
db.First(&userinformation, "infor_id=?", 1)
fmt.Println(userinformation) // 输出:{1 imgload 河南省 123456@qq.com {0 0 0}}
// 如果想要查询到 User相关内容,则应该:
// Model参数: 要查询的表数据,Association参数:关联到的具体的模型: 模型名字为 User (字段名字)
// Find 参数: 查询的结果要存放在什么字段中。 这里是 存在到了userinformation 中的User字段
db.Model(&userinformation).Association("User").Find(&userinformation.User)
fmt.Println(userinformation)
感觉比较方便
var userinfor1 UserInfor
// 查询 address = 河南省 的数据放入到 userinfor1中,并且查询中 要关联User表
db.Preload("User").Find(&userinfor1, "address = ?", "河南省")
fmt.Println(userinfor1)
这种情况下,是将关联表的数据,单独查出来
var userinfor2 UserInfor
db.First(&userinfor2, "address=?", "河南省")
fmt.Println(userinfor2) // 输出 {1 imgload 河南省 123456@qq.com {0 0 0}}
var user1 User
db.Model(&userinfor2).Related(&user1, "User")
fmt.Println(user1) // 输出 {1 18 张三 1}
fmt.Println(userinfor2) // 输出 {1 imgload 河南省 123456@qq.com {0 0 0}}
// 先获取数据
var userinfor5 UserInfor
db.Preload("User").Find(&userinfor5, "address = ?", "河南省")
fmt.Println(userinfor5) // 输出 {1 图片路径 河南省 123456@qq.com {1 88 张三 1}}
// 在进行更新 如果需要修改关联表这里需要 .user . 如果不需要修改关联表,则不修改 .user
db.Model(&userinfor5.User).Update("age", 18)
fmt.Println(userinfor5) // 输出 {1 图片路径 河南省 123456@qq.com {1 18 张三 1}}
先查询再删除
目前是只能删除整个表的信息,没有发现怎么删除某个字段的信息(可以尝试进行字段修改为空吗? “ “ 有待后续发现!)
var userinfor5 UserInfor
db.Preload("User").Find(&userinfor5, "address = ?", "地址")
fmt.Println(userinfor5)
db.Delete(&userinfor5.User)
fmt.Println(userinfor5)
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql" // 引入mysql驱动
)
type Author struct {
AID int
Name string
Age int
Sex string
// 关联关系
Article []Article `gorm:"ForeignKey:AuId;AssociationForeignKey:AID"`
}
type Article struct {
ArID int
Title string
Content string
Desc string
// 设置外键:
AuId int
}
func main() {
db, err := gorm.Open("mysql", "root:zhubao@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
db.CreateTable(&Author{})
db.CreateTable(&Article{})
person := Author{
Name: "张三",
Age: 18,
Sex: "男",
Article: []Article{
{
Title: "HTML入门",
Content: "内容1****",
Desc: "非常好1***",
},
{
Title: "CSS入门",
Content: "内容2***",
Desc: "非常好2****",
},
},
}
db.Create(&person)
}
查询方式和上面一对一关系的查询基本一样。
var authors Author
db.First(&authors, "name = ?", "张三")
fmt.Println(authors)
db.Model(&authors).Association("Article").Find(&authors.Article)
fmt.Println(authors)
var authors Author
db.Preload("Article").Find(&authors, "a_id = ?", 0)
目前仅这种方法没报错!实现过程可参考上面一对一关系中的查询
var authors Author
db.First(&authors, "name=?", "张三")
fmt.Println(authors)
var aubooks Article
db.Model(&authors).Related(&aubooks, "Article")
fmt.Println(aubooks)
先查询出来再进行修改
var authors Author
db.Preload("Article").Find(&authors, "name = ?", "张三")
fmt.Println(authors)
db.Model(&authors.Article).Where("ar_id = ?", 2).Update("title", "JS入门")
先查询再删除
db.Preload("Article").Find(&authors, "name = ?", "张三")
db.Where("ar_id = ?", 2).Delete(&authors.Article)
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql" // 引入mysql驱动
)
type Student struct {
SId int `gorm:"primary_key"`
SNo int
Name string
Sex string
Age int
Course []Course `gorm:"many2many:Student2Course"`
}
type Course struct {
CId int `gorm:"primary_key"`
CName string
TeacherName string
Room string
}
func main() {
db, err := gorm.Open("mysql", "root:zhubao@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
db.CreateTable(&Student{})
db.CreateTable(&Course{})
stu := Student{
SNo: 1001,
Name: "张三",
Sex: "男",
Age: 18,
Course: []Course{
{
CName: "数据结构",
TeacherName: "老王",
Room: "0#508",
},
{
CName: "计算机网络",
TeacherName: "老张",
Room: "0#608",
},
},
}
db.Create(&stu)
}
和上面两种关系操作步骤一样,可参考上面!
像下面这四种方法,其中 ()中那么1也可以换成具体查询条件。比如(&stu,“name = ?”,“张三”)
将查询出来的结果,升序排列 (只能查出来第一条数据)
var stu Student
// SELECT * FROM `students` WHERE (`students`.`id` = 1) ORDER BY `students`.`id` ASC LIMIT 1
db.Debug().First(&stu, 1)
fmt.Println(stu)
根据指定条件进行查询,但是只能查出来第一条数据
如果没有被查询的数据,那么就会自动添加一条数据
user := Student{
Age: 18,
}
var stu Student
// SELECT * FROM `students` WHERE (`students`.`age` = 18) ORDER BY `students`.`id` ASC LIMIT 1
db.Debug().FirstOrCreate(&stu, user)
fmt.Println(stu)
这是将查询结构降序排列,只能查第一个
//SELECT * FROM `students` WHERE (`students`.`id` = 1) ORDER BY `students`.`id` DESC LIMIT 1
db.Debug().Last(&stu, 1)
fmt.Println(stu)
直接查出结果,不进行排序 。 只能查第一个
// SELECT * FROM `students` WHERE (`students`.`id` = 1) LIMIT 1
db.Debug().Take(&stu, 1)
fmt.Println(stu)
这个是根据条件查的。 考虑一下是否能一次查出来多条数据?
// SELECT * FROM `students` WHERE (age = 18)
db.Debug().Find(&stu, "age = ?", 18)
fmt.Println(stu)
根据指定条件进行查询
// SELECT * FROM `students` WHERE (id = 1) LIMIT 1
db.Debug().Where("id = ?", 1).First(&stu)
fmt.Println(stu)
查询指定字段
// SELECT name,age FROM `students` WHERE (id = 1) LIMIT 1
db.Debug().Select("name,age").Where("id = ?", 1).First(&stu)
fmt.Println(stu)
只能插入一条数据,不能批量操作
db.Debug().Create(&Student{
Name: "老八",
Sex: "男",
Age: 66,
})
也是插入一条数据,用法感觉和上面的Create一样。
db.Debug().Save(&Student{
Name: "王凤霞",
Sex: "女",
Age: 22,
})
先查询后修改
var user Student
db.Where("id = ? ", 1).First(&user)
db.Model(&user).Update("age", 19)
直接修改 (实质还是在查询后修改)
db.Where("id = ?", 1).First(&user).Update("age", 18)
直接一次修改多个(实质还是先查询后修改)
db.Where("id =?", 1).First(&user).Update(Student{ // 传入结构体实例
Age: 25,
Name: "老八",
})
这个是用Map键值对的方法修改多个数据,但是目前没有发现与上面那个有什么区别
db.Where("id =?", 1).First(&user).Update(map[string]interface{}{
"age": 50,
"name": "小花花",
})
(1)先查询 后 删除
db.Where("id = ?", 1).First(&user)
db.Delete(&user)
(2)根据指定条件直接删除
db.Where("id = ?", 3).Delete(&user)
not后面那个括号中 可以添加多个判断条件。 (多个判断条件通过结构体形式传送)
var users []Student
db.Not("id = ?", 2).Find(&users) // 查询所有 id 不等于2的
fmt.Println(users)
可以同时并列多个条件。
db.Where("id = ?", 4).Or("id = ?", 5).Find(&users)
让查询结果排序. desc是降序,asc是升序
db.Where("sex = ?", "女").Order("id desc").Find(&users)
limit是限制查询数量的,就比如这个sql语句只能查出来两个记录
db.Limit(2).Find(&users)
设置偏移量,就比如正常数据都是从第一条开始的,这里可以设置偏移,让从第二条或者第三条等等开始查
注意:Offset必须和Limit结合使用
db.Offset(2).Limit(1).Find(&users) // 设置偏移量为2,并且仅查一条数据
这个就是将查询的结果全部复制给另一个结构体。下面这个例子是将查询出来的结果传给demo。
但是 这个代码目前不生效 不知道为什么!!!
type Demo struct {
name string
sex string
age int
}
var demo Demo
var user Student
db.Where("id = ?", 2).Find(&user).Scan(&demo)
fmt.Println(user)
fmt.Println(demo)
就是记录一下查询结果的数量
db.Find(&users).Count(&count)
将查询出来的数据, 通过扫描传给一个新的结构体 理解的不是太透彻!!!
type NewUser struct {
User_id int
Name string
Infor_id int
Address string
}
var newUser []NewUser
var users []User
db.Debug().Select("users.user_id,users.name,user_infos.infor_id,user_infos.address").Joins("left join user_infos on users.i_id = user_infos.infor_id").Find(&users).Scan(&newUser)
fmt.Println(users)
fmt.Println(newUser)
开启全局 类似于 debug的功能,每次执行都能看见sql语句
db.LogMode(true)
var users []User
db.Raw("select * from users ").Find(&users)
fmt.Println(users)
// 增加
db.Exec("insert into users(user_id,age,name,i_id) values (?,?,?,?)", 6, 30, "王老万", 2)
// 修改
db.Exec("update users set name=? where user_id = ?", "小林子", 6)
// 删除
db.Exec("delete from users where user_id = ?", 6)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。