gorm快速使用

bytemode · · 7133 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

## gorm ORM 就是通过实例对象的语法,完成关系型数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写. gorm, github.com/jinzhu/gorm 全特性 ORM (几乎包含所有特性). ## 模型定义 模型一般都是普通的 Golang 的结构体,Go 的基本数据类型,或者指针。sql.Scanner 和 driver.Valuer,同时也支持接口。 ### gorm.Model gorm.Model 是一个包含一些基本字段的结构体,包含的字段有 ID,CreatedAt, UpdatedAt, DeletedAt。 你可以用它来嵌入到你的模型中,或者也可以用它来建立自己的模型.GORM 默认使用 ID 作为主键名。 - 可以通过`gorm:"primary_key"设置主键. - 表名是结构体名称的复数形式, type User struct{} 默认表名是"users", 可以重写TableName() string 返回新表名 - 禁用复数表名:db.SingularTable(true) - 修改默认表名gorm.DefaultTableNameHandler ``` gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string { return "prefix_" + defaultTableName; } ``` - 蛇形列名,列名是字段名的蛇形小写形式 ``` type User struct { ID uint // 字段名是 `id` Name string // 字段名是 `name` Birthday time.Time // 字段名是 `birthday` CreatedAt time.Time // 字段名是 `created_at` } ``` ### 结构标签 标签 说明 Column 指定列的名称 Type 指定列的类型 Size 指定列的大小,默认是 255 PRIMARY_KEY 指定一个列作为主键 UNIQUE 指定一个唯一的列 DEFAULT 指定一个列的默认值 PRECISION 指定列的数据的精度 NOT NULL 指定列的数据不为空 AUTO_INCREMENT 指定一个列的数据是否自增 INDEX 创建带或不带名称的索引,同名创建复合索引 UNIQUE_INDEX 类似 索引,创建一个唯一的索引 EMBEDDED 将 struct 设置为 embedded EMBEDDED_PREFIX 设置嵌入式结构的前缀名称 - 忽略这些字段 FOREIGNKEY 指定外键 ``` type User struct { gorm.Model Name string `gorm:"default:aa"` Age sql.NullInt64 Birthday *time.Time `gorm:"column:day_of_the_beast"` Email string `gorm:"type:varchar(100);unique_index"` Role string `gorm:"size:255"` //设置字段的大小为255个字节 MemberNumber *string `gorm:"unique;not null"` // 设置 memberNumber 字段唯一且不为空 Num int `gorm:"AUTO_INCREMENT"` // 设置 Num字段自增 Address string `gorm:"index:addr"` // 给Address 创建一个名字是 `addr`的索引 IgnoreMe int `gorm:"-"` //忽略这个字段 } ``` ## CRUD ### 连接 ``` import ( _ "github.com/go-sql-driver/mysql" "github.com/jinzhu/gorm" ) db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local") defer db.Close() ``` ### 创建记录 ``` user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()} db.Create(&user) //在钩子中设置字段值 func (user *User) BeforeCreate(scope *gorm.Scope) error { scope.SetColumn("ID", uuid.New()) return nil } ``` ### 查询记录 db.First() db.Find() db.Where().Find() db.Raw() db.Exec() ``` // 获取第一条记录,按主键排序 db.First(&user) // SELECT * FROM users ORDER BY id LIMIT 1; // 获取所有的记录 db.Find(&users) // SELECT * FROM users; // 通过主键进行查询 db.First(&user, 10) // SELECT * FROM users WHERE id = 10; // 原生 SQL db.Find(&user, "name = ?", "jinzhu") // SELECT * FROM users WHERE name = "jinzhu"; db.Find(&users, "name <> ? AND age > ?", "jinzhu", 20) // SELECT * FROM users WHERE name <> "jinzhu" AND age > 20; // Struct db.Find(&users, User{Age: 20}) // SELECT * FROM users WHERE age = 20; // 获取第一条匹配的记录 db.Where("name = ?", "jinzhu").First(&user) // SELECT * FROM users WHERE name = 'jinzhu' limit 1; // 获取所有匹配的记录 db.Where("name = ?", "jinzhu").Find(&users) // SELECT * FROM users WHERE name = 'jinzhu'; //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; type Result struct { Name string Age int } var result Result db.Table("users").Select("name, age").Where("name = ?", 3).Scan(&result) // Raw SQL db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result) ``` ### 更新记录 db.Save() //更新所有字段 db.Model(&struct).Update(k,v) //更新特定字段 ``` db.First(&user) user.Name = "jinzhu 2" user.Age = 100 db.Save(&user) //// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111; // 如果单个属性被更改了,更新它 db.Model(&user).Update("name", "hello") //// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111; ``` ### 删除记录 ``` // 删除一条存在的记录 db.Delete(&email) db.Where("email LIKE ?", "%jinzhu%").Delete(Email{}) ``` ## 高级 ### 钩子 钩子是一个在 插入 / 查询 / 更新 / 删除 之前或之后被调用的方法。 如果你在一个模型中定义了特殊的方法,它将会在插入,更新,查询,删除的时候被自动调用,如果任何的回调抛出错误,GORM 将会停止将要执行的操作并且回滚当前的改变 在 GORM 中的保存 / 删除 操作会默认进行事务处理,所以在事物中,所有的改变都是无效的,直到它被提交为止 可用于更新的钩子: // 开启事务 BeforeSave BeforeUpdate AfterUpdate AfterSave // 提交或回滚的事务 ``` func (u *User) BeforeSave() (err error) { if u.IsValid() { err = errors.New("can't save invalid data") } return } func (u *User) AfterCreate(scope *gorm.Scope) (err error) { if u.ID == 1 { scope.DB().Model(u).Update("role", "admin") } return } func (u *User) BeforeUpdate() (err error) { if u.readonly() { err = errors.New("read only user") } return } // 在事务结束后,进行更新数据 func (u *User) AfterUpdate(tx *gorm.DB) (err error) { if u.Confirmed { tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("verfied", true) } return } // 在事务结束后进行更新数据 func (u *User) AfterDelete(tx *gorm.DB) (err error) { if u.Confirmed { tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("invalid", false) } return } ``` ### 事务 GORM 默认在事务中执行单个 create, update, delete 操作,以确保数据库数据完整性。 ``` / 开启事务 tx := db.Begin() // 在事务中执行一些数据库操作 (从这里开始使用 'tx',而不是 'db') tx.Create(...) // ... // 发生错误回滚事务 tx.Rollback() // 或者提交这个事务 tx.Commit() ```

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

7133 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传