来自:https://www.cnblogs.com/rickiyang/p/14517120.html
今天聊聊目前业界使用比较多的 ORM 框架:GORM。GORM 相关的文档原作者已经写得非常的详细,具体可以看这里,这一篇主要做一些 GORM 使用过程中关键功能的介绍,GORM 约定的一些配置信息说明,防止大家在使用过程中踩坑。
以下示例代码都可以在 Github : gorm-demo 中找到。
GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server。
连接 MySQL 的示例:
MySQl 驱动程序提供了一些高级配置可以在初始化过程中使用,例如:
注意到 gorm.Open(dialector Dialector, opts …Option) 函数的第二个参数是接收一个 gorm.Config{} 类型的参数,这里就是 gorm 在数据库建立连接后框架本身做的一些默认配置,请注意这里如果没有配置好,后面你的数据库操作将会很痛苦!
GORM 提供的配置可以在初始化时使用:
这些参数我们一个一个来说:
SkipDefaultTransaction
跳过默认开启事务模式。为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。如果没有这方面的要求,可以在初始化时禁用它。
NamingStrategy
表名称的命名策略,下面会说。GORM 允许用户通过覆盖默认的NamingStrategy
来更改命名约定,这需要实现接口 Namer
:
默认 NamingStrategy
也提供了几个选项,如:
一般来说这里是一定要配置 *SingularTable: true* 这一项的。
Logger
允许通过覆盖此选项更改 GORM 的默认 logger。
NowFunc
更改创建时间使用的函数:
DryRun
生成 SQL
但不执行,可以用于准备或测试生成的 SQL:
PrepareStmt
PreparedStmt
在执行任何 SQL 时都会创建一个 prepared statement 并将其缓存,以提高后续的效率:
GORM 约定配置#
使用别人的框架就要受制别人的约束,在 GORM 中有很多的约定,如果你没有遵循这些约定可能你认为正常的代码跑起来会发生意想不到的问题。
模型定义
默认情况下,GORM 会使用 ID
作为表的主键。
如果你当前的表主键不是 id 字段,那么你可以通过 primaryKey
标签将其它字段设为主键:
如果你的表采用了复合主键,那也没关系:
**注意:**默认情况下,整型 PrioritizedPrimaryField
启用了 AutoIncrement
,要禁用它,您需要为整型字段关闭 autoIncrement
:
GORM 标签
GORM 通过在 struct 上定义自定义的 gorm 标签来实现自动化创建表的功能:
定义完这些标签之后,你可以使用 AutoMigrate 在 MySQL 建立连接之后创建表:
AutoMigrate 用于自动迁移你的 schema,保持 schema 是最新的。 该 API 会创建表、缺失的外键、约束、列和索引。 如果大小、精度、是否为空可以更改,则 AutoMigrate 会改变列的类型。
出于保护数据的目的,它 不会 删除未使用的列。
默认模型
GORM 定义一个 gorm.Model
结构体,其包括字段 ID
、CreatedAt
、UpdatedAt
、DeletedAt
。
如果你觉得上面这几个字段名字段名是你想要的,那么你完全可以在你的模型中引入它:
反之如果不是你需要的,就没必要多此一举。
表名
这里是一个很大的坑。GORM 使用结构体名的 蛇形命名
作为表名。对于结构体 User
,根据约定,其表名为 users
。
当然我们的表名肯定不会是这样设置的,所以为什么作者要采用这种设定实在是难以捉摸。
这里有两种方式去修改表名:第一种就是去掉这个默认设置;第二种就是在保留默认设置的基础上通过重新设定表名来替换。
先说如何通过重新设定表名来替换,可以实现 Tabler
接口来更改默认表名,例如:
通过去掉默认配置上面已经有提,配置 SingularTable: true 这选项即可。
列名覆盖
默认情况下列名遵循普通 struct 的规则:
如果你的列名和字段不匹配的时候,可以通过如下方式重新指定:
日期字段时间类型设置
GORM 约定使用 CreatedAt
、UpdatedAt
追踪创建/更新时间。如果你定义了这种字段,GORM 在创建、更新时会自动填充。
如果想要保存 UNIX(毫/纳)秒时间戳而不是 time,只需简单地将 time.Time
修改为 int
即可:
嵌入结构体
对于匿名字段,GORM 会将其字段包含在父结构体中,例如:
对于正常的结构体字段,你也可以通过标签 embedded
将其嵌入,例如:
CRUD操作#
新增相关
单行插入,gorm 会返回插入之后的主键信息:
批量插入,批量插入也会同步返回插入之后的主键信息:
插入冲突操作-Upsert:
如果你的表设置了唯一索引的情况下,插入可能会出现主键冲突的情况,MySQL 本身是提供了相关的操作命令 ON DUPLICATE KEY UPDATE,那么对应到 Gorm 中的函数是 Upsert:
删除相关
根据主键删除:
根据条件删除:
批量删除:
对于全局删除的阻止设定
如果在没有任何条件的情况下执行批量删除,GORM 不会执行该操作,并返回 ErrMissingWhereClause
错误。对此,你必须加一些条件,或者使用原生 SQL,或者启用 AllowGlobalUpdate
模式,例如:
更新操作
全量更新 struct 的所有字段,包括零值:
更新指定列:
更新非0值的字段:
如果你想更新0值的字段,那么可以使用 Select 函数先选择指定的列名,或者使用 map 来完成:
Select 方式指定列名:
Select 选定所有列名:
Select 排除指定列名:
根据条件批量更新:
查询操作
查询是重头戏放在最后。
Gorm 提供的便捷查询:
First:获取第一条记录(主键升序)
获取一条记录,没有指定排序字段:
获取最后一条记录(主键降序):
使用主键的方式查询:
条件查询:
not 条件操作:
or 操作:
查询返回指定字段:
如果你只要要查询特定的字段,可以使用 Select 来指定返回字段:
指定排序方式:
分页查询:
分组查询-Group & Having:
Distinct 使用:
事务操作#
如同在 MySQL 中操作事务一样,事务的开始是以 Begin 开始,以 Commit 结束:
以上就是关于 GORM 使用相关的操作说明以及可能会出现的问题,关于 Gorm 的使用还有一些高级特性,这里就不做全面的演示,还是先熟悉基本 api 的操作等需要用到高级特性的时候再去看看也不迟。示例代码都已经上传到 Github,大家可以下载下来练习一下。