Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
Go

13 Advanced Update Data Gorm Library

· 6 mnt baca ·Ihsan Arif

Pelajari teknik advanced update di GORM seperti Update with SQL Expression, Update from SubQuery, Without Hooks/Time Tracking, Returning Data From Modified Rows, Check Field has Changed?, dan Change Updating Values dalam Golang. Dilengkapi dengan contoh kode dan unit test.

GORM memiliki berbagai fitur update data yang lebih kompleks dan canggih. Artikel ini akan membahas teknik advanced update seperti Update with SQL Expression, Update from SubQuery, Without Hooks/Time Tracking, Returning Data From Modified Rows, Check Field has Changed?, dan Change Updating Values.

1. Update with SQL Expression

Contoh Implementasi

go
1// UpdateWithExpression menggunakan ekspresi SQL untuk memperbarui nilai tertentu
2func UpdateWithExpression(db *gorm.DB, id uint) error {
3    return db.Model(&User{}).Where("id = ?", id).Update("balance", gorm.Expr("balance + ?", 100)).Error
4}

Penjelasan Kode

  • UpdateWithExpression menggunakan gorm.Expr untuk menambahkan 100 ke kolom balance.
  • Where("id = ?", id) memastikan hanya user dengan ID tertentu yang diperbarui.

Unit Test

go
 1func TestUpdateWithExpression(t *testing.T) {
 2    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
 3    db.AutoMigrate(&User{})
 4    
 5    user := User{Balance: 500}
 6    db.Create(&user)
 7    
 8    err := UpdateWithExpression(db, user.ID)
 9    if err != nil {
10        t.Errorf("Update gagal: %v", err)
11    }
12    
13    var updatedUser User
14    db.First(&updatedUser, user.ID)
15    if updatedUser.Balance != 600 {
16        t.Errorf("Expected balance 600, got %d", updatedUser.Balance)
17    }
18}

Penjelasan Kode Unit Test

  • Membuka koneksi database SQLite dan memastikan tabel User tersedia.
  • Menambahkan user dengan saldo awal 500.
  • Memanggil UpdateWithExpression untuk menambahkan 100 ke saldo.
  • Mengecek apakah saldo yang diperbarui sesuai dengan ekspektasi.

2. Update from SubQuery

Contoh Implementasi

go
1// UpdateFromSubQuery memperbarui data berdasarkan hasil subquery
2func UpdateFromSubQuery(db *gorm.DB) error {
3    subQuery := db.Table("users").Select("MAX(balance)")
4    return db.Model(&User{}).Where("balance < ?", subQuery).Update("status", "inactive").Error
5}

Penjelasan Kode

  • subQuery mengambil nilai balance tertinggi.
  • Where("balance < ?", subQuery) memilih user dengan saldo di bawah nilai maksimum.
  • Update("status", "inactive") mengubah status user menjadi “inactive”.

Unit Test

go
 1func TestUpdateFromSubQuery(t *testing.T) {
 2    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
 3    db.AutoMigrate(&User{})
 4    
 5    users := []User{
 6        {Balance: 500, Status: "active"},
 7        {Balance: 1000, Status: "active"},
 8    }
 9    db.Create(&users)
10    
11    err := UpdateFromSubQuery(db)
12    if err != nil {
13        t.Errorf("Update gagal: %v", err)
14    }
15    
16    var count int64
17    db.Model(&User{}).Where("status = ?", "inactive").Count(&count)
18    if count != 1 {
19        t.Errorf("Expected 1 user inactive, got %d", count)
20    }
21}

Penjelasan Kode Unit Test

  • Membuka koneksi database SQLite dan memastikan tabel User tersedia.
  • Menambahkan dua user dengan saldo berbeda.
  • Memanggil UpdateFromSubQuery untuk menonaktifkan user dengan saldo lebih kecil.
  • Mengecek apakah satu user benar-benar dinonaktifkan.

3. Without Hooks/Time Tracking

Contoh Implementasi

go
1// UpdateWithoutHooks memperbarui data tanpa menjalankan hooks atau tracking waktu
2func UpdateWithoutHooks(db *gorm.DB, id uint) error {
3    return db.Model(&User{}).Where("id = ?", id).UpdateColumn("balance", 1000).Error
4}

Penjelasan Kode

  • UpdateColumn("balance", 1000) memperbarui saldo tanpa menjalankan hooks atau tracking waktu.

Unit Test

go
 1func TestUpdateWithoutHooks(t *testing.T) {
 2    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
 3    db.AutoMigrate(&User{})
 4    
 5    user := User{Balance: 500}
 6    db.Create(&user)
 7    
 8    err := UpdateWithoutHooks(db, user.ID)
 9    if err != nil {
10        t.Errorf("Update gagal: %v", err)
11    }
12    
13    var updatedUser User
14    db.First(&updatedUser, user.ID)
15    if updatedUser.Balance != 1000 {
16        t.Errorf("Expected balance 1000, got %d", updatedUser.Balance)
17    }
18}

Penjelasan Kode Unit Test

  • Membuka koneksi database SQLite dan memastikan tabel User tersedia.
  • Menambahkan user dengan saldo awal 500.
  • Memanggil UpdateWithoutHooks untuk memperbarui saldo tanpa hooks.
  • Mengecek apakah saldo yang diperbarui sesuai dengan ekspektasi.

4. Returning Data From Modified Rows

Contoh Implementasi

