Go组件学习——gorm四步带你搞定DB增删改查
1、简介
ORM
Object-Relationl Mapping, 它的作用是映射数据库和对象之间的关系,方便我们在实现数据库操作的时候不用去写复杂的sql语句,把对数据库的操作上升到对于对象的操作。
gorm
gorm就是基于Go语言实现的ORM库。
类似于Java生态里大家听到过的Mybatis、Hibernate、SpringData等。
Github
https://github.com/jinzhu/gorm
官方文档
https://gorm.io/
2、如何使用Gorm
只要四步就能上手gorm,可以尽情的沉浸在毫无技术含量的CRUD世界。
2.1 下载gorm库
下载gorm库
go get -u github.com/jinzhu/gorm
这是比较原始的方式,现在有了go mod,我们可以更方便的配置,甚至不用配置。
写好代码,在文件下执行go build,go.mod会自动添加对于gorm的依赖包
github.com/jinzhu/gorm v1.9.10
当然,也可以手动添加这个依赖。
具体参见go-demo项目(https://github.com/DMinerJackie/go-demo)
2.2 创建DB连接
建立数据库连接
package main import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
) func main() {
var err error
db, connErr := gorm.Open("mysql", "root:rootroot@/dqm?charset=utf8&parseTime=True&loc=Local")
if connErr != nil {
panic("failed to connect database")
}
defer db.Close()
db.SingularTable(true)
}
gorm支持很多数据源包括PostgreSQL、MySQL等。
这里连接的是MySQL,所以需要引用"github.com/jinzhu/gorm/dialects/mysql"驱动。
通过上面声明,已经获取数据库的连接。
db.SingularTable(true)这句的作用后面会提到。
2.3 创建映射表结构的struct
定义数据库表结构对应的struct
比如这里我们要操作的是表test表,表结构如下
CREATE TABLE `test` (
`id` bigint(20) NOT NULL,
`name` varchar(5) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
于是我们对应可以定义struct结构如下
type Test struct {
ID int64 `gorm:"type:bigint(20);column:id;primary_key"`
Name string `gorm:"type:varchar(5);column:name"`
Age int `gorm:"type:int(11);column:age"`
}
每个字段后面的gorm是结构标记,可以用于声明对应数据库字段的属性。
比如ID后面的约束为该字段为bigint(20)类型,对应列表为id,且该字段为主键。
除此以外,还有更加丰富的标签定义参见官方文档:http://gorm.io/zh_CN/docs/models.html
2.4 CRUD
有了前面三步的铺垫,下面就可以执行真正写数据库操作了。
比如"增"
test := &Test{
ID:3,
Name:"jackie",
Age:18,
}
db.Create(test)
比如"删"
test := &Test{
ID:3,
Name:"jackie",
Age:18,
}
db.Delete(test)
比如"改"
test := &Test{
ID: 3,
Name: "hello",
Age: 18,
}
db.Model(&test).Update("name", "world")
比如"查"
var testResult Test
db.Where("name = ?", "hello").First(&testResult)
fmt.Println("result: ", testResult)
如果只是想做个纯粹的CRUDer,掌握上面四步就算是会用gorm了。
如果还想来点花式的,更深入的,继续往下看~~~
3、表名和结构体如何映射
从上面四步,我们只看到在创建DB链接的时候,提供的信息仅仅到数据库,那么gorm是如何做到将表结构和你定义的struct映射起来的呢?
有三种方式可以实现,如果以下三种方式都没有实现,如果你是创建表,则gorm默认会在你定义的struct名后面加上”s“,比如上面就会创建tests表。
3.1 db.SingularTable(true)
通过db.SingularTable(true),gorm会在创建表的时候去掉”s“的后缀
3.2 实现TableName方法
func (Test) TableName() string {
return "test"
}
TableName方法定义在scope.go的tabler接口中
type tabler interface {
TableName() string
}
3.3 通过Table API声明
db.Table("test").Where("name = ?", "hello").First(&testResult)
在CRUD前,指明需要操作的表名也是OK的。
4、其他花式操作
下面花式API操作使用表dqm_user_role,对应struct如下
type DqmUserRole struct {
ID int64 `gorm:"column:id;primary_key" json:"id"`
UserId string `gorm:"column:user_id" json:"user_id"`
RoleId string `gorm:"column:role_id" json:"role_id"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
}
表中初始数据如下
以下API均亲测可用
First
var dqmUserRole DqmUserRole
// 按照主键顺序的第一条记录
db.First(&dqmUserRole)
fmt.Println("roleId: ", dqmUserRole.RoleId)
Last
var dqmUserRole1 DqmUserRole
// 按照主键顺序的最后一条记录
db.Last(&dqmUserRole1)
fmt.Println("roleId: ", dqmUserRole1.RoleId)
Find
var dqmUserRoels []DqmUserRole
// 所有记录
db.Find(&dqmUserRoels)
fmt.Println("dqmUserRoles: ", dqmUserRoels)
Where
var dqmUserRole3 DqmUserRole
// 根据条件查询得到满足条件的第一条记录
db.Where("role_id = ?", "2").First(&dqmUserRole3)
fmt.Println("where roleId: ", dqmUserRole3.RoleId) var dqmUserRoles4 []DqmUserRole
// 根据条件查询得到满足条件的所有记录
db.Where("user_id = ?", "1").Find(&dqmUserRoles4)
fmt.Println("where dqmUserRoles: ", dqmUserRoles4) var dqmUserRole5 []DqmUserRole
// like模糊查询
db.Where("role_id like ?", "%2").Find(&dqmUserRole5)
fmt.Println("where dqmUserRoles: ", dqmUserRole5) var dqmUserRole6 []DqmUserRole
db.Where("updated_at > ?", "2019-02-08 18:08:27").Find(&dqmUserRole6)
fmt.Println("where dqmUserRoles: ", dqmUserRole6) var dqmUserRole7 DqmUserRole
// struct结构查询条件
db.Where(&DqmUserRole{RoleId: "1,2", UserId: "1"}).First(&dqmUserRole7)
fmt.Println("where dqmUserRole: ", dqmUserRole7) var dqmUserRole8 DqmUserRole
// map结构查询条件
db.Where(map[string]interface{}{"role_id": "1,2", "user_id": "1"}).Find(&dqmUserRole8)
fmt.Println("where dqmUserRole: ", dqmUserRole8)
Not
var dqmUserRole9 DqmUserRole
db.Not([]int64{1}).First(&dqmUserRole9)
fmt.Println("not dqmUserRole: ", dqmUserRole9)
Or
var dqmUserRole10 []DqmUserRole
db.Where(&DqmUserRole{RoleId: "1,2"}).Or(map[string]interface{}{"user_id": "2"}).Find(&dqmUserRole10)
fmt.Println("or dqmUserRoles: ", dqmUserRole10)
FirstOrInit和Attrs
var dqmUserRole11 DqmUserRole
// 查不到该条记录,则使用attrs值替换
db.Where("user_id = ?", "0").Attrs("role_id", "12").FirstOrInit(&dqmUserRole11)
fmt.Println("after FirstOrInit: ", dqmUserRole11) var dqmUserRole12 DqmUserRole
// 查到记录,则使用数据库中的值
db.Where("user_id = ?", "1").Attrs("role_id", "2").FirstOrInit(&dqmUserRole12)
fmt.Println("after FirstOrInit: ", dqmUserRole12)
FirstOrInit和Assign
var dqmUserRole13 DqmUserRole
// 不管是否找到对应记录,使用Assign值替代查询到的值
db.Where("role_id = ?", "1,2").Assign(DqmUserRole{UserId: "15"}).FirstOrInit(&dqmUserRole13)
fmt.Println("assign dqmUserRole: ", dqmUserRole13)
FirstOrCreate
var dqmUserRole14 DqmUserRole
// 如果记录存在则返回结果,如果不存在则创建
db.Where(&DqmUserRole{UserId: "3", RoleId: "3"}).FirstOrCreate(&dqmUserRole14)
fmt.Println("firstOrCreate dqmUserRole: ", dqmUserRole14)
Order
var dqmUserRole16 []DqmUserRole
db.Order("user_id desc").Find(&dqmUserRole16) // 注意这里的order要在find前面,否则不生效
fmt.Println("order dqmUserRoles: ", dqmUserRole16)
Limit和Offset
var dqmUserRole18 []DqmUserRole
db.Limit(10).Offset(2).Find(&dqmUserRole18) // 如果只有offset没有limit则不会生效
fmt.Println("offset dqmUserRoles: ", dqmUserRole18)
Scan
type Result struct {
Id int64
}
var results []Result
db.Select("id").Where("user_id in (?)", []string{"1", "2"}).Find(&dqmUserRole20).Scan(&results)
fmt.Println("ids: ", results)
支持执行原生sql
var dqmUserRole24 []DqmUserRole
db.Exec("select * from dqm_user_role").Find(&dqmUserRole24)
fmt.Println("sql dqmUserRole: ", dqmUserRole24)
事务
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
if err = tx.Create(&DqmUserRole{UserId: "8", RoleId: "8"}).Error; err != nil {
//tx.Rollback()
//return
} if err = tx.Create(&DqmUserRole{UserId: "9", RoleId: "9"}).Error; err != nil {
//tx.Rollback()
//return
}
错误处理
var dqmUserRole25 DqmUserRole
err = db.Where("role_id = ?", 54321).First(&dqmUserRole25).Error
if err == gorm.ErrRecordNotFound {
fmt.Println("ErrRecordNotFound, record not found")
} else {
fmt.Println("err: ", err)
}
fmt.Println("err dqmUserRole: ", dqmUserRole25)
5、总结
gorm作为一款orm库,几乎满足了一个CRUDer的一切想象。实现灵活,花样繁多。
有了gorm,就不需要再在代码中维护sql语句了。
后面有时间会再看看gorm的实现,作为国人开源的第一个orm库,目前star已经超过15k,值得深入学习下。
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。
Go组件学习——gorm四步带你搞定DB增删改查的更多相关文章
- JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查)
前言:关于Vue框架,好几个月之前就听说过,了解一项新技术之后,总是处于观望状态,一直在犹豫要不要系统学习下.正好最近有点空,就去官网了解了下,看上去还不错的一个组件,就抽空研究了下.最近园子里vue ...
- spring学习(四)spring的jdbcTemplate(增删改查封装)
Spring的jdbcTemplate操作 1.Spring框架一站式框架 (1)针对javaee三层,每一层都有解决技术 (2)到dao 层,使用 jdbcTemplate 2.Spring对不同的 ...
- Mysql学习笔记(三)对表数据的增删改查。
正文内容. 这一部分是最简单的,也是最麻烦的.简单是因为其实只包括增删该插四个部分.大体上看,增加数据.删除数据.修改数据.查询数据都不麻烦啊,我们日常都是常用的.这个谁不会呢?以前在培训机构学mys ...
- 【EF6学习笔记】(二)操练 CRUD 增删改查
本篇原文链接: Implementing Basic CRUD Functionality 说明:学习笔记参考原文中的流程,为了增加实际操作性,并能够深入理解,部分地方根据实际情况做了一些调整:并且根 ...
- EF6 学习笔记(二):操练 CRUD 增删改查
EF6学习笔记总目录 ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 接上篇: EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作 本篇原文链接: I ...
- mongodb的学习笔记一(集合和文档的增删改查)
1数据库的增删改查 一.增加一个数据库: use blog-----切换到指定的数据库,如果数据库不存在,则自动创建该数据库(新建的数据库,如果没有存储对应的集合,是不会显示出来的) 二.删除一个数据 ...
- Mysql学习笔记(二)对表结构的增删改查
有将近一个星期都没有更新mysql了.相反linux的东西倒是学习不少.可能我个人情感上对linux更感兴趣一点.但mysql我也不烦,只是一旦将精力投入到了一样事情上去,就很难将精力分散去搞其他的东 ...
- 数据库学习(MySQL):JDBC的简单增删改查实现
本文为原创,转载请注明出处: https://www.cnblogs.com/Tom-shushu/p/9171896.html 这里我们先在数据库建立一个userinfo表: CREATE TABL ...
- oracle学习笔记系列------oracle 基本操作之表的增删改查
--创建一个表 CREATE TABLE employee_souvc( id ), name ), gender ), birth DATE, salary ,), job ), deptno ) ...
随机推荐
- T4生成实体和简单的CRUD操作
主要跟大家交流下T4,我这里针对的是mysql,我本人比较喜欢用mysql,所以语法针对mysql,所以你要准备mysql的DLL了,同理sqlserver差不多,有兴趣可以自己写写,首先网上找了一个 ...
- 【HDU - 2612】Find a way
-->Find a way 直接上Chinese Descriptions: hsj和lsh最近迷上了pokemon go的游戏.在双十一大物期中考试来临之前,他们想抓一只稀有土拨鼠来攒攒人品 ...
- Appium+python自动化(十五)- Android 这些基础知识,你知多少???(超详解)
简介 前边具体操作和实战已经讲解和分享了很多了,但是一些android的一些基础知识,你又知道多少了,你都掌握了吗?这篇就由宏哥给小伙伴们既是一个分享,又是对前边的一次总结.为什么要对这些做一个简单的 ...
- [Vue 牛刀小试]:第十五章 - 传统开发模式下的 axios 使用入门
一.前言 在没有接触 React.Angular.Vue 这类 MVVM 的前端框架之前,无法抛弃 Jquery 的重要理由,除了优秀的前端 DOM 元素操作性以外,能够非常便捷的发起 http 请求 ...
- 分布式个人理解概述和dubbo实现简述
什么是分布式?为什么使用分布式? 个人有一些浅薄的理解希望可以批评指正,从概念和应用 两个方面概述: 一.概念:分布式也叫分布式服务,也就是说 他是 一种面向服务思想的程序设计和架构风格,典 ...
- 常用的URL Scheme
系统 短信 sms:// app store itms-apps:// 电话 tel:// 备忘录 mobilenotes:// 设置 prefs:root=SETTING E-Mail MESSAG ...
- c++书籍推荐《C++编码规范》下载
百度云及其他网盘下载地址:点我 编辑推荐 <C++编程规范:101条规则.准则与 实践>:良好的编程规范可以改善软件质量,缩短上市时间,提升团队效率,简化维护工作.在<C++编程规范 ...
- IT人士如何扛起工作生活两座大山
前言 当我们年轻时,初入职场,意气风发,恨不能倾尽所有精力工作,奋发图强.建功立业.当我们有了家庭,发现我亦凡人,事业家庭想两手抓,却两难兼顾.后来,我们发现工作生活两顾本身就是一个幻想,我们做的,只 ...
- JAVA基础之JDK安装
JDK的安装与环境变量配置是JAVA开发之路的第一步,很多新人在这一步上就卡了很久,浪费了很多时间,甚至有些人就轻易地“从入门到放弃”了. 今天我们就来一步步教你如何打倒这第一只拦路虎. 1.JDK下 ...
- 一篇文章学会Docker命令
目录 简介 镜像仓库 login pull push search 本地镜像管理 images rmi tag build history save load import 容器操作 ps inspe ...