Pemrograman

13 Advanced Update Data Gorm Library

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

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

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

func TestUpdateWithExpression(t *testing.T) {
    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    db.AutoMigrate(&User{})
    
    user := User{Balance: 500}
    db.Create(&user)
    
    err := UpdateWithExpression(db, user.ID)
    if err != nil {
        t.Errorf("Update gagal: %v", err)
    }
    
    var updatedUser User
    db.First(&updatedUser, user.ID)
    if updatedUser.Balance != 600 {
        t.Errorf("Expected balance 600, got %d", updatedUser.Balance)
    }
}

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

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

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

func TestUpdateFromSubQuery(t *testing.T) {
    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    db.AutoMigrate(&User{})
    
    users := []User{
        {Balance: 500, Status: "active"},
        {Balance: 1000, Status: "active"},
    }
    db.Create(&users)
    
    err := UpdateFromSubQuery(db)
    if err != nil {
        t.Errorf("Update gagal: %v", err)
    }
    
    var count int64
    db.Model(&User{}).Where("status = ?", "inactive").Count(&count)
    if count != 1 {
        t.Errorf("Expected 1 user inactive, got %d", count)
    }
}

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

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

Penjelasan Kode

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

Unit Test

func TestUpdateWithoutHooks(t *testing.T) {
    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    db.AutoMigrate(&User{})
    
    user := User{Balance: 500}
    db.Create(&user)
    
    err := UpdateWithoutHooks(db, user.ID)
    if err != nil {
        t.Errorf("Update gagal: %v", err)
    }
    
    var updatedUser User
    db.First(&updatedUser, user.ID)
    if updatedUser.Balance != 1000 {
        t.Errorf("Expected balance 1000, got %d", updatedUser.Balance)
    }
}

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

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

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

func TestUpdateReturningData(t *testing.T) {
    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    db.AutoMigrate(&User{})
    
    user := User{Balance: 1000}
    db.Create(&user)
    
    updatedUser, err := UpdateReturningData(db, user.ID)
    if err != nil {
        t.Errorf("Update gagal: %v", err)
    }
    
    if updatedUser.Balance != 1500 {
        t.Errorf("Expected balance 1500, got %d", updatedUser.Balance)
    }
}

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

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

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

func TestHasFieldChanged(t *testing.T) {
    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    db.AutoMigrate(&User{})
    
    user := User{Balance: 1000}
    db.Create(&user)
    
    changed, err := HasFieldChanged(db, user.ID)
    if err != nil {
        t.Errorf("Error terjadi: %v", err)
    }
    
    if !changed {
        t.Errorf("Expected true, got false")
    }
}

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

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

Penjelasan Kode

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

Unit Test

func TestUpdateDynamicValue(t *testing.T) {
    db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    db.AutoMigrate(&User{})
    
    user := User{Balance: 500}
    db.Create(&user)
    
    err := UpdateDynamicValue(db, user.ID, 2000)
    if err != nil {
        t.Errorf("Update gagal: %v", err)
    }
    
    var updatedUser User
    db.First(&updatedUser, user.ID)
    if updatedUser.Balance != 2000 {
        t.Errorf("Expected balance 2000, got %d", updatedUser.Balance)
    }
}

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.

comments powered by Disqus

Topik Terhangat

pemrograman
152
jaringan
28
tips-dan-trik
27
tutorial
20
hardware
11
linux
4
kubernetes
1
trik-and-tips
1