LoginSignup
13
9

More than 5 years have passed since last update.

Go言語のgormでORMしてみた(単純検索編)

Last updated at Posted at 2016-08-14

前提

  • Go言語そのものに慣れていない
  • MySQLはVagrantで適当にCentOS6.6に構築
  • MacでGolangの実行環境を整えてトライアンドエラー
  • 利用したのは gorm

いざ実践!

  1. サンプルを写経して、実行。
  2. 検索結果が取得できない。
  3. 他のテーブルを検索するようにしたらWarningが表示された。
実行結果
$ go run db_connect.go
該当レコードなし

(Error 1054: Unknown column 'sample.deleted_at' in 'where clause')
[2016-08-14 19:47:53]
該当レコードなし

なぜ検索結果が存在しないのか?

  • Rubyとかのアクティブレコードベースの概念だけあって、構造体名とテーブル名の関係は単数 <> 複数の形でないといけなかった
  • 単数形のテーブル名を利用したい場合は、単数形のオプションを付けないといけなかった
    • db.SingularTable(true)
    • ※テーブル名を別途指定する方法もあるが省略
誤り箇所1
CREATE TABLE `sample` (
-- 以降省略
誤り箇所2
type Sample struct {
// 以降省略

なぜ警告が表示されるのか?

  • オブジェクト定義の際に、gorm.Modelとしていた箇所のせいで gorm の推奨カラムが追加されていた
誤り箇所
type Sample struct {
    gorm.Model
    ID   uint
    Name string `gorm:"type:varchar(45);"`
}

最終的な実行ソース

db_sample.go
// DBアクセスsample.go
package main

import (
    "fmt"

    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

type Sample struct {
    // メモ:gorm.Modelは構造体で、IDとか勝手に足してくれる存在、CreatedAtとかDeletedAtとか
    // テーブル構造が異なる場合は、自分で専用の構造体を用意しないといけない
    // ただし、SoftDeleteは上手く動かない?(※要調査)
    //  gorm.Model
    ID   uint64 `gorm:"primary_key"`
    Name string `gorm:"type:varchar(45);"`
}

type User struct {
    ID    uint64 `gorm:"primary_key"`
    Email string `gorm:"type:varchar(255);"`
    Name  string `gorm:"type:varchar(45);"`
}

func main() {
    db, err := gorm.Open("mysql", "testuser:testuser@/go_sample?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        panic("failed to connect database")
    }
    // テーブル名が複数系でない場合、これを指定すること
    db.SingularTable(true)

    // 実行ログ出力
    db.LogMode(true)

    var sample Sample
    var count = 0
    db.First(&sample, 2).Count(&count)

    if count == 0 {
        fmt.Println("該当レコードなし")
    } else {
        fmt.Println("id:" + fmt.Sprint(sample.ID))
        fmt.Println("name:" + sample.Name)
    }

    var user User
    db.First(&user).Count(&count)
    if count == 0 {
        fmt.Println("該当レコードなし")
    } else {
        fmt.Println("id:" + fmt.Sprint(user.ID))
    }
}
ddl_sample.sql
CREATE TABLE `sample` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
ddl_user.sql
CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `email` varchar(255) DEFAULT NULL,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

残課題

  • 件数をわざわざ取得しないで存在しないチェックを行いたい
    • ID == 0 でも良いけれど、美しくない

TODOリスト

  • 複雑な検索結果の取得
  • 登録・更新・削除
  • トランザクション制御
  • リレーションの貼り方、概念的な整理
  • デフォルトのカラム構造以外で SoftDelete する方法
  • ソースの自動生成

参考

GORM Guides
Golangのgormで、カスタマイズしたtime.Timeに差し変える

13
9
1

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
13
9