Pelajari berbagai teknik query tingkat lanjut di GORM dengan Golang, termasuk Smart Select Fields, Locking, SubQuery, From SubQuery, dan lainnya. Dilengkapi contoh kode dan unit test.
Dalam artikel ini, kita akan membahas berbagai teknik query tingkat lanjut menggunakan GORM di Golang. Topik-topik yang dibahas meliputi Smart Select Fields, Locking, SubQuery, From SubQuery, Group Conditions, IN with multiple columns, Named Argument, Find To Map, FirstOrInit, FirstOrCreate, Optimizer/Index Hints, Iteration, FindInBatches, Query Hooks, Pluck, Scopes, dan Count.
1. Smart Select Fields
Metode Select()
digunakan untuk memilih field tertentu dalam query agar lebih efisien.
Contoh Kode Fungsi
func GetUserNames(db *gorm.DB) ([]string, error) {
var names []string
result := db.Model(&User{}).Select("name").Pluck("name", &names)
return names, result.Error
}
Penjelasan Kode
db.Model(&User{})
→ Menentukan modelUser
sebagai sumber data..Select("name").Pluck("name", &names)
→ Memilih hanya kolomname
dan menyimpannya dalam slicenames
.return names, result.Error
→ Mengembalikan daftar nama dan error jika ada.
Unit Test
func TestGetUserNames(t *testing.T) {
names, err := GetUserNames(db)
assert.Nil(t, err)
assert.Greater(t, len(names), 0)
}
Penjelasan Unit Test
- Memanggil
GetUserNames(db)
untuk mendapatkan daftar nama user. - Memastikan tidak ada error dengan
assert.Nil(t, err)
. - Memastikan jumlah nama yang dikembalikan lebih dari nol dengan
assert.Greater(t, len(names), 0)
.
2. Locking
Metode Locking
digunakan untuk mengunci record agar tidak diubah oleh transaksi lain selama proses berlangsung.
Contoh Kode Fungsi
func LockUserRecord(db *gorm.DB, id uint) (*User, error) {
var user User
result := db.Clauses(clause.Locking{Strength: "UPDATE"}).First(&user, id)
return &user, result.Error
}
Penjelasan Kode
db.Clauses(clause.Locking{Strength: "UPDATE"})
→ Menambahkan klausa locking pada query..First(&user, id)
→ Mengambil record user berdasarkanid
.return &user, result.Error
→ Mengembalikan user yang ditemukan dan error jika ada.
Unit Test
func TestLockUserRecord(t *testing.T) {
user, err := LockUserRecord(db, 1)
assert.Nil(t, err)
assert.NotNil(t, user)
}
Penjelasan Unit Test
- Memanggil
LockUserRecord(db, 1)
untuk mengunci user dengan ID 1. - Memastikan tidak ada error dengan
assert.Nil(t, err)
. - Memastikan user yang dikembalikan tidak
nil
denganassert.NotNil(t, user)
.
3. SubQuery
Metode SubQuery
digunakan untuk menyusun query dalam query utama, biasanya digunakan untuk filtering yang kompleks.
Contoh Kode Fungsi
func GetLatestUsers(db *gorm.DB) ([]User, error) {
var users []User
subQuery := db.Model(&User{}).Select("MAX(created_at)").Group("id")
result := db.Where("created_at IN (?)", subQuery).Find(&users)
return users, result.Error
}
Penjelasan Kode
subQuery := db.Model(&User{}).Select("MAX(created_at)").Group("id")
→ Membuat subquery untuk mendapatkan waktu pembuatan terbaru.db.Where("created_at IN (?)", subQuery).Find(&users)
→ Mengambil user dengancreated_at
terbaru dari subquery.return users, result.Error
→ Mengembalikan hasil query dan error jika ada.
Unit Test
func TestGetLatestUsers(t *testing.T) {
users, err := GetLatestUsers(db)
assert.Nil(t, err)
assert.Greater(t, len(users), 0)
}
Penjelasan Unit Test
- Memanggil
GetLatestUsers(db)
untuk mendapatkan daftar user terbaru. - Memastikan tidak ada error dengan
assert.Nil(t, err)
. - Memastikan jumlah user yang dikembalikan lebih dari nol dengan
assert.Greater(t, len(users), 0)
.
4. From SubQuery
Metode From SubQuery
digunakan untuk menyusun query berdasarkan hasil dari subquery lain yang dijalankan sebelumnya.
Contoh Kode Fungsi
func GetUsersFromSubQuery(db *gorm.DB) ([]User, error) {
var users []User
subQuery := db.Model(&User{}).Select("id").Where("age > ?", 25)
result := db.Where("id IN (?)", subQuery).Find(&users)
return users, result.Error
}
Penjelasan Kode
subQuery := db.Model(&User{}).Select("id").Where("age > ?", 25)
→ Membuat subquery untuk mendapatkan ID user dengan usia di atas 25 tahun.db.Where("id IN (?)", subQuery).Find(&users)
→ Mengambil user berdasarkan ID yang didapat dari subquery.return users, result.Error
→ Mengembalikan daftar user dan error jika ada.
Unit Test
func TestGetUsersFromSubQuery(t *testing.T) {
users, err := GetUsersFromSubQuery(db)
assert.Nil(t, err)
assert.Greater(t, len(users), 0)
}
Penjelasan Unit Test
- Memanggil fungsi
GetUsersFromSubQuery(db)
untuk mendapatkan daftar user. - Memastikan tidak ada error dengan
assert.Nil(t, err)
. - Memastikan jumlah user lebih dari nol dengan
assert.Greater(t, len(users), 0)
.
5. Group Conditions
Metode Group By
digunakan untuk mengelompokkan hasil berdasarkan suatu kolom tertentu.
Contoh Kode Fungsi
func GetUserCountGroupedByAge(db *gorm.DB) ([]map[string]interface{}, error) {
var results []map[string]interface{}
result := db.Model(&User{}).
Select("age, count(*) as total").
Group("age").
Find(&results)
return results, result.Error
}
Unit Test
func TestGetUserCountGroupedByAge(t *testing.T) {
results, err := GetUserCountGroupedByAge(db)
assert.Nil(t, err)
assert.Greater(t, len(results), 0)
}
6. IN with Multiple Columns
Metode ini digunakan untuk melakukan query dengan kondisi IN
pada lebih dari satu kolom.
Contoh Kode Fungsi
func GetUsersWithMultiColumnCondition(db *gorm.DB) ([]User, error) {
var users []User
result := db.Where("(name, age) IN ((?, ?), (?, ?))", "Alice", 30, "Bob", 25).Find(&users)
return users, result.Error
}
Unit Test
func TestGetUsersWithMultiColumnCondition(t *testing.T) {
users, err := GetUsersWithMultiColumnCondition(db)
assert.Nil(t, err)
assert.Greater(t, len(users), 0)
}
7. Named Argument
Metode Named Argument
digunakan untuk mempermudah pembacaan query dengan parameter yang memiliki nama.
Contoh Kode Fungsi
func GetUsersByNamedParams(db *gorm.DB, name string, age int) ([]User, error) {
var users []User
result := db.Where("name = @name AND age = @age", map[string]interface{}{ "name": name, "age": age }).Find(&users)
return users, result.Error
}
Unit Test
func TestGetUsersByNamedParams(t *testing.T) {
users, err := GetUsersByNamedParams(db, "Alice", 30)
assert.Nil(t, err)
assert.Greater(t, len(users), 0)
}
Selanjutnya, kita akan membahas Find To Map, FirstOrInit, FirstOrCreate, Optimizer/Index Hints, Iteration, FindInBatches, Query Hooks, Pluck, Scopes, dan Count.
Untuk mempelajari lebih lanjut tentang database dalam Golang, silakan kunjungi: