Gorm是go语言编写的一个ORM框架,是中国人开发的框架(自豪)
偷懒不写sql语句数据库操作神器
ORM的优缺点:
优点:
提高开发效率
缺点:
牺牲执行功能
牺牲灵活性
弱化SQL能力
package main
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
type UserInfo struct {
Id uint
Name string
Gender string
Hobby string
}
func main() {
db, err := gorm.Open("mysql", "root:*****@(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
//创建表 自动迁移 (把结构体和数据库表进行对应)
db.AutoMigrate(&UserInfo{})
//创建数据行
u1 := UserInfo{Id: 1, Name: "zyj", Gender: "男", Hobby: "唱"}
db.Create(&u1)
//查询
var u UserInfo
db.First(&u)
fmt.Println(u)
//更新
db.Model(&u).Update("hobby", "唱跳rap篮球")
//删除
db.Delete(&u) //将查询出来的第一条数据删除
}
为了方便模型定义,GORM内置了一个gorm.Model结构体。gorm.Model是一个包含了ID,CreatedAt,UpdateAt,DeleteAt四个字段的Golang结构体,可以把这个结构体嵌入到自己的模型中。
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
package main
import (
"database/sql"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"time"
)
//数据库中的表名为数据库变量名的复数
type UserInfo struct {
gorm.Model //内嵌gorm.Model
Id string `gorm:"primary_key"`
Name string
Age sql.NullInt64 //零值类型
Birthday *time.Time `gorm:"column:user_birth"` //创建时设置列名为user_birth
Email string `gorm:"type:varchar(100);unique_index"`
Role string `gorm:"size:255"` //设置字段大小为255
MemberNumber *string `gorm:"unique;not null"` //设置会员号(member number)唯一并且不为空
Num int `gorm:"AUTO_INCREMENT"` //设置num为自增类型
Address string `gorm:"index:addr"` //给address字段创建名为addr的索引
IgnoreMe int `gorm:"-"` //忽略本字段
}
func main() {
db, err := gorm.Open("mysql", "root:********@(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
return "prefix_" + defaultTableName
} //所有gorm创建的表名统一加prefix_
db.AutoMigrate(&UserInfo{})
//使用UserInfo结构体创建一个名叫user的表
db.Table("user").CreateTable(&UserInfo{})
}
package main
import (
"fmt"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
dsn := "root:********@(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
SkipDefaultTransaction: true, //关闭默认事务
PrepareStmt: true, //缓存预编译语句
DisableForeignKeyConstraintWhenMigrating: true, //迁移时禁用外键约束
})
if err != nil {
fmt.Println(err)
}
sqldb, _ := db.DB()
sqldb.SetConnMaxLifetime(10 * time.Second) //设置最大连接时间
sqldb.SetMaxIdleConns(10) //设置池中空闲连接数的上限
sqldb.SetMaxOpenConns(100) //限制最大连接数
}
CreatedAt该字段记录初次创建记录的时间
db.Create(&user) // `CreatedAt`将会是当前时间
// 可以使用`Update`方法来改变`CreateAt`的值
db.Model(&user).Update("CreatedAt", time.Now())
UpdatedAt该字段的值将会是每次更新记录的时间。
db.Save(&user) // `UpdatedAt`将会是当前时间
db.Model(&user).Update("name", "jinzhu") // `UpdatedAt`将会是当前时间
DeletedAt:调用Delete删除该记录时,将会设置DeletedAt字段为当前时间,而不是直接将记录从数据库中删除。
package main
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
//1.定义模型
type User struct {
ID int64
Name string `gorm:"default:'zyj''"`
Age int64
}
func main() {
//连接MySQL数据库
db, err := gorm.Open("mysql", "root:*****@(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
defer db.Close()
//2.把模型与数据库表对应起来
db.AutoMigrate(&User{})
//3.创建
u := User{
Name: "zyj",
Age: 18,
}
fmt.Println("数据库存不存在该主键对应的对象", db.NewRecord(&u))
db.Create(&u) //创建记录
db.Debug().Create(&u) //会把对应操作的sql语句打印出来
//注意,所有字段的零值,如:0、”“、false等都不会保存入数据库,而是使用对应的默认值
}
// 根据主键查询第一条记录
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;
where条件查询
// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
SELECT * FROM users WHERE name = 'jinzhu' limit 1;
// Get all matched records
db.Where("name = ?", "jinzhu").Find(&users)
SELECT * FROM users WHERE name = 'jinzhu';
// <>
db.Where("name <> ?", "jinzhu").Find(&users)
SELECT * FROM users WHERE name <> 'jinzhu';
// IN
db.Where("name IN (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)
SELECT * FROM users WHERE name in ('jinzhu','jinzhu 2');
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
SELECT * FROM users WHERE name LIKE '%jin%';
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
// Time
db.Where("updated_at > ?", lastWeek).Find(&users)
SELECT * FROM users WHERE updated_at > '2000-01-01 00:00:00';
// BETWEEN
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
SELECT * FROM users WHERE created_at BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';
Struct&Map查询
// Struct
db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
SELECT * FROM users WHERE name = "jinzhu" AND age = 20 LIMIT 1;
// Map
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
SELECT * FROM users WHERE name = "jinzhu" AND age = 20;
// 主键的切片
db.Where([]int64{20, 21, 22}).Find(&users)
SELECT * FROM users WHERE id IN (20, 21, 22);
Not条件
db.Not("name", "jinzhu").First(&user)
SELECT * FROM users WHERE name <> "jinzhu" LIMIT 1;
// Not In
db.Not("name", []string{"jinzhu", "jinzhu 2"}).Find(&users)
SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");
// Not In slice of primary keys
db.Not([]int64{1,2,3}).First(&user)
SELECT * FROM users WHERE id NOT IN (1,2,3);
db.Not([]int64{}).First(&user)
SELECT * FROM users;
// Plain SQL
db.Not("name = ?", "jinzhu").First(&user)
SELECT * FROM users WHERE NOT(name = "jinzhu");
// Struct
db.Not(User{Name: "jinzhu"}).First(&user)
SELECT * FROM users WHERE name <> "jinzhu";
选择字段查询
db.Select("name, age").Find(&users)
SELECT name, age FROM users;
db.Select([]string{"name", "age"}).Find(&users)
SELECT name, age FROM users;
db.Table("users").Select("COALESCE(age,?)", 42).Rows()
SELECT COALESCE(age,'42') FROM users;
查询并排序
db.Order("age desc, name").Find(&users)
SELECT * FROM users ORDER BY age desc, name;
// 多字段排序
db.Order("age desc").Order("name").Find(&users)
SELECT * FROM users ORDER BY age desc, name;
// 覆盖排序
db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
SELECT * FROM users ORDER BY age desc; (users1)
SELECT * FROM users ORDER BY age; (users2)
更多查询参考网站:
参考网站
更新所有字段
db.First(&user)
user.Name = "七米"
user.Age = 99
db.Save(&user)
条件更新
// 更新单个属性,如果它有变化
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})
更新所选字段
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;
// 删除现有记录
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);
db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
DELETE from emails where email LIKE "%jinzhu%";
db.Delete(Email{}, "email LIKE ?", "%jinzhu%")
DELETE from emails where email LIKE "%jinzhu%";
软删除
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;
go get -u gorm.io/gen@latest
package main
import (
"sign-lottery/pkg/constants"
"strings"
"gorm.io/driver/mysql"
"gorm.io/gen"
"gorm.io/gorm"
)
const MysqlDSN = constants.MysqlDSN //mysql连接的dsn
func main() {
//连接数据库
db, err := gorm.Open(mysql.Open(MysqlDSN))
if err != nil {
panic(err)
}
//创建generator实例
g := gen.NewGenerator(gen.Config{
OutPath: "dao/db", //模型输出地址
Mode: gen.WithDefaultQuery, //WithDefaultQuery 生成默认查询结构体(作为全局变量使用), 即`Q`结构体和其字段(各表模型)
FieldNullable: true, // 表字段可为 null 值时, 对应结体字段使用指针类型
FieldCoverable: false,
/*表字段默认值与模型结构体字段零值不一致的字段, 在插入数据时需要赋值该字段值为零值的, 结构体字段须是指针类型才能成功, 即`FieldCoverable:true`配置下生成的结构体字段.
因为在插入时遇到字段为零值的会被GORM赋予默认值. 如字段`age`表默认值为10, 即使你显式设置为0最后也会被GORM设为10提交.
如果该字段没有上面提到的插入时赋零值的特殊需要, 则字段为非指针类型使用起来会比较方便.*/
FieldSignable: false, // 模型结构体字段的数字类型的符号表示是否与表字段的一致, `false`指示都用有符号类型
FieldWithIndexTag: false, // 生成 gorm 标签的字段索引属性
FieldWithTypeTag: true, // 生成 gorm 标签的字段类型属性
})
g.UseDB(db)
// 自定义字段的数据类型
dataMap := map[string]func(detailType string) (dataType string){
"varchar": func(detailType string) (dataType string) {
return "string"
},
"bigint": func(detailType string) (dataType string) {
return "int64"
},
"int": func(detailType string) (dataType string) {
return "int"
},
"double": func(detailType string) (dataType string) {
return "float64"
},
"text": func(detailType string) (dataType string) {
return "string"
},
"tinytext": func(detailType string) (dataType string) {
return "string"
},
}
g.WithDataTypeMap(dataMap)
// 自定义模型结体字段的标签
// 将特定字段名的 json 标签加上`string`属性,即 MarshalJSON 时该字段由数字类型转成字符串类型
jsonField := gen.FieldJSONTagWithNS(func(columnName string) (tagContent string) {
toStringField := `balance, `
if strings.Contains(toStringField, columnName) {
return columnName + ",string"
}
return columnName
})
// 将非默认字段名的字段定义为自动时间戳和软删除字段;
// 自动时间戳默认字段名为:`updated_at`、`created_at, 表字段数据类型为: INT 或 DATETIME
// 软删除默认字段名为:`deleted_at`, 表字段数据类型为: DATETIME
autoUpdateTimeField := gen.FieldGORMTag("updated_time", "column:updated_at;type:int unsigned;autoUpdateTime")
autoCreateTimeField := gen.FieldGORMTag("created_at", "column:created_at;type:int unsigned;autoCreateTime")
softDeleteField := gen.FieldType("deleted_at", "soft_delete.DeletedAt")
fieldOpts := []gen.ModelOpt{jsonField, autoCreateTimeField, autoUpdateTimeField, softDeleteField}
// 创建全部模型文件, 并覆盖前面创建的同名模型
g.GenerateAllTable(fieldOpts...)
g.Execute()
}