为了将数据库驱动与框架主库解耦,从v2.1版本开始,所有的数据库驱动都需要手动引入。
v2.1
数据库驱动的安装和引入请参考:https://github.com/gogf/gf/tree/master/contrib/drivers
GoFrame框架的ORM功能由gdb模块实现,用于常用关系型数据库的ORM操作。
GoFrame
ORM
gdb
gdb数据库引擎底层采用了链接池设计,当链接不再使用时会自动关闭,因此链接对象不用的时候不需要显式使用Close方法关闭数据库连接。
Close
注意:为提高数据库操作安全性,在ORM操作中不建议直接将参数拼接成SQL字符串执行,建议使用预处理的方式(充分使用?占位符)来传递SQL参数。gdb的底层实现中均采用的是预处理的方式处理开发者传递的参数,以充分保证数据库操作安全性。
SQL
?
接口文档:
https://pkg.go.dev/github.com/gogf/gf/v2/database/gdb
GoFrame ORM组件具有以下显著特点:
GoFrame ORM
OpenTelemetry
Scan
Map/Struct
nil
sql.ErrNoRows
Map/Struct/Slice
DAO
Model/DAO
DryRun
Handler
GoFrame ORM Features
GoFrame ORM Dependencies
g.DB
gdb.New
gdb.Instance
获取数据库操作对象有三种方式,一种是使用g.DB方法(推荐),一种是使用原生gdb.New方法,还有一种是使用包原生单例方法gdb.Instance,而第一种是推荐的使用方式。这三种方式的区别如下:
有这么多对象获取方式原因在于GoFrame是一个模块化设计的框架,每个模块皆可单独使用。
New
db, err := gdb.New(gdb.ConfigNode{ Link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test", })
// 获取默认配置的数据库对象(配置名称为"default") db := g.DB() // 获取配置分组名称为"user"的数据库对象 db := g.DB("user") // 使用原生单例管理方法获取数据库对象单例 db, err := gdb.Instance() db, err := gdb.Instance("user")
由于go标准库的数据库操作对象采用接口实现,因此提供了非常好的可扩展性和兼容性。框架已支持的第三方数据库驱动请参考:https://github.com/gogf/gf/tree/master/contrib/drivers
go
额外接入新的数据库相当方便,可参考源码中关于PostgreSQL、SQLite、Oracle、SQL Server的接入方式。具体介绍请参考后续 ORM接口开发-驱动开发 章节。
PostgreSQL
SQLite
Oracle
SQL Server
请问orm报错empty database configuration for item name 'default'是什么问题呀,之前一直没有问题,这两天就不行了。但是数据库配置也没问题,在test包测试执行同样的orm也没问题(但是我重新装过go,不知道有没有关系)。执行gf gen dao也是报错Error: database initialization failed。
orm
empty database configuration for item name 'default'
test
gf gen dao
Error: database initialization failed
表示你的配置文件中的数据库配置有问题,检查一下,参考一下:ORM使用配置
在微服务生产环境中,通常有数据库 migrate 需求,这块 ORM 是否有考虑支持?
migrate
暂无考虑。
那么项目中遇到随着版本更新,数据库的变更,比如2.0 比1.0 新增字段,新增表;需要进行版本升级,保留1.0的数据; 该怎么做呢?
gdb 有类似gorm的 AutoMigrate 自动建表功能吗?最近在学习focus发现用的是gdb但是搜了下没发现自动建表的功能 需要手动建表或者导入 是我没搜到还是没有呢?
gorm
AutoMigrate
focus
goframe的orm没有migrate功能,未来估计也不太可能会有。
goframe
发现两个问题
1、很多团队是基于 模型驱动开发(DDD),尤其是Java团队转过来的人群,建议支持 AutoMigrate
DDD
Java
2、支持手动关闭数据库连接,比如在一些嵌入式设备上,需要多个进程修改sqlite中的数据,不能手动关闭,很容易造成database locked
sqlite
database locked
当然,可能会有人建议我去用gorm 或xorm 但是还是希望国产框架能够做的更好哈
xorm
GoFrame ORM不支持Migrate特性,这种特性不太严谨,未来应该也不太可能会支持。你另外一个关于数据库连接关闭的问题,是可以手动关闭的,建议可以结合文档和源码一起看看。
Migrate
DDL操作 和 DML操作应该分开
DDL
DML
代码 应该只操作数据 而不应该操作数据库表
权限越位了。
且库表的创建修改权限,应该集中在技术管理人员手里,如果放在代码账号里,
人人都有权限,存在操作风险哦,团队内的成员,SQL水平参差不齐,安全意识也不一定到位。
这是管理上的问题,不是所有问题都要在开发层面解决
postgresql 如何支持LastInsertId,有别的方法可以用吗
postgresql 如何实现获取自增主键
gorm Create 是会返回主键的,请问,gform如何返回postgresql主键 RETURNING "id"
暂不支持
django 中的实现: https://github.com/django/django/blob/main/django/db/backends/postgresql/operations.py
"github.com/lib/pq"
用户是否可以在 insert sql 后面自己加 RETURNING "id"
很简单,可以提个PR。
请问g.DB().GetStructs这些使用sql语句查询的api怎么调Cache函数做数据缓存?
g.DB().GetStructs
sql
api
Cache
你可以看看Raw方法通过SQL语句创建为Model,随后可以使用Model的数据缓存特性。
Raw
Model
ORM开启多链接的情况下,有没计划提供针对同一对象的操作顺序保障。
因为在多连接情况下同一对象的操作请求走不同链接可能会导致数据的最终结果和预期的不一致。
多连接情况下同一对象的操作请求走不同链接可能会导致数据的最终结果和预期的不一致。
你这个场景或许只有事务能帮助你,可以参考下章节:ORM事务处理
请问 orm 可以支持 hooks 操作吗?这样清理缓存就可以方便很多,且同一个 model 对应的多个缓存也可以一并清理
如:
_, err := db.Table("user").Cache(-1, "vip-user").Data(gdb.Map{"name": "smith"}).Where("uid", 1).Update()
就可以改造为:
_, err := db.Table("user").Data(gdb.Map{"name": "smith"}).Where("uid", 1).Update() func afterSave(instance) { g.Redis().Do("del", "vip-user") g.Redis().Do("del", <其他 key>) }
GoFrame ORM支持数据库级别的回调处理,具体请参考章节:ORM接口开发-回调处理 目前暂不支持Model级别的回调功能。
在调试中除了使用日志功能输出原生SQL语句的方法,还有没有链式操作的方法API输出原生的SQL语句?我在调试过程中,发现update无法输出原生SQL语句
请自己检查程序逻辑。
大佬,请问mongodb这个应该这么用呢?网上找了也没看到goframe有人用过
直接用mongodb的官方库
https://docs.mongodb.com/drivers/go/
这个我也看到了,官方这个据说不太好用。主要是怎么优雅的结合gf一起使用
七牛封装了一个
ORM似乎不支持postgresql的数组类型,数据库中 是float4数组,通过orm查询出来的数据返回 “0”
请提个issue,把具体的类型名称发一下
issue
请问一下,这个orm是否支持事件监听
请问有没有类似beforeSave() , afterSave() 这样类似的方法,或者说类似的功能该怎么实现
GoFrame的ORM采用的是接口化设计,没有HOOK功能,你可以使用接口覆盖来实现自定义功能,相比较HOOK设计灵活性和扩展性更高。请参考:ORM接口开发-回调处理
强哥,看到深入有点晕,在控制器里查询数据是直接用g.model("user") 还是用dao.User,包括在service里面, 什么时候用g.model("user") 和 dao.user 还是很模糊,这两者有什么区别呢
在控制器里查询数据是直接用g.model("user") 还是用dao.User,包括在service里面, 什么时候用g.model("user") 和 dao.user 还是很模糊,这两者有什么区别呢 我看着也蒙,这两种有各自的应用场景吗?
dao是项目工程管理中的模块,由框架工具自动生成和维护,推荐开发业务项目都按照框架推荐的工程结构进行。
dao
g.Model是便捷的模型创建方法,相对上层业务的工程架构来讲,是属于较低层的组件工具方法。
g.Model
你好,请问一下,这个orm能实现监听binlog吗?
你好,个人觉得这并不是ORM应该做的事情。
_, e := dao.User.Ctx(ctx).Insert(&u)这个怎么获取mysql的错误码呢?这样出错
mysqlErr, ok := e.Error.(mysql.MySQLError)if ok { if mysqlErr.Number == 1062 { // solve the duplicate key error. //return error("") }}
获取error的错误码可以使用gerror.Code方法,具体请参考章节:错误处理-错误码使用
error
gerror.Code
郭强 , driver分离后,做单元测试时,如何处理, 是否得在每个会调用orm的test.go文件,都要手动引入
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
我是这个样子,
lance 强仔 在相同包下只需要引用一次即可。
goframe有没有计划支持tidb/gaussdb等国产数据库
期待
tidb兼容mysql协议理论上可以直接用.gaussdb大概查了下是完全兼容mysql的.如果有些许不兼容的地方可以通过注册driver的形式去覆盖.也欢迎提供pr.
47 Comments
陈富贵
请问
orm
报错empty database configuration for item name 'default'
是什么问题呀,之前一直没有问题,这两天就不行了。但是数据库配置也没问题,在test
包测试执行同样的orm
也没问题(但是我重新装过go
,不知道有没有关系)。执行gf gen dao
也是报错Error: database initialization failed
。郭强
表示你的配置文件中的数据库配置有问题,检查一下,参考一下:ORM使用配置
Yufan Sheng
在微服务生产环境中,通常有数据库
migrate
需求,这块ORM
是否有考虑支持?郭强
暂无考虑。
白夜
那么项目中遇到随着版本更新,数据库的变更,比如2.0 比1.0 新增字段,新增表;需要进行版本升级,保留1.0的数据; 该怎么做呢?
英梨梨
gdb
有类似gorm
的AutoMigrate
自动建表功能吗?最近在学习focus
发现用的是gdb
但是搜了下没发现自动建表的功能 需要手动建表或者导入 是我没搜到还是没有呢?郭强
goframe
的orm
没有migrate
功能,未来估计也不太可能会有。ssz
发现两个问题
1、很多团队是基于 模型驱动开发(
DDD
),尤其是Java
团队转过来的人群,建议支持AutoMigrate
2、支持手动关闭数据库连接,比如在一些嵌入式设备上,需要多个进程修改
sqlite
中的数据,不能手动关闭,很容易造成database locked
ssz
当然,可能会有人建议我去用
gorm
或xorm
但是还是希望国产框架能够做的更好哈郭强
GoFrame ORM
不支持Migrate
特性,这种特性不太严谨,未来应该也不太可能会支持。你另外一个关于数据库连接关闭的问题,是可以手动关闭的,建议可以结合文档和源码一起看看。刘羽禅
DDL
操作 和DML
操作应该分开代码 应该只操作数据 而不应该操作数据库表
权限越位了。
且库表的创建修改权限,应该集中在技术管理人员手里,如果放在代码账号里,
人人都有权限,存在操作风险哦,团队内的成员,
SQL
水平参差不齐,安全意识也不一定到位。ssz
这是管理上的问题,不是所有问题都要在开发层面解决
奭奭
postgresql 如何支持LastInsertId,有别的方法可以用吗
奭奭
postgresql 如何实现获取自增主键
奭奭
gorm Create 是会返回主键的,请问,gform如何返回postgresql主键 RETURNING "id"
郭强
暂不支持
hyh
django 中的实现: https://github.com/django/django/blob/main/django/db/backends/postgresql/operations.py
用户是否可以在 insert sql 后面自己加 RETURNING "id"
郭强
很简单,可以提个PR。
xx
请问
g.DB().GetStructs
这些使用sql
语句查询的api
怎么调Cache
函数做数据缓存?郭强
你可以看看
Raw
方法通过SQL
语句创建为Model
,随后可以使用Model
的数据缓存特性。白开水
ORM开启多链接的情况下,有没计划提供针对同一对象的操作顺序保障。
因为在多连接情况下同一对象的操作请求走不同链接可能会导致数据的最终结果和预期的不一致。
郭强
你这个场景或许只有事务能帮助你,可以参考下章节:ORM事务处理
Heathcliff Huu
请问 orm 可以支持 hooks 操作吗?这样清理缓存就可以方便很多,且同一个 model 对应的多个缓存也可以一并清理
如:
就可以改造为:
郭强
GoFrame ORM
支持数据库级别的回调处理,具体请参考章节:ORM接口开发-回调处理 目前暂不支持Model
级别的回调功能。钱波
在调试中除了使用日志功能输出原生SQL语句的方法,还有没有链式操作的方法API输出原生的SQL语句?我在调试过程中,发现update无法输出原生SQL语句
郭强
请自己检查程序逻辑。
xx
大佬,请问mongodb这个应该这么用呢?网上找了也没看到goframe有人用过
海亮
直接用mongodb的官方库
https://docs.mongodb.com/drivers/go/
xx
这个我也看到了,官方这个据说不太好用。主要是怎么优雅的结合gf一起使用
智刚
七牛封装了一个
g
ORM似乎不支持postgresql的数组类型,数据库中 是float4数组,通过orm查询出来的数据返回 “0”
郭强
请提个
issue
,把具体的类型名称发一下王一飞
请问一下,这个orm是否支持事件监听
lige
请问有没有类似beforeSave() , afterSave() 这样类似的方法,或者说类似的功能该怎么实现
郭强
GoFrame的ORM采用的是接口化设计,没有HOOK功能,你可以使用接口覆盖来实现自定义功能,相比较HOOK设计灵活性和扩展性更高。请参考:ORM接口开发-回调处理
lige
强哥,看到深入有点晕,在控制器里查询数据是直接用g.model("user") 还是用dao.User,包括在service里面, 什么时候用g.model("user") 和 dao.user 还是很模糊,这两者有什么区别呢
niyong
在控制器里查询数据是直接用g.model("user") 还是用dao.User,包括在service里面, 什么时候用g.model("user") 和 dao.user 还是很模糊,这两者有什么区别呢 我看着也蒙,这两种有各自的应用场景吗?
郭强
dao
是项目工程管理中的模块,由框架工具自动生成和维护,推荐开发业务项目都按照框架推荐的工程结构进行。g.Model
是便捷的模型创建方法,相对上层业务的工程架构来讲,是属于较低层的组件工具方法。王一飞
你好,请问一下,这个orm能实现监听binlog吗?
郭强
你好,个人觉得这并不是
ORM
应该做的事情。long
郭强
获取
error
的错误码可以使用gerror.Code
方法,具体请参考章节:错误处理-错误码使用lance
郭强 , driver分离后,做单元测试时,如何处理, 是否得在每个会调用orm的test.go文件,都要手动引入
强仔
我是这个样子,
郭强
lance 强仔 在相同包下只需要引用一次即可。
KingKong
goframe有没有计划支持tidb/gaussdb等国产数据库
期待
糖水不加糖
tidb兼容mysql协议理论上可以直接用.gaussdb大概查了下是完全兼容mysql的.如果有些许不兼容的地方可以通过注册driver的形式去覆盖.也欢迎提供pr.