Halo… Selamat datang kembali di blog Ruang Developer. Gimana kabarnya hari ini? Semoga tetap semangat belajar koding ya. Pada postingan ini kita akan belajar bagaiamana caranya menggunakan database transaction di Laravel.
Apa Itu Database Transaction?
Sebelum kita menggunakan database transaction, tentu kita harus mengetahui terlebih dahulu apa itu database transaction.
Dalam konteks database, transaction adalah unit logika yang dijalankan secara independent untuk mengambil atau melakukan perubahan data. Sedangkan database transaction adalah kumpulan atau serangkaian operasi yang dilakukan dalam DBMS (Database Management Systam) terhadap database. Database transaction berfungsi untuk mengatur alur transaksi dalam suatu database untuk mempertahankan konsistensi data.
Berikut ini adalah beberapa proses dalam database transaction.
Begin
Begin digunakan untuk memberi tanda bahwa transaction akan di mulai.
Commit
Commit digunakan untuk memberi tanda bahwa semua transaction telah selesai dan data harus disimpand dalam database. Commit harus diterapkan jika ingin menyelesaikan database transaction.
Rollback
Rollback digunakan ketika terdapat kesalahan atau kegagalan pada saat transaction berlangsung. Rollback harus diterapkan agar tidak terdapat perubahan parsial (sebagian) dalam database akibat kegagalan proses sehingga data tetap konsisten.
Kapan Harus Menggunakan Database Transaction?
Database transaction biasanya digunakan pada saat melakukan transaksi yang merubah beberapa data sekaligus pada satu proses. Contoh kasusnya adalah sebagai berikut.
Pada suatu aplikasi penjualan online, terdapat sistem invoice untuk customer yang melakukan pembelian. Alurnya adalah sebagai berikut.
- Order dibuat dan memiliki status unpaid (belum dibayar)
- Tagihan dibayar oleh customer
- Status order dirubah menjadi paid (sudah dibayar)
Pada proses diatas, terdapat kemungkinan kegagalan saat merubah status order dari unpaid menjadi paid. Jika proses tetap dilanjutkan maka status order masih tetap unpaid padahal pembayaran sudah berhasil dilakukan (data tidak konsisten).
Pada kondisi seperti itulah kita memerlukan database transaction. Sehingga saat terjadi kegagalan, semua perubahan yang dilakukan sebelumnya akan dibatalkan (rollback).
Contoh Database Transaction Dengan MySQL
Pada contoh ini saya akan menggunakan satu tabel saja agar lebih sederhana. Misalnya saya memiliki tabel items dengan data berikut ini:
mysql> select * from items;
+----+----------+-------+
| id | name | stock |
+----+----------+-------+
| 1 | Mouse | 20 |
| 2 | Keyboard | 4 |
| 3 | Monitor | 8 |
+----+----------+-------+
3 rows in set (0.00 sec)
Kemudian saya akan begin transaction dan mengupdate stock untuk item mouse menjadi 3.
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> update items set stock = 3 where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Sekarang kita lihat datanya.
mysql> select * from items;
+----+----------+-------+
| id | name | stock |
+----+----------+-------+
| 1 | Mouse | 3 |
| 2 | Keyboard | 4 |
| 3 | Monitor | 8 |
+----+----------+-------+
3 rows in set (0.00 sec)
Misalnya saya anggap terdapat kesalahan saat proses dijalankan. Saya ingin membatalkan perubahan dengan cara melakukan rollback.
mysql> ROLLBACK;
Query OK, 0 rows affected (0.01 sec)
Kita lihat lagi datanya
mysql> select * from items;
+----+----------+-------+
| id | name | stock |
+----+----------+-------+
| 1 | Mouse | 20 |
| 2 | Keyboard | 4 |
| 3 | Monitor | 8 |
+----+----------+-------+
3 rows in set (0.00 sec)
Sekarang stock item mouse kembali menjadi 20 seperti semula.
Lalu bagaimana jika tidak ada kesalah dan ingin menyimpan data?
Untuk menyimpan data dan menyelesaikan transaction, kita tinggal gunakan perintah commit.
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
Namun karena sebelumnya sudah saya rollback, maka tidak ada data yang dismpan dalam database ya.
Nah begitulah penerapan sederhana database transaction ketika melakukan perubahan data.
Menggunakan Database Transaction Di Laravel
Tentu kita semua tahu bahwa laravel selalu menyediakan hal hal mendasar yang kita perlukan dalam membuat aplikasi. Salah satunya adalah database transaction ini.
Untuk menggunakan database transaction di laravel, caranya sangat mudah sekali. Database transaction tersedia di dalam Facade DB milik laravel. Ada dua cara yang bisa kita gunakan perhatikan contoh kode berikut.
Cara otomatis:
DB::transaction(function(){
// transaksi database di sini
}, 1);
Dengan menggunakan cara di atas, kita cukup menuliskan transaksi database dalam callback function. Jika terjadi kesalahan saat transaksi maka laravel otomatis akan melakukan rollback data. Parameter kedua pada method transaction adalah jumlah berapa kali percobaan dilakukan. Misalnya jika 2 kali, maka ketika terjadi kesalahan proses akan diulangi lagi, jika masih tetap salah baru kemudian rollback dijalankan.
Cara manual:
try {
DB::beginTransaction();
// transaksi database di sini
DB::commit();
} catch (\Throwable $th) {
DB::rollBack();
throw $th;
}
Cara berikutnya adalah menggunakan block try catch. Pada kode diatas, kita menulis transaksi database diantara beginTransaction dan commit, kemudian rollback pada block catch.
Jika terjadi jesalahan saat transaski, maka error akan dilemparkan ke block catch dan rollBack akan dijalankan untuk mengembalikan data ke kondisi awal.
Contoh
Sebagai contoh, di sini saya sudah menyediakan project laravel sederhana, dengan database berisi dua tabel yaitu tabel order dan invoice.
Pada tabel order terdapat field is_paid yang mengindikasikan apakah order sudah terbayar atau belum.
Sedangkan pada tabel invoice terdapat field is_success yang mengindikasikan apakah pembayaran sukses dilakukan atau gagal.
Anggap saja ada sebuah proses dimana saya akan merubah is_success pada tabel invoice menjadi true dan is_paid pada tabel order menjadi true. Maka saya bisa menuliskan kodenya kurang lebih seperti berikut.
Menggunakan cara otomatis
Route::get('test-transaction', function () {
// Membuat data invoice untuk contoh
$invoice = new Invoice(['is_success' => false]);
$invoice->save();
// Membuat data order untuk contoh
$order = new Order(['is_paid' => false]);
$order->save();
DB::transaction(function () use ($invoice, $order) {
// Transaksi database merubah invoice
$invoice->is_success = true;
$invoice->save();
throw new Error('error');
// Transaksi database merubah order
$order->is_paid = true;
$order->save();
});
});
Menggunakan Cara Manual (try-catch)
Route::get('test-transaction', function () {
// Membuat data invoice untuk contoh
$invoice = new Invoice(['is_success' => false]);
$invoice->save();
// Membuat data order untuk contoh
$order = new Order(['is_paid' => false]);
$order->save();
try {
// Memulai transaksi
DB::beginTransaction();
// Transaksi database merubah invoice
$invoice->is_success = true;
$invoice->save();
// Transaksi database merubah order
$order->is_paid = true;
$order->save();
// Commit transaksi
DB::commit();
} catch (\Throwable $th) {
// Rollback jika ada error
DB::rollBack();
throw $th;
}
});
Nah seperti itulah cara menggunakan database transaction di laravel. Terdapat dua cara yang bisa kamu gunakan.
Untuk mencoba apakah data berhasil di rollBack kamu bisa mencoba manual menulis throw error dan lihat apakah data berhasil dirollback.
Pada contoh diatas, database transaction langsung saya tulis dalam callback milik router laravel. Ini hanya untuk menyederhanakan contohnya saja ya. Pada penerapannya, database transaction biasanya dituliskan di dalam service layer, atau paling maksimal di dalam controller. Selalu baca dan pelajari best practice dalam menulis kode ya…