从GORM的Raw()查询中检索数据

huangapple go评论81阅读模式
英文:

Retrieving data from GORM Raw() Query

问题

我正在尝试通过项目学习来学习Golang。我给自己提出了一个问题,模拟顾客将产品添加到购物车中。目前,我有一个名为Cart.go的模型,如下所示:

type Cart struct {
    ID         string    
    Customer   Customer  
    CustomerID string    
    Product    Product   
    ProductID  string    
    CreatedAt  time.Time 
    UpdatedAt  time.Time
}

在Cart模型中,我定义了一个函数:

func (c *Cart) GetAllItemsInCart(db *gorm.DB, customer_id string) (*gorm.DB, error) {
    items := db.Raw("SELECT id, product_id FROM carts WHERE customer_id = ?", customer_id).Scan(&c)

    return items, nil
}

这个函数在一个控制器中被调用:

func (server *Server) GetAllCartItems(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)

    id := vars["id"]

    cart := models.Cart{}

    items, err := cart.GetAllItemsInCart(server.DB, id)

    if err != nil {
        responses.ERROR(w, http.StatusInternalServerError, err)
        return
    }

    responses.JSON(w, http.StatusOK, items)
}

据我了解,Scan()函数将扫描结构体的值,或者在这种情况下将加载找到的数据到指定的结构体中。然而,我收到的响应是:

{
    "Value": null,
    "Error": null,
    "RowsAffected": 2
}

这给了我50%的希望,因为"RowsAffected": 2是正确的。然而,显然返回的有效载荷响应不是我想要的。任何指导将不胜感激,谢谢。

英文:

I am trying to learn Golang via project based learning. The problem I have placed before myself to simulate customers adding products to their cart. Currently, I have the Cart.go model as such..

type Cart struct {
     ID         string    
     Customer   Customer  
     CustomerID string    
     Product    Product   
     ProductID  string    
     CreatedAt  time.Time 
     UpdatedAt  time.Time
}

On the Cart model, I have a function defined as

func (c *Cart) GetAllItemsInCart(db *gorm.DB, customer_id string) (*gorm.DB, error) {
    items := db.Raw("SELECT id, product_id FROM carts WHERE customer_id = ?", customer_id).Scan(&c)

    return items, nil
}

This function is called in a controller

func (server *Server) GetAllCartItems(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)

    id := vars["id"]

    cart := models.Cart{}

    items, err := cart.GetAllItemsInCart(server.DB, id)

    if err != nil {
	    responses.ERROR(w, http.StatusInternalServerError, err)
	    return
    }

    responses.JSON(w, http.StatusOK, items)
}

As I understand it currently is that Scan() will scan the value of a struct, or in this case load the data found into the specified struct. However, the response I am seeing come back is

 {
    "Value": null,
    "Error": null,
    "RowsAffected": 2
 }

Which gives me 50% hope because "RowsAffected": 2 would be correct. However, the payload response is obviously not what I am looking for. Any guidance would be greatly appreciated, thank you.

答案1

得分: 1

Scan将值放入你提供的变量指针(通过via &c),并返回一个数据库事务对象。你将该事务对象称为items,但实际上它并不是itemsitems(即购物车的内容)在c *Cart中,而不是在Scan返回的对象中。

你的方法通过填充c来修改它,不需要返回任何东西,除非你想返回Scan可能返回的错误。

所以,你应该这样做:

err := cart.GetAllItemsInCart(server.DB, id)

// ... 

responses.JSON(w, http.StatusOK, cart)
英文:

Scan places the value into the pointer to a variable you've given it (via &c), and returns a database transaction object. You're calling that transaction object items, which it isn't. The items (ie, the contents of your cart) are in c *Cart, not in the thing returned by Scan.

Your method modifies c by filling it, it doesn't have to return anything, unless you want to return the error that Scan may return.

Instead of this...

    items, err := cart.GetAllItemsInCart(server.DB, id)

    // ... 

    responses.JSON(w, http.StatusOK, items)

You should be doing this:

    err := cart.GetAllItemsInCart(server.DB, id)

    // ...

    responses.JSON(w, http.StatusOK, cart)

答案2

得分: 0

你需要修复几个问题:

  • 你需要使用Scan(c)而不是Scan(&c),因为c已经是一个指针。
  • 你应该始终检查错误。在你的GetAllItemsInCart方法中,你没有传递或检查错误。从技术上讲,你确实传递了它(在items对象内部),但你没有在任何地方检查它。
  • 没有必要将*gorm.DB指针传递到更高层。

如果你想保留代码的结构,可以像这样修改:

func (c *Cart) GetAllItemsInCart(db *gorm.DB, customer_id string) error {
    return db.Raw("SELECT id, product_id FROM carts WHERE customer_id = ?", customer_id).Scan(c).Error
}

// controller
func (server *Server) GetAllCartItems(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)

    id := vars["id"]

    cart := models.Cart{}

    err := cart.GetAllItemsInCart(server.DB, id)
    if err != nil {
        responses.ERROR(w, http.StatusInternalServerError, err)
        return
    }

    responses.JSON(w, http.StatusOK, cart)
}
英文:

You will need to fix a couple of things:

  • You will need to use Scan(c) instead of Scan(&c) since c is already a pointer.
  • You should always check for errors. In your GetAllItemsInCart method, you don't pass or check the error. Technically, you do pass it (inside the items object), but you do not check it anywhere.
  • There is no need to pass the *gorm.DB pointer higher up.

If you want to preserve the structure of the code the way you already started, it could look something like this:

func (c *Cart) GetAllItemsInCart(db *gorm.DB, customer_id string) error {
    return db.Raw("SELECT id, product_id FROM carts WHERE customer_id = ?", customer_id).Scan(c).Error
}

// controller
func (server *Server) GetAllCartItems(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)

    id := vars["id"]

    cart := models.Cart{}

    err := cart.GetAllItemsInCart(server.DB, id)
    if err != nil {
        responses.ERROR(w, http.StatusInternalServerError, err)
        return
    }

    responses.JSON(w, http.StatusOK, cart)
}

huangapple
  • 本文由 发表于 2021年6月14日 10:17:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/67964078.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定