GORM 支持复杂对象

GORM 支持复杂对象

💡 原文中文,约15000字,阅读约需36分钟。
📝

内容提要

GORM支持复杂对象和Go基本类型。然而,它可能无法满足所有开发需求。GORM提供了两种解决方案:通过接口定义支持的数据类型和使用自定义数据类型库。datatypes库使用JSON表示复杂数据结构,而pq库支持Postgres的GORM数据类型。GORM通过接口支持自定义数据类型,用于解析和保存数据到数据库,定义数据库类型,以及读取或查询复杂数据类型。文章提供了实现GORM支持复杂对象的示例代码。

🔎

延伸解读

GORM 原生类型支持的局限

GORM 默认仅支持 Go 基本类型,如 bool、string、数值类型等。然而实际开发中常遇到复杂数据结构,例如 [][]byte、map[string]T 等,这些类型无法直接映射到数据库。文章指出,GORM 原生不支持这些类型,因此需要借助接口或第三方库来扩展。理解这一局限有助于在项目初期评估是否需引入自定义类型方案。

两种扩展方案:接口与库

GORM 提供了两种解决复杂对象支持的途径:一是通过实现少量接口(如 Scanner、Valuer、GormDBDataTypeInterface 等)自定义数据类型;二是使用社区扩展库,如 datatypes 和 pq。datatypes 利用 JSON 表示复杂结构,pq 则针对 Postgres 提供 Hstore、Array 等类型支持。选择时需权衡项目数据库类型和团队熟悉度。

自定义类型的三个实现维度

文章详细说明了 GORM 从三个维度支持自定义数据类型:解析和保存数据(实现 Scanner 和 Valuer 接口)、定义数据库字段类型(通过 GormDBDataTypeInterface 或 GormDataTypeInterface)、以及复杂数据类型的读取或查询(实现 clause.Expression 接口)。示例代码展示了如何为 JSON 类型实现这些接口,并针对不同数据库生成相应的 SQL 表达式。

跨数据库兼容性注意事项

示例代码中,JSON 类型的 GormDBDataType 方法根据数据库类型返回不同的字段类型:SQLite 和 MySQL 返回 JSON,Postgres 返回 JSONB。查询和更新表达式也针对不同数据库生成特定 SQL,如 MySQL 使用 JSON_EXTRACT,Postgres 使用 json_extract_path_text。这意味着自定义类型需考虑多数据库兼容性,否则可能在不同数据库上出现行为差异。

❓

Q&A

GORM 默认支持哪些 Go 数据类型?

GORM 默认支持 Go 的基本类型,包括 bool、string、各种 int 和 uint 类型、byte、rune、float32、float64、complex64、complex128。

GORM 处理复杂对象有哪些解决方案?

GORM 提供两种解决方案:一是通过接口让用户自定义支持的数据类型;二是使用社区提供的自定义数据类型库,如 datatypes 和 pq。

datatypes 库和 pq 库有什么区别?

datatypes 是 GORM 社区扩展的数据类型库,使用 JSON 表示复杂数据结构,包括 JSON、DateTime、JSON_SET、JSONType[T]、JSONSlice[T]、JSONArray 等。pq 是 Postgres 的 Go 驱动库,支持 GORM 数据类型(Scanner、Valuer 接口),主要包括 Hstore、NullTime、Array 等。

如何通过接口实现 GORM 自定义数据类型?

GORM 从三个维度支持自定义数据类型:1. 解析和保存数据到数据库,实现 Scanner 和 Valuer 接口;2. 定义数据库字段类型,实现 GormDBDataTypeInterface 或 GormDataTypeInterface;3. 复杂数据类型的读取或查询,实现 clause.Expression 接口。

GORM 中如何查询 JSON 字段?

可以使用 JSONQuery 函数构建查询表达式,通过 Extract、HasKey、Equals、Likes 等方法指定查询条件,并实现 clause.Expression 接口的 Build 方法来生成不同数据库的 SQL。

GORM 中如何更新 JSON 字段?

可以使用 JSONSet 函数构建更新表达式,通过 Set 方法指定路径和值,并实现 clause.Expression 接口的 Build 方法来生成不同数据库的更新 SQL。

🏷️

标签

➡️

继续阅读