Pelajari cara menggunakan GORM untuk membuat record di berbagai database dalam Golang. Dapatkan panduan lengkap dengan contoh kode, unit test, dan teknik optimal untuk Simple Create, Batch Insert, Create Hooks, dan banyak lagi.
GORM adalah library ORM (Object Relational Mapper) yang populer dalam ekosistem Golang. Dengan GORM, pengembang dapat berinteraksi dengan berbagai database seperti MySQL, PostgreSQL, SQLite, dan SQL Server secara lebih mudah dan efisien.
Artikel ini akan membahas berbagai metode untuk membuat record di GORM dengan langkah-langkah yang jelas, contoh kode, serta unit test untuk memastikan fungsionalitasnya.
1. Simple Create Record
Untuk membuat record sederhana di GORM, kita dapat menggunakan metode Create()
.
Contoh Kode
package main
import (
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"testing"
)
// User merepresentasikan model user dalam database
type User struct {
ID uint `gorm:"primaryKey"`
Name string
Email string
}
func CreateUser(db *gorm.DB, name, email string) error {
user := User{Name: name, Email: email}
return db.Create(&user).Error
}
Penjelasan Kode:
- Pendefinisian Struct
User
: Struct ini mewakili tabelusers
dalam database dengan ID sebagai primary key. - Fungsi
CreateUser
: Fungsi ini menerima parameter database, nama, dan email, lalu menyimpan data ke dalam database menggunakanCreate()
.
Unit Test dengan SQLMock
import (
"database/sql"
"testing"
"github.com/DATA-DOG/go-sqlmock"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func TestCreateUser(t *testing.T) {
mockDB, mock, _ := sqlmock.New()
sqlDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: mockDB}), &gorm.Config{})
mock.ExpectBegin()
mock.ExpectExec("INSERT INTO \"users\" \(").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
err := CreateUser(sqlDB, "Alice", "alice@example.com")
if err != nil {
t.Errorf("Failed to create user: %v", err)
}
}
Penjelasan Unit Test:
- Menggunakan SQLMock untuk membuat mock database.
- Menyiapkan ekspektasi query INSERT menggunakan SQLMock.
- Memanggil
CreateUser
dan memverifikasi hasilnya. - Memastikan tidak ada error selama proses penyimpanan data.
2. Create Record With Selected Fields
func CreateUserWithSelectedFields(db *gorm.DB, name string) error {
return db.Select("Name").Create(&User{Name: name}).Error
}
Penjelasan Kode:
- Fungsi
CreateUserWithSelectedFields
: Hanya menyimpan fieldName
ke dalam database, sementara field lain sepertiEmail
akan dibiarkan kosong. - Metode
Select("Name")
: Menginstruksikan GORM untuk hanya menyertakan kolomName
dalam pernyataanINSERT
.
Unit Test dengan SQLMock
import (
"testing"
"github.com/DATA-DOG/go-sqlmock"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func TestCreateSelectedFields(t *testing.T) {
mockDB, mock, _ := sqlmock.New()
sqlDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: mockDB}), &gorm.Config{})
mock.ExpectBegin()
mock.ExpectExec("INSERT INTO \"users\" \(").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
err := CreateUserWithSelectedFields(sqlDB, "Bob")
if err != nil {
t.Errorf("Failed to create user: %v", err)
}
}
Penjelasan Unit Test:
- Menggunakan SQLMock untuk mensimulasikan interaksi dengan database tanpa koneksi nyata.
mock.ExpectExec()
memastikan hanya kolomName
yang disertakan dalam perintahINSERT
.mock.ExpectCommit()
menandakan akhir transaksi database.
3. Batch Insert
func BatchInsertUsers(db *gorm.DB, users []User) error {
return db.Create(&users).Error
}
Penjelasan Kode:
- Fungsi
BatchInsertUsers
: Menerima slice dariUser
dan menyisipkan semua record dalam satu operasi database. - Metode
Create(&users)
: Secara otomatis menghasilkan perintahINSERT
untuk setiap entri dalam sliceusers
.
Unit Test dengan SQLMock
func TestBatchInsert(t *testing.T) {
mockDB, mock, _ := sqlmock.New()
sqlDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: mockDB}), &gorm.Config{})
mock.ExpectBegin()
mock.ExpectExec("INSERT INTO \"users\" \(").WillReturnResult(sqlmock.NewResult(1, 2))
mock.ExpectCommit()
users := []User{{Name: "Charlie"}, {Name: "David"}}
err := BatchInsertUsers(sqlDB, users)
if err != nil {
t.Errorf("Failed to batch insert users: %v", err)
}
}
Penjelasan Unit Test:
- Menggunakan SQLMock untuk memverifikasi batch insert tanpa benar-benar terhubung ke database.
mock.ExpectExec()
memastikan perintahINSERT
menangani lebih dari satu record.mock.ExpectCommit()
menandakan transaksi selesai dan berhasil disimpan ke database.
4. Create Hooks
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
// Menambahkan prefix "Prefix-" ke field Name sebelum disimpan ke database
u.Name = "Prefix-" + u.Name
return nil
}
Unit Test dengan SQLMock
import (
"testing"
"github.com/DATA-DOG/go-sqlmock"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func TestCreateHooks(t *testing.T) {
mockDB, mock, _ := sqlmock.New()
sqlDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: mockDB}), &gorm.Config{})
// Mensimulasikan operasi database
mock.ExpectBegin()
mock.ExpectExec("INSERT INTO \"users\" ").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
user := User{Name: "Eve"}
err := sqlDB.Create(&user).Error
if err != nil {
t.Errorf("Failed to create user with hook: %v", err)
}
}
Penjelasan Kode:
- Fungsi
BeforeCreate
menambahkan prefix “Prefix-” pada fieldName
sebelum data disimpan ke database. - Menggunakan SQLMock untuk simulasi database, sehingga tidak perlu koneksi database sungguhan.
- Unit test memverifikasi bahwa hook dijalankan dengan benar, dengan memastikan data tersimpan dengan perubahan yang diharapkan.
5. Create From Map
func CreateUserFromMap(db *gorm.DB, data map[string]interface{}) error {
// Menggunakan map untuk menyimpan data ke tabel users
return db.Model(&User{}).Create(data).Error
}
Unit Test dengan SQLMock
func TestCreateFromMap(t *testing.T) {
mockDB, mock, _ := sqlmock.New()
sqlDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: mockDB}), &gorm.Config{})
// Mensimulasikan operasi database
mock.ExpectBegin()
mock.ExpectExec("INSERT INTO \"users\" ").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
data := map[string]interface{}{ "Name": "Charlie", "Email": "charlie@example.com" }
err := CreateUserFromMap(sqlDB, data)
if err != nil {
t.Errorf("Failed to create user from map: %v", err)
}
}
Penjelasan Kode:
- Fungsi
CreateUserFromMap
menerima data dalam bentuk map yang memungkinkan fleksibilitas dalam penyimpanan data. - Menggunakan
db.Model(&User{}).Create(data)
untuk menyimpan data tanpa perlu membuat objek struct User secara eksplisit. - Unit test dengan SQLMock mensimulasikan penyimpanan data menggunakan
ExpectExec
untuk memastikan queryINSERT
dieksekusi tanpa error.
6. Create From SQL Expression
func CreateUserWithExpression(db *gorm.DB) error {
// Menggunakan ekspresi SQL untuk menyimpan data ke dalam tabel users
return db.Exec("INSERT INTO users (name, email) VALUES (?, ?)", "Generated", "generated@example.com").Error
}
Unit Test dengan SQLMock
func TestCreateUserWithExpression(t *testing.T) {
mockDB, mock, _ := sqlmock.New()
sqlDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: mockDB}), &gorm.Config{})
// Mensimulasikan operasi database
mock.ExpectBegin()
mock.ExpectExec("INSERT INTO users ").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
err := CreateUserWithExpression(sqlDB)
if err != nil {
t.Errorf("Failed to create user with SQL expression: %v", err)
}
}
Penjelasan Kode:
- Menggunakan
Exec
untuk menjalankan SQL mentah yang memberikan fleksibilitas dalam eksekusi query. - Query
INSERT INTO users (name, email) VALUES (?, ?)
digunakan untuk menyisipkan data langsung tanpa perlu menggunakan model GORM. - Unit test dengan SQLMock memverifikasi eksekusi query menggunakan
ExpectExec
, memastikan bahwa query dieksekusi dengan benar. - Simulasi transaksi database dilakukan dengan
ExpectBegin
danExpectCommit
, memastikan perubahan dilakukan dalam transaksi yang benar.
7. Create with Associations
Saat bekerja dengan relasi antar tabel, kita bisa menyimpan data dengan asosiasi menggunakan GORM.
Contoh Kode
type Profile struct {
ID uint
UserID uint
Bio string
}
type UserWithProfile struct {
ID uint
Name string
Profile Profile
}
func CreateUserWithProfile(db *gorm.DB, name, bio string) error {
user := UserWithProfile{Name: name, Profile: Profile{Bio: bio}}
return db.Create(&user).Error
}
Unit Test dengan SQLMock
import (
"testing"
"github.com/DATA-DOG/go-sqlmock"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func TestCreateUserWithProfile(t *testing.T) {
mockDB, mock, _ := sqlmock.New()
sqlDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: mockDB}), &gorm.Config{})
// Mensimulasikan operasi database
mock.ExpectBegin()
mock.ExpectExec("INSERT INTO \"user_with_profiles\" ").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectExec("INSERT INTO \"profiles\" ").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
err := CreateUserWithProfile(sqlDB, "John", "Software Engineer")
if err != nil {
t.Errorf("Failed to create user with profile: %v", err)
}
}
Penjelasan Kode:
- Mendefinisikan model
Profile
danUserWithProfile
untuk merepresentasikan relasi antara pengguna dan profilnya. - Fungsi
CreateUserWithProfile
membuat user baru dengan profil dan langsung menyimpan ke database. - Unit test menggunakan SQLMock untuk mensimulasikan transaksi database, memastikan operasi
INSERT
dilakukan pada kedua tabel. ExpectExec
digunakan untuk memverifikasi queryINSERT
pada tabel user dan profile.
8. Upsert / On Conflict
Upsert digunakan untuk menyisipkan data atau memperbarui jika sudah ada.
Contoh Kode
func UpsertUser(db *gorm.DB, name, email string) error {
user := User{Name: name, Email: email}
return db.Clauses(gorm.Clauses{gorm.OnConflict{UpdateAll: true}}).Create(&user).Error
}
Unit Test dengan SQLMock
func TestUpsertUser(t *testing.T) {
mockDB, mock, _ := sqlmock.New()
sqlDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: mockDB}), &gorm.Config{})
// Mensimulasikan operasi database
mock.ExpectBegin()
mock.ExpectExec("INSERT INTO \"users\" ").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
err := UpsertUser(sqlDB, "Alice", "alice@example.com")
if err != nil {
t.Errorf("Failed to upsert user: %v", err)
}
}
Penjelasan Kode:
- Fungsi
UpsertUser
menggunakangorm.OnConflict
untuk menangani duplikasi dan memperbarui data jika sudah ada. - Unit test menggunakan SQLMock untuk memastikan operasi upsert berjalan dengan benar.
- Menggunakan
ExpectExec
untuk memverifikasi eksekusi queryINSERT
dengan strategi upsert. - Simulasi transaksi database dilakukan dengan
ExpectBegin
danExpectCommit
, memastikan operasi berjalan sesuai aturan transaksi.
Artikel ini memberikan panduan lengkap bagi programmer Golang untuk menggunakan GORM dalam membuat record di berbagai database. Setiap teknik yang dijelaskan memiliki contoh implementasi dan unit test agar lebih mudah dipahami dan diuji dalam proyek nyata.
Untuk tutorial lebih lanjut, kunjungi:
Artikel Terhangat
14 Menghapus (Delete) Data Gorm Library
03 Mar 2025
13 Advanced Update Data Gorm Library
03 Mar 2025
11 Update Data GORM Library
03 Mar 2025
08 Advanced Query dengan GORM di Golang
03 Mar 2025

14 Menghapus (Delete) Data Gorm Library

13 Advanced Update Data Gorm Library

11 Update Data GORM Library
