2020/6/30 改良しました
前回DB接続まで
今回も雑にテーブルの基本操作
DB接続
接続をメソッドに。本来は環境やDBを設定ファイルなどで切り替えれるようにするのが良いか
db/db.go
package db
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
func Connection() *gorm.DB {
db, err := gorm.Open("mysql", "root:@tcp(db:3306)/gin_app?charset=utf8&parseTime=True&loc=Local")
if err != nil {
panic("failed to connect database")
}
db.LogMode(true)
return db
}
マイグレーション
こちらもメソッドに。任意で実行できるように変更
migrate/migrate.go
package main
import (
"app/db"
"app/model"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
func main() {
db := db.Connection()
defer db.Close()
db.AutoMigrate(&model.User{})
db.AutoMigrate(&model.UserName{})
}
マイグレーション実行は
docker exec -it gin_app go run /go/src/app/migrate/migrate.go
モデル
各テーブルをモデルとして定義
今回はリレーションも使って見たかったので user
user_name
を作成
テーブルは↓こんなかんじ
$ docker exec -it gin_db mysql -u root -e "use gin_app; show tables;"
+-------------------+
| Tables_in_gin_app |
+-------------------+
| user_names |
| users |
+-------------------+
model/user.go
package model
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
type User struct {
gorm.Model
UserName UserName
}
model/user_name.go
package model
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
type UserName struct {
gorm.Model
UserID uint
Name string
}
コントローラ
名前はserviceでもなんでもいいかもしれない
とりあえず動けばいいのでバリデーションなどは入れていません
controller/user.go
package controller
import (
"app/db"
"app/model"
"github.com/gin-gonic/gin"
)
type User struct{}
func NewUser() *User {
return &User{}
}
func (t *User) Get(c *gin.Context) {
db := db.Connection()
defer db.Close()
var user model.User
result := db.First(&user, c.Param("id")).Related(&user.UserName)
c.JSON(200, result.Value)
}
func (t *User) List(c *gin.Context) {
db := db.Connection()
defer db.Close()
var users []model.User
result := db.Preload("UserName").Find(&users)
c.JSON(200, result.Value)
}
func (t *User) Create(c *gin.Context) {
db := db.Connection()
defer db.Close()
var user model.User
db.Create(&user)
var userName model.UserName
c.BindJSON(&userName)
userName.UserID = user.ID
db.Create(&userName)
}
func (t *User) Update(c *gin.Context) {
db := db.Connection()
defer db.Close()
var user model.User
db.First(&user, c.Param("id")).Related(&user.UserName)
if user.UserName.ID > 0 {
c.BindJSON(&user.UserName)
db.Save(&user.UserName)
}
}
func (t *User) Delete(c *gin.Context) {
db := db.Connection()
defer db.Close()
var user model.User
db.First(&user, c.Param("id")).Related(&user.UserName)
if user.ID > 0 {
db.Delete(&user)
}
if user.UserName.ID > 0 {
db.Delete(&user.UserName)
}
// こっちの消し方でも良い
// db.Where("id = ?", c.Param("id")).Delete(&model.User{})
// db.Where("user_id = ?", c.Param("id")).Delete(&model.UserName{})
}
main
各操作をルーターに追加
main.go
package main
import (
"app/controller"
"github.com/gin-gonic/gin"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
func main() {
r := gin.Default()
r.GET("/users", controller.NewUser().List)
r.GET("/users/:id", controller.NewUser().Get)
r.POST("/users", controller.NewUser().Create)
r.PUT("/users/:id", controller.NewUser().Update)
r.DELETE("/users/:id", controller.NewUser().Delete)
r.Run()
}
実行
作成
curl -X POST http://localhost:3001/users -d '{"name": "hoge"}'
1件取得
curl http://localhost:3001/users/1
全件取得
curl http://localhost:3001/users/
更新
curl -X PUT http://localhost:3001/users/1 -d '{"name": "huga"}'
削除
curl -X DELETE http://localhost:3001/users/1
おわり