go
1// UpdateReturningData memperbarui data dan mengembalikan data yang diperbarui
2func UpdateReturningData(db *gorm.DB, id uint) (User, error) {
3    var user User
4    err := db.Model(&User{}).Where("id = ?", id).Update("balance", 1500).Returning("*").Scan(&user).Error
5    return user, err
6}

Penjelasan Kode

  • Update("balance", 1500) memperbarui saldo menjadi 1500.
  • Returning("*") mengembalikan seluruh data user setelah diperbarui.
  • Scan(&user) menyimpan hasil update ke dalam struct user.

Unit Test

go
 1func TestUpdateReturningData(t *testing.T) {
 2    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
 3    db.AutoMigrate(&User{})
 4    
 5    user := User{Balance: 1000}
 6    db.Create(&user)
 7    
 8    updatedUser, err := UpdateReturningData(db, user.ID)
 9    if err != nil {
10        t.Errorf("Update gagal: %v", err)
11    }
12    
13    if updatedUser.Balance != 1500 {
14        t.Errorf("Expected balance 1500, got %d", updatedUser.Balance)
15    }
16}

Penjelasan Kode Unit Test

  • Membuka koneksi database SQLite dan memastikan tabel User tersedia.
  • Menambahkan user dengan saldo awal 1000.
  • Memanggil UpdateReturningData untuk memperbarui saldo dan mendapatkan hasilnya.
  • Mengecek apakah saldo yang diperbarui sesuai dengan ekspektasi.

5. Check Field has Changed?

Contoh Implementasi

go
1// HasFieldChanged mengecek apakah suatu field telah berubah
2func HasFieldChanged(db *gorm.DB, id uint) (bool, error) {
3    var user User
4    db.First(&user, id)
5    return db.Model(&user).Updates(User{Balance: 2000}).RowsAffected > 0, nil
6}

Penjelasan Kode

  • db.First(&user, id) mengambil data user berdasarkan ID.
  • Updates(User{Balance: 2000}) memperbarui saldo.
  • RowsAffected > 0 mengecek apakah pembaruan terjadi.

Unit Test

go
 1func TestHasFieldChanged(t *testing.T) {
 2    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
 3    db.AutoMigrate(&User{})
 4    
 5    user := User{Balance: 1000}
 6    db.Create(&user)
 7    
 8    changed, err := HasFieldChanged(db, user.ID)
 9    if err != nil {
10        t.Errorf("Error terjadi: %v", err)
11    }
12    
13    if !changed {
14        t.Errorf("Expected true, got false")
15    }
16}

Penjelasan Kode Unit Test

  • Membuka koneksi database SQLite dan memastikan tabel User tersedia.
  • Menambahkan user dengan saldo awal 1000.
  • Memanggil HasFieldChanged untuk mengecek apakah saldo berubah.
  • Mengecek apakah perubahan benar-benar terjadi.

6. Change Updating Values

Contoh Implementasi

go
1// UpdateDynamicValue memperbarui nilai saldo berdasarkan parameter yang diberikan
2func UpdateDynamicValue(db *gorm.DB, id uint, newBalance int) error {
3    return db.Model(&User{}).Where("id = ?", id).Update("balance", newBalance).Error
4}

Penjelasan Kode

  • Update("balance", newBalance) memperbarui saldo dengan nilai yang diberikan dari parameter newBalance.

Unit Test

go
 1func TestUpdateDynamicValue(t *testing.T) {
 2    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
 3    db.AutoMigrate(&User{})
 4    
 5    user := User{Balance: 500}
 6    db.Create(&user)
 7    
 8    err := UpdateDynamicValue(db, user.ID, 2000)
 9    if err != nil {
10        t.Errorf("Update gagal: %v", err)
11    }
12    
13    var updatedUser User
14    db.First(&updatedUser, user.ID)
15    if updatedUser.Balance != 2000 {
16        t.Errorf("Expected balance 2000, got %d", updatedUser.Balance)
17    }
18}

Penjelasan Kode Unit Test

  • Membuka koneksi database SQLite dan memastikan tabel User tersedia.
  • Menambahkan user dengan saldo awal 500.
  • Memanggil UpdateDynamicValue untuk memperbarui saldo menjadi 2000.
  • Mengecek apakah saldo yang diperbarui sesuai dengan ekspektasi.

Kesimpulan

Dalam artikel ini, kita telah membahas berbagai teknik advanced update di GORM, termasuk:

  • Update with SQL Expression untuk melakukan operasi matematika dalam query.
  • Update from SubQuery untuk memperbarui data berdasarkan hasil subquery.
  • Without Hooks/Time Tracking untuk menghindari pemanggilan hooks atau perubahan timestamp otomatis.
  • Returning Data From Modified Rows untuk mendapatkan data terbaru setelah update.
  • Check Field has Changed? untuk mengecek apakah nilai field benar-benar berubah.
  • Change Updating Values untuk memperbarui nilai secara dinamis sesuai dengan kondisi.

Dengan memahami teknik-teknik ini, Anda dapat mengoptimalkan proses pembaruan data di aplikasi berbasis Golang dengan GORM. Pastikan untuk selalu menguji setiap pembaruan dengan unit test agar fungsionalitas tetap terjaga.

IH
Ihsan Arif
Backend engineer & penulis di Santekno. Aktif menulis tentang Go, Laravel, dan arsitektur backend modern.
Follow

💬 Komentar