Ga terasa semenjak pindah di kantor baru, saya belum posting lagi di blog ini heheh mungkin karena sekarang lagi agak sibuk untuk adaptasi dengan technology yang di pakai di kantor baru ini jadi ga sempat untuk posting di blog. oke lah, saya mau nulis artikel simpel aja sih sebenernya yang mungkin banyak ga di sadari orang ketika dia coding menggunakan Spring 3.0 dan Hibernate (atau ORM lainnya). Kali ini berkenaan dengan transaction management, biar lebih clear kita definisikan terlebih dahulu apa yang di maksud dengan Transaction. Transaction adalah satu atau lebih operasi, sebuah transaction memungkinkan adanya beberapa unit operasi yang bekerja di dalamnya. Simak contoh dibawah ini :
Misalkan pada kasus sebuah penjualan barang, ketika sebuah transaksi penjualan barang berlangsung sebetulnya ada beberapa step yang perlu dilakukan sebelum system tersebut memastikan bahwa barang yang dimaksud siap untuk dijual. kurang lebih step by step nya adalah sebagai berikut :
- Mengecek ketersediaan barang yang dimaksud di gudang (inventory)
- Setelah dipastikan ada, maka kita akan insert data ke tabel penjualan (dan penjualan detail)
- Mengurangi nilai quantity pada tabel stok barang
Nah 3 buah step ini harus berjalan semua, artinya jika ada salah satu step tersebut diatas yang mengalami kegagalan, maka step lain tidak bisa dijalankan, misalkan ketika system gagal untuk mengurangi nilai quantity pada tabel stok barang (Step 3) maka data yang di insert pada tabel penjualan harus di batalkan atau di rollback kembali dan transaksi dibatalkan.

Ilustrasi Sebuah Transaksi
Nah dengan menggunakan Spring 3.0 kita bisa melakukan hal hal seperti ini bisa di lakukan, dengan menggunakan annotation @Transactional, tapi sebelumnya silahkan enable kan transaction manager di file configuration.xml anda.
<!-- ini untuk meng enable kan transaction manager --> <tx:annotation-driven transaction-manager="transactionManager" />
<!-- karena saya pakai hibernate, maka deklarasi Hibernate Transaction Manager seperti ini --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory" />
Nah pada contoh ini saya menambahkan annotation
@Transactional(rollBackFor=Exception.class)
di level Class DAO Implement nya, yang mempunyai arti jika terjadi exception pada saat menjalankan method – method di dalam class ini maka transaction tersebut akan dibatalkan. berikut contoh Model, DAO, Service dan Controller nya
Dummy.java
package com.research.model; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Dummy implements Serializable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue private Long id; @Column private String code; public Dummy(){} //setter getter tidak ditampilkan
Mahasiswa.java
package com.research.model; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Mahasiswa implements Serializable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue private Long id; @Column(length=3) private String name; public Mahasiswa(){ } //setter getter tidak ditampilkan
DummyDAO.java
package com.research.dao.iface; import com.research.model.Dummy; import com.research.model.Mahasiswa; public interface DummyDAO { public void save(Dummy dummy); public void update(Dummy dummy); public void delete(Dummy dummy); public void saveBatch(Dummy dummy, Mahasiswa mahasiswa); }
DummyDAOImpl.java
package com.research.dao; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import com.research.base.dao.BaseDAO; import com.research.dao.iface.DummyDAO; import com.research.model.Dummy; import com.research.model.Mahasiswa; @Repository @Transactional(rollbackFor = Exception.class) public class DummyDAOImpl extends BaseDAO implements DummyDAO { @Override public void save(Dummy dummy) { getSession().save(dummy); } @Override public void update(Dummy dummy) { // TODO Auto-generated method stub getSession().update(dummy); } @Override public void delete(Dummy dummy) { // TODO Auto-generated method stub getSession().delete(dummy); } @Override public void saveBatch(Dummy dummy, Mahasiswa mahasiswa){ getSession().save(dummy); getSession().save(mahasiswa); } }
DummyService.java
package com.research.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.research.dao.iface.DummyDAO; import com.research.model.Dummy; import com.research.model.Mahasiswa; @Service("dummyService") public class DummyService implements DummyDAO { @Autowired private DummyDAO dummyDAO; @Override public void save(Dummy dummy) { // TODO Auto-generated method stub dummyDAO.save(dummy); } @Override public void update(Dummy dummy) { // TODO Auto-generated method stub dummyDAO.update(dummy); } @Override public void delete(Dummy dummy) { // TODO Auto-generated method stub dummyDAO.delete(dummy); } @Override public void saveBatch(Dummy dummy, Mahasiswa mahasiswa){ dummyDAO.saveBatch(dummy, mahasiswa); } }
DummyController.java
package com.research; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.research.model.Dummy; import com.research.model.Mahasiswa; import com.research.service.DummyService; @Controller @RequestMapping("/dummy") public class DummyController { @Autowired private DummyService dummyService; @RequestMapping(method = RequestMethod.GET) public String performList(Model model) { try { Dummy dummy = new Dummy(); dummy.setCode("code 2"); Mahasiswa mhs = new Mahasiswa(); mhs.setName("Ghufron"); /** pada com.research.model.Mahasiswa length column name hanya 3, sengaja dimasukkan lebih dari 3 agar terjadi execption dan melihat transaction di batalkan */ dummyService.saveBatch(dummy, mhs); /** pada DummyDAOImpl.java method saveBatch akan menyimpan ke tabel Dummy dan tabel mahasiswa, jika salah satunya gagal maka kedua duanya akan dibatalkan */ model.addAttribute("message", "Success kang --- "); } catch (Exception e) { // TODO: handle exception model.addAttribute("message", e.getMessage()); e.printStackTrace(); } return "dummy_list"; } }
Dan ketika kita running, apa yang terjadi sodara – sodara .. ?

Error Appear
dan ternyata kita berhasil membuat sebuah exception sederhana dengan memasukkan nilai length Name pada object Mahasiswa melebihi length yang diperbolehkan, dan kita bisa lihat di database hasilnya

Checking Data In Case Error Occur
oke segitu dulu penjelasan dari ane .. selamat mencoba ..