Akademi Manajemen Informatika

sandidharma.ac.id – Halo semuanya! Beberapa hari Lewat saya menemukan bug cukup menjebak di salah satu service yang saya kerjakan dengan Go dan GORM. Secara logika, semuanya terlihat Betul—data yang dikirim ke repository sudah sesuai, ID valid, Enggak Terdapat error, dan bahkan struct yang di-passing sudah terisi lengkap. Tapi anehnya, data Enggak ter-update sama sekali di database.

Awalnya Saya Curiga Banyak Hal

Saya sempat berpikir Terdapat yang salah di layer service atau mungkin di payload dari client. Tapi setelah tracing cukup Pelan, Rupanya masalahnya datang dari Metode saya menginisialisasi *gorm.DB di repository.

Saya menulis constructor seperti ini:

func NewUserRepository(db *gorm.DB) *userRepository {
	return &userRepository{
		model: db.Model(&entities.User{}),
	}
}

Dan di method Update saya menggunakan:

func (r *userRepository) Update(ctx context.Context, id uuid.UUID, entity *entities.User) error {
	return r.model.WithContext(ctx).Where("id = ?", id).Updates(entity).Error
}

Seluruh terlihat Berkualitas-Berkualitas saja — hingga saya menjalankan beberapa proses update secara berulang Kepada data yang berbeda. Anehnya, entitas Enggak ter-update sama sekali, padahal ID sudah Betul, dan data pun valid.

READ  Pengertian, fitur yang dimiliki, dan Kelebihan

Di Sini Letak Masalahnya

Karena saya menyimpan hasil chaining Model() ke dalam field model, maka seluruh query yang dibangun setelahnya (seperti WithContext, Where, dll) tetap “terikat” dengan chaining awal itu. Dan pada kasus tertentu seperti Updates(), ini menyebabkan GORM gagal menyusun query update secara Betul.

Masalah ini Enggak muncul Begitu Select() atau Find(), karena GORM Dapat mendeteksi model dari parameter yang kita berikan, misalnya:

r.model.WithContext(ctx).Find(&result)

Tapi Kepada Updates(), GORM sangat bergantung pada hasil chaining Model() agar Paham entitas mana yang harus di-update.

Solusinya Sederhana Tapi Krusial

Saya refactor repository constructor agar hanya menyimpan *gorm.DB mentahnya saja:

func NewUserRepository(db *gorm.DB) *userRepository {
	return &userRepository{
		db: db,
	}
}

Dan Kepada setiap method, saya chaining ulang dengan Model() yang sesuai:

func (r *userRepository) Update(ctx context.Context, id uuid.UUID, entity *entities.User) error {
	return r.db.WithContext(ctx).
		Model(&entities.User{}).
		Where("id = ?", id).
		Updates(entity).Error
}

Dengan Metode ini, kita Dapat memastikan bahwa context dan model selalu fresh dan Enggak membawa Pengaruh samping dari chaining sebelumnya.

READ  Pengertian, Metode Kerja, Perbedaan, Kelebihan

Pelajaran Krusial

  • Hindari menyimpan hasil chaining db.Model(…) di dalam struct repository.
  • Simpan saja instance *gorm.DB Asli, dan lakukan chaining baru di setiap method.
  • Jangan anggap enteng chaining GORM, karena efeknya Dapat muncul Tenang-Tenang tanpa error yang Terang.

Semoga pengalaman ini Dapat membantu Kawan-Kawan yang menggunakan GORM agar Enggak menghabiskan waktu Kepada debugging seperti saya kemarin. 😅