crud 指的creat retrieve update delete增加,查询,更新,删除四种操作
ORM,对象关系映射,是一种框架格式,显示了映射关系
迁移
创建表,查看表,重命名表,删除表
type User struct {
ID int
Name string
}
func main() {
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: "root:123456@tcp(127.0.0.1:3306)/db1?charset=utf8mb4&parseTime=True&loc=Local",
}), &gorm.Config{
SkipDefaultTransaction: false, //是否跳过事务事件,事务事件使得数据更安全
NamingStrategy: schema.NamingStrategy{
TablePrefix: "t_", //表 添加前缀
SingularTable: false, //表名设置为单数
},
DisableForeignKeyConstraintWhenMigrating: true, //数据库采用逻辑外键,访问速度更快
})
if err != nil {
fmt.Println(err)
}
//_ = db.AutoMigrate(&User{}) //自动迁移
M := db.Migrator() //手动迁移
//M.CreateTable(&User{}) //创建表
//fmt.Println(M.HasTable(&User{})) //查看表是否存在,("t_user")用表名的形式也可以 但是最好用结构体的形式,方便清楚
//fmt.Println(M.DropTable(&User{})) //删除表
if M.HasTable(&User{}) {
M.RenameTable(&User{}, "a_users") //如果存在表就改名
} else {
M.CreateTable(&User{}) //不存在就创建表
}
}
CRUD
创建
func CreatedTest() { //首字母大写,对其他目录可见
//创建单条数据
//GlobalDb.Create(&TestUser{Name: "景之", Age: 20}) //记得设置数据库编码格式为utf8
//GlobalDb.Omit("Name").Create(&TestUser{Name: "景之", Age: 20}) 跳过名字创建Age
//GlobalDb.Select("Name").Create(&TestUser{Name: "景之", Age: 20}) 只创建Name
//创建多条数据
GlobalDb.Create(&[]TestUser{
{Name: "景之", Age: 20},
{Name: "郭龙", Age: 21},
{Name: "弛子", Age: 20},
{Name: "小艺", Age: 20},
})
}
查询
以下查的好多都是单条数据,如果是要查询多条数据也很简单,只需要
var Users TestUser
//查询语句
GlobalDb.Find(&Users)
fmt.Println(Users)
//如此就可,就是换成了切片
查询单个对象
db.First(&user)
db.Take(&user)
db.Last(&user)
result := db.First(&user)
result.RowsAffected // 返回找到的记录数 比如说咱要找叫做小艺的同学,那么学校可能有好几个人叫小艺,几个就是记录数
查询map型切片和结构体
func TestFind() {
//查询结构体,map型切片
//var result = make(map[string]interface{})
//GlobalDb.Model(&TestUser{}).First(&result)
//fmt.Println(result)
var User TestUser
//根据主键排序查询
//GlobalDb.Model(&TestUser{}).Take(&User)
//GlobalDb.Model(&TestUser{}).First(&User)
GlobalDb.Model(&TestUser{}).Last(&User)
fmt.Println(User)
}
主键检索
//直接检索到第几条数据
db.First(&user, 10)
// SELECT * FROM users WHERE id = 10;
db.First(&user, "10")
// SELECT * FROM users WHERE id = 10;
//多条检索查询
db.Find(&users, []int{1,2,3})
// SELECT * FROM users WHERE id IN (1,2,3);
查询总共有几条数据
var Users []TestUser //加上[] 就是切片,包含所有数据否则TestUser只是代表找到这个表(表就是结构体)
//查询所有对象
res := GlobalDb.Find(&Users) //返回error 和 RowsAffected
fmt.Println(res.RowsAffected) //输出有几条数据
//打印所有数据
var Users []TestUser
//找到所有对象
GlobalDb.Find(&Users)
fmt.Println(Users)
条件查询
//根据string字段查询
var User TestUser
//GlobalDb.Where("name = ?", "景之").First(&User)
GlobalDb.Where("name = ? AND age = 20", "景之").First(&User)
//GlobalDb.Where("name = ? AND age >= ?", "景之", "19").Find(&Users) //???
fmt.Println(User)
//官网还有好多,这只是最基本的用法
//<>排除这个的数据
//LIKE模糊,在条件位置加%%,例如%j%
内联
//string形式
GlobalDb.First(&User, "id = ?", 5)
//结构体形式
GlobalDb.First(&User, TestUser{Name: "jz"})
//map形式
GlobalDb.First(&User, map[string]interface{}{"Name": "jz"})
往下基本看文档自己都会
高级查询
智能字段,自定义api,
type UserInfo struct {
//自定义智能字段
Name string
Age uint8
}
func TestFind() {
var u UserInfo
GlobalDb.Model(&TestUser{}).Where("Name LIKE ?", "%小%").Find(&u)
fmt.Println(u)
}
//结果是:{小艺 20}
更新
形式上和查询基本一样,最后的改为下边的三个关键词,对应即可
func TestUpdate() {
//update 只更新选择的字段
//updates 跟新所有字段,形式1 map 形式2 结构体,结构体零值不参与更新
//save everything更新
GlobalDb.Model(&TestUser{}).Where("Name = ?", "jz").Update("name", "jz大帅哥")
}
删除
func TestDelete() {
var user []TestUser
//Unscoped真的删除这一行,没有Unscoped是软删除
//gorm.Model含有gorm.deletedat,拥有软删除的能力
//拥有软删除能力的模型调用 Delete 时,记录不会被数据库。但 GORM 会将 DeletedAt 置为当前时间, 并且你不能再通过普通的查询方法找到该记录。
GlobalDb.Unscoped().Where("namE", "jz大帅哥").Delete(&user) //name这种条件都是大小写不太区分的
}
原生
GlobalDb.Row(原生语句)
关联
belongsTo
belongs to
会与另一个模型建立了一对一的连接
这种模型的每一个实例都“属于”另一个模型的一个实例
//GirlGod可以有很多个User
type User struct {
gorm.Model
Name string
GirlGodID int
GirlGod GirlGod
}
type GirlGod struct {
ID int
Name string
}
预加载
var girl GirlGod
GlobalDb.Preload("Dog").First(&girl, 2)
fmt.Println(girl)
//女神出门带着添狗,preload预加载,把天狗带上
Has One
// User 有一张 CreditCard,UserID 是外键
type User struct {
gorm.Model
GirlGod GirlGod // 追随者有了女神
}
type GirlGod struct {
gorm.Model
Number string
UserID uint //女神带有追随着
}
Has Many
和has one 区别就是,把Dog变成了Dogs切片
type Dog struct {
gorm.Model
Name string
GirlGodID uint //狗链子
}
type GirlGod struct {
gorm.Model
Name string
Dogs []Dog //拿到狗链子
}
func One2one() {
d1 := Dog{
Model: gorm.Model{
ID: 1,
},
Name: "汪汪1号",
}
d2 := Dog{
Model: gorm.Model{
ID: 2,
},
Name: "汪汪2号",
}
g := GirlGod{
Model: gorm.Model{
ID: 1,
},
Name: "女神",
Dogs: []Dog{d1, d2}, //汪汪1号和汪汪2号都在追女神 ID都是1
}
GlobalDb.Create(&g)
查询
//预加载全部
var girl GirlGod
GlobalDb.Preload("Dogs").First(&girl)
fmt.Println(girl)
//选择性预加载。内联式查询
GlobalDb.Preload("Dogs", "name = ?", "汪汪1号").First(&girl)
//当条件很多时候,可以用个函数
GlobalDb.Preload("Dogs", func(db *gorm.DB) *gorm.DB{
return db.Where("name = ?", "汪汪1号")
}).First(&girl)
多态
- 支持一对一和一对多
type Jiazi struct {
ID uint
Name string
Xiaofengche Xiaofengche `gorm:"polymorphic:Owner;"`
}
type Yujie struct {
ID uint
Name string
Xiaofengche Xiaofengche `gorm:"polymorphic:Owner;"`
}
type Xiaofengche struct {
ID uint
Name string
OwnerType string
OwnerID uint
}
func Polymorphic() {
GlobalDb.Create(&Jiazi{Name: "夹子", Xiaofengche: Xiaofengche{
Name: "小风车",
}})
GlobalDb.Create(&Yujie{Name: "御姐", Xiaofengche: Xiaofengche{
Name: "大风车",
}})
}
关联外键
关联id
type Jiazi struct {
ID uint
Name string
Xiaofengche []Xiaofengche `gorm:"foreignKey:JiaziName"` //还是关联的id,只不过起的名字叫jiazi_name
}
type Xiaofengche struct {
ID uint
Name string
JiaziName string
}
func Polymorphic() {
GlobalDb.AutoMigrate(&Jiazi{}, &Xiaofengche{})
GlobalDb.Create(&Jiazi{Name: "大夹子", Xiaofengche: []Xiaofengche{
{Name: "小风车1"},
{Name: "小风车2"},
}})
}
关联Name
- 把关联语句换为下边这个
- references引用指向自己,大夹子
`gorm:"foreignKey:JiaziName;references:Name"`
事务
单层普通事务
type TMG struct {
ID uint
Name string
}
func TestTransaction() {
flag := false
GlobalDb.AutoMigrate(&TMG{})
GlobalDb.Transaction(func(tx *gorm.DB) error {
tx.Create(&TMG{Name: "汉子"})
tx.Create(&TMG{Name: "高大威猛"})
fmt.Println("上边执行过了")
if flag {
return nil
} else {
return errors.New("躲开汉子")
}
})
}
嵌套事务
func TestTransaction() {
GlobalDb.AutoMigrate(&TMG{})
GlobalDb.Transaction(func(tx *gorm.DB) error {
tx.Create(&TMG{Name: "高大威猛"})
tx.Transaction(func(tx *gorm.DB) error {
tx.Create(&TMG{Name: "汉子"})
return errors.New("躲开了汉子")
})
fmt.Println("执行高大威猛出现,汉子不出现")
return nil
})
}
手动事务
//手动事务
tx := GlobalDb.Begin()
tx.Create(&TMG{Name: "汉子"})
tx.Create(&TMG{Name: "高大威武"})
tx.Commit()
SavePoint、RollbackTo
tx := GlobalDb.Begin()
tx.Create(&TMG{Name: "汉子"})
tx.SavePoint("duo")
tx.Create(&TMG{Name: "高大威武"})
tx.RollbackTo("duo")
tx.Commit()
总结:写的有点乱了,我尽量给他整清楚了,因为我也是看b站up主+看文档学习有点乱,但是我真的尽量整清楚了。