gorm:将数据库存储模型和查询发送模型分开。

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

gorm : seperate in-database storing model and query sending model

问题

发送gorm模型的有效方法是什么,其中该模型与用于存储数据库中数据的gorm模型不同?

这个Post模型(结构体)用于存储数据库中的数据。

type Post struct {
    gorm.Model
    Title string 
    Body  string 
}

但是我想使用这个PostRead gorm模型,将其发送回用户。因为以后可能会添加额外的变量,这些变量不会存储在这个数据库中(或者额外的变量可能来自其他服务或数据库)。

type PostRead struct {
    ID        string    `json:"id" gorm:"primary_key"`
    Title     string    `json:"title"`
    Body      string    `json:"body"`
    CreatedAt time.Time `json:"createAt"`
    UpdatedAt time.Time `json:"updatedAt"`
    ...
    // 以后要添加的其他变量
}

这是我当前的控制器代码,用于发送数据:

func PostGetAll(c *gin.Context) {
    posts, err := services.PostGetAllService()

    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err})
        return
    }

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

这是我从数据库获取数据的服务代码:

func PostGetAllService() ([]models.Post, error) {
    var posts []models.Post
    result := initializers.DB.Find(&posts)

    if result.Error != nil {
        return nil, errors.New(result.Error.Error())
    }

    return posts, nil
}

注意:我知道我可以在控制器函数PostGetAll()中创建一个PostRead的切片数组,然后使用append()postsPost)中的数据添加到切片数组中。
但对我来说,这似乎是一种冗余的解决方法,因此我想知道是否存在更好的解决方案?

更好的高效解决方案

英文:

What is an efficient way of sending a gorm model, which the model is not the same with a gorm model using to store datas in database ?

This Post model (struct) is used to store datas in DB.

type Post struct {
	gorm.Model
	Title string 
	Body  string 
}

But I want to use this PostRead gorm model, to be sent to back to user instead. Since there could be extra variables adding to this later, which won't be store in this database. (or the extra variables could be from another services or databases)

type PostRead struct {
	ID    string `json:"id" gorm:"primary_key"`
	Title string `json:"title"`
	Body  string `json:"body"`
	CreatedAt time.Time `json:"createAt"`
	UpdatedAt time.Time `json:"updatedAt"`
    ...
    <other variables to be added later>
}

Here's my current controller codes, to send data back :

func PostGetAll(c *gin.Context) {
	posts, err := services.PostGetAllService()

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err})
		return
	}

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

And here's my service codes, to get datas from database :

func PostGetAllService() ([]models.Post, error) {
	var posts []models.Post
	result := initializers.DB.Find(&posts)

	if result.Error != nil {
		return nil, errors.New(result.Error.Error())
	}

	return posts, nil
}

NOTE : I knew that I could create a SliceArray of PostRead in the controller function PostGetAll(), then use append() to add datas from posts (Post) into the SliceArray.
But for me this seems to be abundant way of solving this problem, hence I wonder if there is a better solution existed ?

Better efficient solution

答案1

得分: 1

我不完全确定你的问题,但我会尽力帮助你。

通常我会按照以下方式进行操作,但我相信还有更好的方法。

对于模型,我会将它们准备在一个类似以下的 pkg 中。

// 用于从表单中读取数据。
type CreatePostForm struct {
    Title string `json:"title"`
    Body  string `json:"body"`
}

// 用于与数据库交互。
type Post struct {
    gorm.Model
    Title string 
    Body  string
}

type Posts []Post

// 用于数据传输对象(发送到 UI 等)。
type PostDto struct {
    Title       string 
    Body        string
    CreatedDate time.Time
    CreatedBy   string
}

type PostsDto []PostDto

// 将表单数据转换为数据库模型以进行数据库操作。
func (p PostCreateForm) ToCreateModel() (*Post, error) {
    // 在这里处理逻辑,基本上是创建一个新的 Post 模型并返回它。
}

// 将数据库模型转换为 DTO 以回复请求等。
func (p Post) ToDto() (*PostDto, error) {
    // 在这里处理逻辑,基本上是创建一个新的 PostDto 模型并返回它。
}

// 将多个 Posts 转换为多个 DTOs。
func (ps Posts) ToDto() PostsDto {
    dtos := make(PostsDto, len(ps))
    for key, post := range ps {
        dtos[key] = post.ToDto()
    }

    return dtos
}

所以基本上在从数据库获取数据后,你可以通过使用 Posts.ToDto() 这样的方法将类型 Posts 转换为类型 PostsDto

数据库适配器将位于另一个 pkg 中,它基本上负责读取/写入数据库的工作,但我不会分享它,因为你的问题更多是关于发送另一组数据进行 CRUD 操作。

希望这能帮到你,但我仍然认为可能有更好的方法来做这件事。

英文:

Not entirely sure of your question but let me try to help anyway.

Normally I would do the following but I am sure there are better ways to do it.

For models I will prepare them in a pkg like the following.

// For reading data from form.
type CreatePostForm struct {
    Title string `json:"title"`
    Body  string `json:"body"`
}

// For interactions with database.
type Post struct {
    gorm.Model
    Title string 
    Body  string
}

type Posts []Post

// For data transfer object (sending over to UI etc).
type PostDto struct {
    Title       string 
    Body        string
    CreatedDate time.Time
    CreatedBy   string
}

type PostsDto []PostDto

// Convert form data into database model for database operations.
func (p PostCreateForm) ToCreateModel() (*Post, error) {
    // Process logic here which is basically creating a new Post model and returning it..
}

// Convert database model into DTO to reply to request etc.
func (p Post) ToDto() (*PostDto, error) {
    // Process logic here which is basically creating a new PostDto model and returning it..
}

// Convert many Posts to many DTOs.
func (ps Posts) ToDto() PostsDto {
    dtos := make(PostsDto, len(ps))
    for key, post := range ps {
	    dtos[key] = post.ToDto()
    }

    return dtos
}

So basically from the above after your get the data from the database you can basically converts type Posts to type PostsDto through the use of methods like Posts.ToDto().

The DB adaptor will be in another pkg which basically does the work for reading/writing to the database which I will not share since your question is more of sending another set of data for CRUD operations.

Again, I hope this will help you but I still think there might be a better way to do it.

huangapple
  • 本文由 发表于 2022年11月14日 11:32:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/74426659.html
匿名

发表评论

匿名网友

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

确定