GORM GIN 更新查询导致 500 内部服务器错误。

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

GORM GIN Update Query Results in 500 Internal Server Error

问题

我正在使用Gin和GORM在Golang中构建一个Book API。我已经成功实现了API的创建、获取和删除部分,但更新部分导致了500 Internal Server Error。我正在尝试实现一个只更新请求体中提供的特定标签的更新功能(如下面的示例所示)。非常感谢任何帮助或指导。

GO日志

[31m2022/05/09 14:08:00 [Recovery] 2022/05/09 - 14:08:00 panic recovered:
PATCH /books/2 HTTP/1.1
Host: 127.0.0.1:8080
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 66
Content-Type: text/plain;charset=UTF-8
Origin: chrome-extension://ihgpcfpkpmdcghlnaofdmjkoemnlijdi
Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: none
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36


reflect: call of reflect.Value.SetString on uint Value
C:/Program Files/Go/src/reflect/value.go:221 (0xc7bb04)
        flag.mustBe: panic(&ValueError{methodName(), f.kind()})
C:/Program Files/Go/src/reflect/value.go:1747 (0xc7ba3e)
        Value.SetString: v.mustBe(String)
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/schema/field.go:771 (0x10defb7)
        (*Field).setupValuerAndSetter.func11: field.ReflectValueOf(ctx, value).SetString(data)
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks/update.go:144 (0x115b68e)
        ConvertToAssignments.func2: field.Set(stmt.Context, stmt.ReflectValue, value)
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks/update.go:275 (0x11534f9)
        ConvertToAssignments: assignValue(field, value)
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks/update.go:73 (0x115ac9e)
        Update.func1: if set := ConvertToAssignments(db.Statement); len(set) != 0 {
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks.go:130 (0x10ebe14)
        (*processor).Execute: f(db)
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/finisher_api.go:372 (0x10f4e8d)
        (*DB).Updates: return tx.callbacks.Update().Execute(tx)
C:/New folder/golang/github.com/shashank-kakarla/BookAPI/controllers/books.go:101 (0x1167007)
        UpdateBook: models.DB.Model(&book).Updates(input)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x10917e1)
        (*Context).Next: c.handlers[c.index](c)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/recovery.go:99 (0x10917c7)
        CustomRecoveryWithWriter.func1: c.Next()
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x10908c6)
        (*Context).Next: c.handlers[c.index](c)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/logger.go:241 (0x1090885)
        LoggerWithConfig.func1: c.Next()
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x1086689)
        (*Context).Next: c.handlers[c.index](c)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:555 (0x108666f)
        (*Engine).handleHTTPRequest: c.Next()
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:511 (0x1086112)
        (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
C:/Program Files/Go/src/net/http/server.go:2867 (0xe76e29)
        serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
C:/Program Files/Go/src/net/http/server.go:1932 (0xe721ac)
        (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
C:/Program Files/Go/src/runtime/asm_amd64.s:1371 (0xc3d900)
        goexit: BYTE    $0x90   // NOP
←[0m
[GIN] 2022/05/09 - 14:08:00 |←[97;41m 500 ←[0m|     19.7185ms |       127.0.0.1 |←[97;42m PATCH   ←[0m "/books/2"

GO模型

func UpdateBook(c *gin.Context) {
	// 如果存在,则获取模型
	var book models.Book
	if err := models.DB.Where("id = ?", c.Param("id")).First(&book).Error; err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "记录未找到"})
		return
	}

	// 验证输入
	var input UpdateBookInput
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	models.DB.Model(&book).Updates(input)

	c.JSON(http.StatusOK, gin.H{"data": book})
}

UpdateBookInput 结构体

type UpdateBookInput struct {
	Title  string `json:"title"`
	Author string `json:"author"`
}

main.go

func main() {

	router := gin.Default()

	models.ConnectDatabase()

	router.GET("/books", controllers.FetchBooks)
	router.GET("/books/:id", controllers.FindBookByID)
	router.GET("/books/title/:title", controllers.FindBookByTitle)
	router.GET("/books/author/:author", controllers.FindBookByAuthor)

	router.POST("/books", controllers.CreateBook)

	router.PATCH("/books/:id", controllers.UpdateBook)

	router.DELETE("/books/:id", controllers.RemoveBook)

	router.Run()
}

请求URL和Body
URL

PATCH http://127.0.0.1:8080/books/2

BODY

{
    "title": "Breaking Dawn",
}

模式/模型

package models

type Book struct {
	ID     uint   `json:"id" gorm:"primary_key"`
	Title  string `json:"title"`
	Author string `json:"author"`
}

英文:

I am building a Book API in Golang using Gin and GORM. I have successfully implemented the Create, get and delete parts of the API but the Update is resulting in 500 Internal Server Error. I am trying to for a Update functionality which only updates the specific tags provided in the body(example given below). Any help or guidance is greatly appreciated.

GO Logs

[31m2022/05/09 14:08:00 [Recovery] 2022/05/09 - 14:08:00 panic recovered:
PATCH /books/2 HTTP/1.1
Host: 127.0.0.1:8080
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 66
Content-Type: text/plain;charset=UTF-8
Origin: chrome-extension://ihgpcfpkpmdcghlnaofdmjkoemnlijdi
Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: none
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36


reflect: call of reflect.Value.SetString on uint Value
C:/Program Files/Go/src/reflect/value.go:221 (0xc7bb04)
        flag.mustBe: panic(&ValueError{methodName(), f.kind()})
C:/Program Files/Go/src/reflect/value.go:1747 (0xc7ba3e)
        Value.SetString: v.mustBe(String)
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/schema/field.go:771 (0x10defb7)
        (*Field).setupValuerAndSetter.func11: field.ReflectValueOf(ctx, value).SetString(data)
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks/update.go:144 (0x115b68e)
        ConvertToAssignments.func2: field.Set(stmt.Context, stmt.ReflectValue, value)
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks/update.go:275 (0x11534f9)
        ConvertToAssignments: assignValue(field, value)
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks/update.go:73 (0x115ac9e)
        Update.func1: if set := ConvertToAssignments(db.Statement); len(set) != 0 {
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks.go:130 (0x10ebe14)
        (*processor).Execute: f(db)
C:/Users/NK086843/go/pkg/mod/gorm.io/gorm@v1.23.5/finisher_api.go:372 (0x10f4e8d)
        (*DB).Updates: return tx.callbacks.Update().Execute(tx)
C:/New folder/golang/github.com/shashank-kakarla/BookAPI/controllers/books.go:101 (0x1167007)
        UpdateBook: models.DB.Model(&book).Updates(input)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x10917e1)
        (*Context).Next: c.handlers[c.index](c)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/recovery.go:99 (0x10917c7)
        CustomRecoveryWithWriter.func1: c.Next()
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x10908c6)
        (*Context).Next: c.handlers[c.index](c)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/logger.go:241 (0x1090885)
        LoggerWithConfig.func1: c.Next()
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x1086689)
        (*Context).Next: c.handlers[c.index](c)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:555 (0x108666f)
        (*Engine).handleHTTPRequest: c.Next()
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:511 (0x1086112)
        (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
C:/Program Files/Go/src/net/http/server.go:2867 (0xe76e29)
        serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
C:/Program Files/Go/src/net/http/server.go:1932 (0xe721ac)
        (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
C:/Program Files/Go/src/runtime/asm_amd64.s:1371 (0xc3d900)
        goexit: BYTE    $0x90   // NOP
←[0m
[GIN] 2022/05/09 - 14:08:00 |←[97;41m 500 ←[0m|     19.7185ms |       127.0.0.1 |←[97;42m PATCH   ←[0m "/books/2"

GO Models

func UpdateBook(c *gin.Context) {
	// Get model if exist
	var book models.Book
	if err := models.DB.Where("id = ?", c.Param("id")).First(&book).Error; err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Record not found!"})
		return
	}

	// Validate input
	var input UpdateBookInput
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	models.DB.Model(&book).Updates(input)

	c.JSON(http.StatusOK, gin.H{"data": book})
}

UpdateBookInput Struct

type UpdateBookInput struct {
	Title  string `json:"title"`
	Author string `json:"author"`
}

main.go

func main() {

	router := gin.Default()

	models.ConnectDatabase()

	router.GET("/books", controllers.FetchBooks)
	router.GET("/books/:id", controllers.FindBookByID)
	router.GET("/books/title/:title", controllers.FindBookByTitle)
	router.GET("/books/author/:author", controllers.FindBookByAuthor)

	router.POST("/books", controllers.CreateBook)

	router.PATCH("/books/:id", controllers.UpdateBook)

	router.DELETE("/books/:id", controllers.RemoveBook)

	router.Run()
}

Request URL and Body
URL

PATCH http://127.0.0.1:8080/books/2

BODY

{
    "title": "Breaking Dawn",
}

Schema/Model

package models

type Book struct {
	ID     uint   `json:"id" gorm:"primary_key"`
	Title  string `json:"title"`
	Author string `json:"author"`
}

答案1

得分: 1

我猜测JSON数据中包含一个类型为字符串的ID字段,因为这里唯一的uint字段是ID。要么gorm在更新时表现奇怪,要么是类似这样的情况。

确保输入是干净的。

英文:

I suppose the JSON data contains an ID field which is of type string, because the only uint field is ID here. Either gorm is behaving weird with Updates or its something like this.

Make sure the input is clean.

答案2

得分: 0

将UpdateBookInput对象转换为models.Book对象,而不是直接传递它。

英文:

Instead of passing the UpdateBookInput object directly, convert it to a models.Book object.

huangapple
  • 本文由 发表于 2022年5月10日 03:18:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/72177199.html
匿名

发表评论

匿名网友

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

确定