CRUD
增(创建记录)
package main
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
//1.定义模型
type User struct {
ID int64
Name string `gorm:"default:'无名'"` //当没有设置名字的时候存默认名字
Age int64
}
func main() {
//连接MySQL数据库
db, err := gorm.Open("mysql", "root:123456@(localhost:3306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
if err!= nil{
panic(err)
}
defer db.Close()
//2.把模型与数据库中的表对应起来
db.AutoMigrate(&User{})
// 3.创建
u := User{Name: "jiaojiao",Age: 18} //在代码层面创建一个User对象
fmt.Println(db.NewRecord(&u)) //判断主键是否为空 true
db.Create(&u) // 在数据库中创建了一条 数据
fmt.Println(db.NewRecord(&u)) // 判断主键是否为空 false
}
使用指针方式实现零值存入数据库
// 使用指针
type User struct {
ID int64
Name *string `gorm:"default:'小王子'"`
Age int64
}
user := User{Name: new(string), Age: 18))}
db.Create(&user) // 此时数据库中该条记录name字段的值就是''
使用Scanner/Valuer接口方式实现零值存入数据库
// 使用 Scanner/Valuer
type User struct {
ID int64
Name sql.NullString `gorm:"default:'小王子'"` // sql.NullString 实现了Scanner/Valuer接口
Age int64
}
user := User{Name: sql.NullString{"", true}, Age:18} //true表示虽然是空字符串但是有值
db.Create(&user) // 此时数据库中该条记录name字段的值就是''
查(查询)
一般查询
// 根据主键查询第一条记录
db.First(&user)
//// SELECT * FROM users ORDER BY id LIMIT 1;
// 随机获取一条记录
db.Take(&user)
//// SELECT * FROM users LIMIT 1;
// 根据主键查询最后一条记录
db.Last(&user)
//// SELECT * FROM users ORDER BY id DESC LIMIT 1;
// 查询所有的记录
db.Find(&users)
//// SELECT * FROM users;
// 查询指定的某条记录(仅当主键为整型时可用)
db.First(&user, 10)
//// SELECT * FROM users WHERE id = 10;
package main
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
//1.定义模型
type User struct {
gorm.Model
Name string
Age int64
}
func main() {
//连接MySQL数据库
db, err := gorm.Open("mysql", "root:123456@(localhost:3306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
if err!= nil{
panic(err)
}
defer db.Close()
//2.把模型与数据库中的表对应起来
db.AutoMigrate(&User{})
// 3.创建
//u1 := User{Name: "jiaojiao",Age: 18} //在代码层面创建一个User对象
//db.Create(&u1)
//u2 := User{Name: "jiapeng",Age: 28} //在代码层面创建一个User对象
//db.Create(&u2)
//4.查询
//var user User //声明模型结构体类型变量user
user := new(User) //此时user是一个User类型的指针
db.First(user) //查询第一条数据
fmt.Printf("user:%#v\n",user)
var users []User
db.Find(&users) //查询所有的数据
fmt.Printf("users:%#v",users)
}
链式操作相关
链式操作
Method Chaining,Gorm 实现了链式操作接口,所以你可以把代码写成这样:
// 创建一个查询
tx := db.Where("name = ?", "jinzhu")
// 添加更多条件
if someCondition {
tx = tx.Where("age = ?", 20)
} else {
tx = tx.Where("age = ?", 30)
}
if yetAnotherCondition {
tx = tx.Where("active = ?", 1)
}
在调用立即执行方法前不会生成Query语句,借助这个特性你可以创建一个函数来处理一些通用逻辑。
立即执行方法
Immediate methods ,立即执行方法是指那些会立即生成SQL语句并发送到数据库的方法, 他们一般是CRUD方法,比如:
Create, First, Find, Take, Save, UpdateXXX, Delete, Scan, Row, Rows…
这有一个基于上面链式方法代码的立即执行方法的例子:
tx.Find(&user)
//生成的SQL语句
SELECT * FROM users where name = 'jinzhu' AND age = 30 AND active = 1;
范围
Scopes,Scope是建立在链式操作的基础之上的。
基于它,你可以抽取一些通用逻辑,写出更多可重用的函数库。
func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
return db.Where("amount > ?", 1000)
}
func PaidWithCreditCard(db *gorm.DB) *gorm.DB {
return db.Where("pay_mode_sign = ?", "C")
}
func PaidWithCod(db *gorm.DB) *gorm.DB {
return db.Where("pay_mode_sign = ?", "C")
}
func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
return func (db *gorm.DB) *gorm.DB {
return db.Scopes(AmountGreaterThan1000).Where("status IN (?)", status)
}
}
db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
// 查找所有金额大于 1000 的信用卡订单
db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
// 查找所有金额大于 1000 的 COD 订单
db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)
// 查找所有金额大于 1000 且已付款或者已发货的订单
多个立即执行方法
Multiple Immediate Methods,在 GORM 中使用多个立即执行方法时,后一个立即执行方法会复用前一个立即执行方法的条件 (不包括内联条件) 。
db.Where("name LIKE ?", "jinzhu%").Find(&users, "id IN (?)", []int{1, 2, 3}).Count(&count)
//生成的 Sql
SELECT * FROM users WHERE name LIKE 'jinzhu%' AND id IN (1, 2, 3)
SELECT count(*) FROM users WHERE name LIKE 'jinzhu%'
更新
更新所有字段
Save()默认会更新该对象的所有字段,即使你没有赋值。
db.First(&user)
user.Name = "jiao"
user.Age = 99
db.Save(&user)
//// UPDATE `users` SET `created_at` = '2020-02-16 12:52:20', `updated_at` = '2020-02-16 12:54:55', `deleted_at` = NULL, `name` = '七米', `age` = 99, `active` = true WHERE `users`.`deleted_at` IS NULL AND `users`.`id` = 1
更新修改字段
如果你只希望更新指定字段,可以使用Update或者Updates
// 更新单个属性,如果它有变化
db.Model(&user).Update("name", "hello")
//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
// 根据给定的条件更新单个属性
db.Model(&user).Where("active = ?", true).Update("name", "hello")
//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;
// 使用 map 更新多个属性,只会更新其中有变化的属性
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
//// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
// 使用 struct 更新多个属性,只会更新其中有变化且为非零值的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18})
//// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
// 警告:当使用 struct 更新时,GORM只会更新那些非零值的字段
// 对于下面的操作,不会发生任何更新,"", 0, false 都是其类型的零值
db.Model(&user).Updates(User{Name: "", Age: 0, Active: false})
更新选定字段
如果你想更新或忽略某些字段,你可以使用 Select,Omit
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
//// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
//// UPDATE users SET age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;
删除
删除记录
警告 删除记录时,请确保主键字段有值,GORM 会通过主键去删除记录,如果主键为空,GORM 会删除该 model 的所有记录。
// 删除现有记录
db.Delete(&email)
//// DELETE from emails where id=10;
// 为删除 SQL 添加额外的 SQL 操作
db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)
//// DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);
软删除
如果一个 model 有 DeletedAt 字段,他将自动获得软删除的功能! 当调用 Delete 方法时, 记录不会真正的从数据库中被删除, 只会将DeletedAt 字段的值会被设置为当前时间
db.Delete(&user)
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;
// 批量删除
db.Where("age = ?", 20).Delete(&User{})
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;
// 查询记录时会忽略被软删除的记录
db.Where("age = 20").Find(&user)
//// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;
// Unscoped 方法可以查询被软删除的记录
db.Unscoped().Where("age = 20").Find(&users)
//// SELECT * FROM users WHERE age = 20;
物理删除
// Unscoped 方法可以物理删除记录
db.Unscoped().Delete(&order)
//// DELETE FROM orders WHERE id=10;
详细:有道云笔记