質問するログイン新規登録

Q&A

0回答

1393閲覧

golang(ORM:gorm)で、構造体の設計と実装を簡潔にしたい。

退会済みユーザー

退会済みユーザー

総合スコア0

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

0グッド

0クリップ

投稿2021/04/07 14:10

0

0

前提・実現したいこと

golang(フレームワークはginです)で、
DBへinsertする際のstructやfunctionについて、より簡潔に、わかりやすく、疎結合に書きたいです。
しかし知見がなく、お詳しい方、良い方法をご教示願えませんでしょうか。

前提としては、下記のようなstructがあります。ORMはgormです。

go

1package entity 2 3import "github.com/jinzhu/gorm" 4 5// マイグレーション用 6type Post struct { 7 UserId uint64 `gorm:"type:int; "` //型は変更不可 8 PostImageId int `gorm:"type:int; "`//型は変更不可 9 DogName string `gorm:"type:varchar(30); "`//型は変更不可 10 OtherMessage string `gorm:"type:varchar(4000);"`//型は変更不可 11}

go

1package main 2router.POST("/addRecord", controller.Create)// レコードをDBへ登録する

発生している問題・エラーメッセージ

controllerでは、クライアントから受けたパラメタを
上記に示したstructentity.Post(マイグレーション用の構造体)型の変数recordに入れ、
下記の通りDBへInsertしています。
ここで面倒なこととして、受けたパラメタはstring型
entity.Postの各フィールドはuint型int型があるため、全て各フィールドに沿った変換をする必要があります。

go

1package controller 2 3func Create(c *gin.Context) { 4 userId, _ := strconv.ParseUint(c.PostForm("user_id"), 10, 64) //stringからUintに変換する 5 postImageId, _ := strconv.ParseInt(c.PostForm("post_image_id")) //stringからintに変換する 6 7 // テーブルに登録するためのレコード情報 8 var record = entity.Post{ 9 UserId: userId, //変換したUintを格納する 10 PostImageId: postImageId,//変換したintを格納する 11 DogName: c.PostForm("dog_name"), 12 OtherMessage: c.PostForm("other_message"), 13 } 14 db.InsertRecord(&record) // -> 下記コードブロックへ 15 c.JSON(http.StatusCreated, "*****created") 16}

go

1package db 2 3func InsertRecord(registerRecord *entity.Post) { //entity.Post型の引数で受ける 4 db := open() 5 db.Create(&registerRecord) // insert 6 defer db.Close() 7}

controllerで行っているこの型変換作業の羅列は美しくなく(実際は膨大な量のフィールドを変換しています)、
またマイグレーション用のstructをCRUDにも使っていることは、あまりよくないと感じています。

試したこと

以下、テーブル設計のためのstructと、insertのためのstructを切り分けるために、私が考えた案です。
お詳しいかた、どのような方法が賢いか、ご教示願えませんでしょうか。


案A:INSERT用のstructを使用する。
今使用しているstructentity.Post(マイグレーション用struct)を使用せず、
entity.DTOPostというstructを用意します。
全てstringなので、Create()では、受けたパラメタを変換せずそのまま格納できます。

go

1package entity 2 3// CRUD用(編集中) 4type DTOPost struct { 5 UserId string 6 PostImageId string 7 DogName string 8 OtherMessage string 9}

しかし、gorm(ORM)の機能上、struct名がそのままinsert先のテーブル名指定になります
つまり、ここでは本当はPostテーブルにinsertしたいが、DTOPostテーブルにinsertしてしまうことになります。
公式をみたところ、insert先のテーブル名を指定できる機能はなさそうでした。
https://gorm.io/ja_JP/docs/create.html


案B:パッケージを分ける
同じパッケージに同名structを持つことはできないので、
ディレクトリ(パッケージ)を分けて、structPostを作成する。

go

1package other 2 3// CRUD用(編集中) 4type Post struct { 5 UserId string 6 PostImageId string 7 DogName string 8 OtherMessage string 9}

go

1package db 2 3func InsertRecord(registerRecord *other.Post) { //other.Post型の引数で受ける 4 db := open() 5 db.Create(&registerRecord) // insert 6 defer db.Close() 7}

(B案は試していませんが、洗練された方法ではないかな、と感じています。)


案C:その他


今はinsertのためにマイグレーション用structをそのまま使っており、
そもそもマイグレーション用の構造体をinsertでも使用することに違和感もあります。

長々とすみません、
お詳しいかた、どのような方法が賢いか、ご教示願えませんでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.29%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問