2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

WanoグループAdvent Calendar 2020

Day 20

gormで一時的にPreloadやsave_assosiationの関係性を構築する

Last updated at Posted at 2020-12-20

この記事はWanoグループ Advent Calendar 2020 20日目の記事になります。20ったら20です。

突然ですが、ここに、image_assetというモデルがあるとします。
集約です。

image_asset
{
  "id": 13,
  "user_id": 1,
  "asset_id": 28,
  "asset": {
    "bucket": "988323dc-42e1-11eb-9c12-8c859050389c",
    "location": "852cb6b4-f0d0-4ace-a1c3-2966c7027985",
    "mime_type": "test/mimetype/image/repo",
    "upload_datetime": null,
    "filename": "988323e6-42e1-11eb-9c12-8c859050389c",
    "s3_storage_class_id": 1,
    "is_exist": false,
    "file_size_byte": null,
    "md5_hash": "8b1a5be6-5b44-45e0-9325-ec9428e378ff"
  },
  "image_asset_type_id": 1,
  "orig_image_asset_id": null,
  "width": 66780,
  "height": 12087,
  "image_asset_category_id": null,
  "from_tcj": false
}

image_assetはassetを持ちます。
image_assetとassetはmysqlのテーブル上も別ですが、集約なのでライフサイクル上も一緒とします。


package mysqldto

import (
	"database/sql"
	"gopkg.in/guregu/null.v3"
	"time"
)

var (
	_ = time.Second
	_ = sql.LevelDefault
	_ = null.Bool{}
)



type ImageAsset struct {
	ID                   int        `gorm:"primary_key;AUTO_INCREMENT;column:id;type:uint;" json:"id"`
	CreateTime           *time.Time `gorm:"column:create_time;type:datetime;default:CURRENT_TIMESTAMP;" json:"create_time"`
	UpdateTime           *time.Time `gorm:"column:update_time;type:timestamp;default:CURRENT_TIMESTAMP;" json:"update_time"`
	UserID               int        `gorm:"column:user_id;type:uint;" json:"user_id"`
	AssetID              int        `gorm:"column:asset_id;type:uint;" json:"asset_id"`
	ImageAssetTypeID     int        `gorm:"column:image_asset_type_id;type:utinyint;" json:"image_asset_type_id"`
	Width                int        `gorm:"column:width;type:uint;default:0;" json:"width"`
	Height               int        `gorm:"column:height;type:uint;default:0;" json:"height"`
	ImageAssetCategoryID null.Int   `gorm:"column:image_asset_category_id;type:utinyint;" json:"image_asset_category_id"`
	FromTcj              bool       `gorm:"column:from_tcj;type:utinyint;default:0;" json:"from_tcj"`
}


type Asset struct {
	ID               int         `gorm:"primary_key;AUTO_INCREMENT;column:id;type:uint;" json:"id"`
	CreateTime       *time.Time  `gorm:"column:create_time;type:datetime;default:CURRENT_TIMESTAMP;" json:"create_time"`
	UpdateTime       *time.Time  `gorm:"column:update_time;type:timestamp;default:CURRENT_TIMESTAMP;" json:"update_time"`
	Bucket           string      `gorm:"column:bucket;type:varchar;size:100;" json:"bucket"`
	Location         string      `gorm:"column:location;type:varchar;size:1023;" json:"location"`
	MimeType         string      `gorm:"column:mime_type;type:varchar;size:50;" json:"mime_type"`
	UploadDatetime   null.Time   `gorm:"column:upload_datetime;type:datetime;" json:"upload_datetime"`
	Filename         null.String `gorm:"column:filename;type:varchar;size:255;" json:"filename"`
	IsExist          bool        `gorm:"column:is_exist;type:utinyint;default:1;" json:"is_exist"`
	S3StorageClassID int         `gorm:"column:s3_storage_class_id;type:utinyint;default:1;" json:"s_3_storage_class_id"`
	FileSizeByte     null.Int    `gorm:"column:file_size_byte;type:ubigint;" json:"file_size_byte"`
	Md5Hash          null.String `gorm:"column:md5_hash;type:varchar;size:512;" json:"md_5_hash"`
}

ただし、mysqlのdtoを表現する構造体は以上のように愚直に別テーブルでsave_associationとかのタグ魔法もないとします。
ImageAssetをAssetと共にSave,Getするにはどうするでしょうか?
まあ普通に別途クエリを書けばいいんですが...

上書き

package mysql_repositoy


type imageAssetAggregate struct {
	*mysqldto.ImageAsset
	Asset mysqldto.Asset `gorm:"ForeignKey:AssetID;save_associations:true"`
}
...

	gormDB = gormDB.Table(`image_asset`).
		Preload(`Asset`).
		Joins(`INNER JOIN asset ON asset.id = image_asset.asset_id`)

gormのtipsでもなんでもないんですが、単に一時的に構造体作って埋め込むだけでも、gormの魔法タグを使った同時SaveやPreloadによる雑な子集約の収集は実現できます。

...なんでこういうことしてるかというと、modelとdtoの分離の文脈とか、dtoは純粋にmysqlテーブルの形にしておきたいとか、でもでもActiveRecordっぽいEager Loadingは欲しいときあるよね!とかいろいろ経緯や事情があるんですが、まあこういうこともできるよという話でした。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?