반응형
https://www.youtube.com/watch?v=9koLNdEcSR0
위 영상에서 다룬 내용들을 정리했음.
2020년 8월 기준 영상이라, 영상 이후 변경 혹은 수정된 방식의 GORM 사용법으로 업데이트했다.
GORM
- Code-first ORM.
- go code로 Create DB Schema, interact with DB with Writing SQL Query 등을 가능하게 함.
https://gorm.io/docs/models.html
package main
import (
"fmt"
"log"
"gorm.io/gorm"
"gorm.io/driver/sqlite"
)
/*
테이블 정의하기
- gorm.Model을 struct의 정의부에 추가한다.
- primary Key인 ID, createdAt, UpdatedAt DeletedAt이 정의되어 있음.
- ID는 어떤 데이터 타입이든 상관없다. struct에 ID 필드가 정의되어 있다면 그걸 자동으로 primary key로 사용함.
*/
type Channel struct {
gorm.Model
Name string
Description string
}
type User struct {
gorm.Model
Email string
Username string
}
// https://gorm.io/docs/belongs_to.html
type Message struct {
gorm.Model
Content string
UserID int // foreign key 자동인식. UserID를 반드시 입력해줘야 Belongs to 관계가 성립된다.
User User
ChannelID int
Channel Channel
}
// https://gorm.io/docs/migration.html
/*
기본적으로 migrate는 자동.
- only creates table, missing columns and missing indexes. (이미 정의된 것을 변경하거나 삭제하지는 않는다.)
*/
// create 3 table in DB.
func setup(db *gorm.DB) {
db.AutoMigrate(&Channel{}, &User{}, &Message{})
seed(db)
}
func seed(db *gorm.DB) {
channels := []Channel{
{Name: "General", Description: "General Discussions"},
{Name: "Off-Topic", Description: "Weird stuff goes here"},
{Name: "Suggestions", Description: "Video suggestions go here"},
}
// https://gorm.io/docs/create.html
// Batch insert 기능. slice를 파라미터로 넣으면 된다.
db.Create(&channels)
users := []User{
{Email: "test@test.com", Username: "Joe420"},
{Email: "yes@yes.com", Username: "Bob"},
}
db.Create(&users)
var generalChat, suggestionsChat Channel
// https://gorm.io/docs/query.html
// 조건문 걸어서 field 조회하는 방법.
db.Where("Name = ?", "General").First(&generalChat)
// inline Condition 형태로도 사용 가능.
db.First(&suggestionsChat, "Name = ?", "Suggestions")
var joe, bob User
db.First(&joe, "Username = ?", "Joe420")
db.First(&bob, "Username = ?", "Bob")
// 사용자 정의 struct가 포함되어 있는 경우 (generalChat과 job이라는 struct 사용 시)
// -> DB 조회해서 있으면 그거 연결하고, 없으면 생성한다.
messages := []Message{
{Content: "Hello!", Channel: generalChat, User: joe},
{Content: "What up", Channel: generalChat, User: bob},
{Content: "Make more go videos", Channel: suggestionsChat, User: joe},
}
db.Create(&messages)
}
func main() {
// Logger 세팅: https://gorm.io/docs/logger.html
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // Slow SQL threshold
LogLevel: logger.Silent, // Log level
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
Colorful: false, // Disable color
},
)
// sqlite3 사용. 어떤 db를 쓰느냐에 따라 다르게 정의해서 쓰면 됨
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{
Logger : newLogger,
})
if err != nil {
panic("can't connect to database")
}
defer os.Remove("test.db")
setup(db)
var users []User
db.Find(&users) // select all users
for i, u := range users {
fmt.Println(i)
fmt.Println("Email:", u.Email, "Username:", u.Username)
}
var messages []Message
// https://gorm.io/docs/preload.html
//db.Preload("User").Find(&messages) -> Eager loading 기능.
//db.Model(users[0]).Related(&message) -> 현재는 Related 메소드는 지원하고 있지 않음.
db.Preload("User").Find(&messages, &Message{UserID: users[0].ID})
for _, m := range messages {
fmt.Println("Message:", m.Content, "Sender:", m.User.Email)
}
doError(db)
}
func doError(db *gorm.DB) {
var fred User
// Error handling.
if err := db.Where("username = ?", "Fred").First(&fred).Error; err != nil {
log.Fatalf("Error when loading user: %s", err)
}
}
특징
- gorm.Model 세팅할 때 deletedAt 필드가 있으면 자동으로 soft delete가 적용된다. deletedAt 필드에 delete 요청한 시간이 기록되며, normal Query로는 해당 row를 더 이상 찾을 수 없게 된다.
- 그래서 deletedAt에는 자동으로 index가 생성된다.
반응형
'학습일지 > 데이터베이스' 카테고리의 다른 글
if kakao 2021 - PostgreSQL ecosystem (0) | 2022.08.05 |
---|---|
Transaction Isolation - MySQL과 Postgresql 비교 (0) | 2022.06.15 |
빠르게 정리하는 데이터베이스 (3) Normalization (0) | 2022.04.09 |
빠르게 정리하는 데이터베이스 (2) - MySQL Stored Procedure (0) | 2021.08.07 |
빠르게 정리하는 데이터베이스 (1) 기본개념, DB Structure (0) | 2021.07.05 |