Golang中如何使用gorm动态添加查询参数

Golang中如何使用gorm动态添加查询参数 我希望根据接收到的参数动态构建查询。例如,[SELECT (参数) FROM (参数) WHERE (参数)],而不是为每个用例反复编写查询,我希望使其完全动态化。最让我关注的部分是 WHERE 子句,因为它可能包含不同的查询操作(AND、OR、%LIKE 等)。

我希望使用 GORM 来实现这一点,以防止 SQL 注入。

func main() {
    fmt.Println("hello world")
}
5 回复

假设你的 QueryBuilder 函数完全按照你期望的方式工作,你会如何调用它并使用其结果?

更多关于Golang中如何使用gorm动态添加查询参数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我使用一个结构体来获取参数,并根据这些参数,通过将它们传递给一个QueryBuilder函数来生成结果。

@fahad-fk 你是在找这个吗?它已经允许你输入任意的SQL表达式和参数。如果不是,你能说明一下你寻找的功能与此有何不同吗?

我将展示我的代码,希望你能理解。我编写了一段代码,但这不是完成此任务的完美方式。有一个名为 DynamicQuery() 的函数,它获取 JSON 参数用于选择、条件、或操作,并将它们绑定到一个结构体中,之后我将其传递给第二个名为 QueryBuilder() 的函数。

query one

现在,在第二个函数中,借助 sprint.f(),我构建了 db.where() 的结构,正如你通过代码所看到的,以便使用 ORM 运行它。我认为,过度使用 sprint.f() 会导致查询中容易受到 SQL 注入攻击。

query 2

在Golang中使用GORM动态构建查询参数,可以通过链式调用和条件构建来实现。以下是一个完整的示例:

package main

import (
    "fmt"
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
    "gorm.io/gorm/clause"
)

type User struct {
    ID    uint
    Name  string
    Age   int
    Email string
}

func main() {
    db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }

    // 自动迁移
    db.AutoMigrate(&User{})

    // 动态查询示例
    query := db.Model(&User{})
    
    // 动态添加WHERE条件
    conditions := map[string]interface{}{
        "age > ?":    18,
        "name LIKE ?": "%John%",
        "email IS NOT NULL": nil,
    }
    
    for condition, value := range conditions {
        if value == nil {
            query = query.Where(condition)
        } else {
            query = query.Where(condition, value)
        }
    }
    
    // 动态排序
    query = query.Order("age DESC")
    
    // 动态选择字段
    query = query.Select("id, name, age")
    
    // 执行查询
    var users []User
    if err := query.Find(&users).Error; err != nil {
        fmt.Printf("查询失败: %v\n", err)
        return
    }
    
    fmt.Printf("找到 %d 个用户\n", len(users))
}

// 更复杂的动态查询构建函数
func dynamicQuery(db *gorm.DB, filters map[string]interface{}) *gorm.DB {
    query := db.Model(&User{})
    
    for field, value := range filters {
        switch field {
        case "name":
            if name, ok := value.(string); ok && name != "" {
                query = query.Where("name LIKE ?", "%"+name+"%")
            }
        case "age_min":
            if age, ok := value.(int); ok {
                query = query.Where("age >= ?", age)
            }
        case "age_max":
            if age, ok := value.(int); ok {
                query = query.Where("age <= ?", age)
            }
        case "email":
            if email, ok := value.(string); ok && email != "" {
                query = query.Where("email = ?", email)
            }
        }
    }
    
    return query
}

// 使用Scopes进行动态查询
func WithFilters(filters map[string]interface{}) func(db *gorm.DB) *gorm.DB {
    return func(db *gorm.DB) *gorm.DB {
        for key, value := range filters {
            switch key {
            case "search":
                db = db.Where("name LIKE ? OR email LIKE ?", 
                    "%"+value.(string)+"%", 
                    "%"+value.(string)+"%")
            case "active":
                db = db.Where("active = ?", value)
            }
        }
        return db
    }
}

// 使用示例
func queryWithScopes(db *gorm.DB) {
    var users []User
    filters := map[string]interface{}{
        "search": "john",
        "active": true,
    }
    
    db.Scopes(WithFilters(filters)).Find(&users)
}

// 动态OR条件
func dynamicOrConditions(db *gorm.DB) {
    var users []User
    
    db.Where(
        db.Where("name = ?", "John").Or("name = ?", "Jane"),
    ).Where("age > ?", 20).Find(&users)
}

// 使用clause进行复杂动态查询
func dynamicClauseQuery(db *gorm.DB, conditions []clause.Expression) *gorm.DB {
    return db.Clauses(clause.Where{
        Exprs: conditions,
    })
}

// 构建动态表达式
func buildDynamicExpressions(params map[string]interface{}) []clause.Expression {
    var exprs []clause.Expression
    
    if name, ok := params["name"].(string); ok && name != "" {
        exprs = append(exprs, clause.Like{
            Column: "name",
            Value:  "%" + name + "%",
        })
    }
    
    if age, ok := params["age"].(int); ok && age > 0 {
        exprs = append(exprs, clause.Gt{
            Column: "age",
            Value:  age,
        })
    }
    
    return exprs
}

这个示例展示了多种动态构建查询的方法:

  1. 基础WHERE条件:使用Where()方法链式调用
  2. 动态条件映射:通过map结构传递查询条件
  3. Scopes作用域:使用Scopes封装可复用的查询逻辑
  4. 复杂OR条件:动态构建OR查询
  5. Clause表达式:使用GORM的clause包构建复杂表达式

GORM会自动处理参数化查询,防止SQL注入。所有用户输入都会通过预编译语句处理,确保查询安全。

回到顶部