GORM 的链式方法特性可让编码更加流畅自然。 Here are examples using both the Traditional API and the Generics API:
Traditional API
db.Where("name = ?", "jinzhu").Where("age = ?", 18).First(&user) |
Generics API (>= v1.30.0)
ctx := context.Background() |
Both APIs support method chaining, but the Generics API provides enhanced type safety and returns errors directly from operation methods.
方法分类
GORM 将方法分为三大类: Chain Methods
, Finisher Methods
, and New Session Methods
. These categories apply to both the Traditional API and the Generics API.
链式方法
用于修改或追加目前 Clauses
的 Statement
。 一些常见的链式方法包括:
- ``
Select
Omit
Joins
Scopes
Preload
Raw
(提示:Raw
不能与其他链式方法结合使用来构建 SQL)
完整列表,访问 GORM Chainable API。 另外, SQL Builder 文档提供了更多关于 Clauses
的详细信息。
Finisher 方法
终结方法是即时的,执行生成和运行 SQL 命令的注册回调。 此类别包括方法:
Create
First
Find
Take
Save
Update
Delete
Scan
Row
Rows
完整列表, 参考 GORM Finisher API。
新的Session方法
GORM 将 Session
、WithContext
和 Debug
等方法定义为“新会话方法”,它们对于创建可共享和可复用的 *gorm.DB
实例非常重要。 更多详情,请参阅 Session 文档。
可复用性与安全性
Traditional API
A critical aspect of GORM’s Traditional API is understanding when a *gorm.DB
instance is safe to reuse. 在调用 链式方法Chain Method
或 终结方法Finisher Method
之后,GORM 会返回一个已初始化的 *gorm.DB
实例。 这个实例无法安全地重新使用,因为它可能会将先前操作中的状况带回,有可能导致被污染的 SQL 查询。 例如
不安全地复用的例子
queryDB := DB.Where("name = ?", "jinzhu") |
安全再利用的例子
安全地复用 *gorm.DB
实例,通过使用新会话方法:
queryDB := DB.Where("name = ?", "jinzhu").Session(&gorm.Session{}) |
在这种情况下,使用 Session(gorm.Session{})
可以确保每次查询都从全新的上下文开始,避免前一次操作&的条件污染后续 SQL 查询。 这对于维护数据库操作的完整性和准确性至关重要。
Generics API
One of the significant advantages of GORM’s Generics API is that it inherently addresses the SQL pollution issue. With the Generics API, you don’t need to worry about reusing instances unsafely because:
- The context is passed directly to each operation method
- Errors are returned directly from operation methods
- The generic interface design prevents condition pollution
Here’s an example of how the Generics API handles method chaining safely:
ctx := context.Background() |
The Generics API design significantly reduces the risk of SQL pollution, making your database interactions more reliable and predictable.
清晰示例
Let’s clarify with a few examples using both the Traditional API and the Generics API:
Traditional API Examples
- 例子1:安全复用实例
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) |
在这个例子中,每个方法调用链都是独立的,确保干净、无污染的 SQL 查询。
- (Bad) 示例2:不安全的实例复用
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) |
In this bad example, reusing the tx
variable leads to compounded conditions, which is generally not desirable.
- 例3:使用新会话方法安全复用
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) |
在这个例子中,使用新会话方法 Session
, WithContext
, Debug
为每个逻辑操作正确地初始化一个 *gorm.DB
实例,从而防止了条件污染,确保每个查询都是独立的,并且基于所提供的特定条件。
Generics API Examples
- Example 4: Method Chaining with Generics API
ctx := context.Background() |
In this example, the Generics API provides type safety while maintaining the fluent method chaining style. The context is passed directly to the finisher methods (First
, Find
), and errors are returned directly from these methods, following Go’s standard error handling pattern.
Overall, these examples illustrate the importance of understanding GORM’s behavior with respect to method chaining and instance management to ensure accurate and efficient database querying. The Generics API offers a more type-safe and less error-prone approach to method chaining compared to the Traditional API.