Spring Transaction Management

Hibernate Logo

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 :

  1. Mengecek ketersediaan barang yang dimaksud di gudang (inventory)
  2. Setelah dipastikan ada, maka kita akan insert data ke tabel penjualan (dan penjualan detail)
  3. 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

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

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

Checking Data In Case Error Occur

oke segitu dulu penjelasan dari ane .. selamat mencoba ..

Leave a Reply