Memakai Querydsl Dengan Spring Data JPA


Spring Data JPA sangat mempermudah hidup saya karena sekarang saya cukup mengetik deklarasi method untuk mewakili query ke database. Tapi pada kasus tertentu, saya tetap merasa Spring Data repository saya masih bisa dirapikan. Sebagai contoh, saya memiliki sebuah tampilan seperti berikut ini:

Dialog Pencarian

Dialog Pencarian

Tampilan seperti ini memungkinkan pengguna untuk melakukan beberapa jenis pencarian, anggap saja pencarian “sama dengan” dan pencarian “mengandung“.  Seandainya ada 2 atribut di domain class yang dijadikan patokan pencarian, maka di Spring Data repository, saya harus membuat 4 method yang mewakili 4 query yang berbeda, seperti berikut ini:

public interface PemesananRepository extends JpaRepository<Pemesanan, Long> {

  @Query("..[query diabaikan]..")
  Page<Pemesanan> findPagePemesananByKodePemesanan(@Param("kodePemesanan") String kodePemesanan, Pageable pageable);

  @Query("..[query diabaikan]..")
  Page<Pemesanan> findPagePemesananByKodePemesanan(@Param("kodePemesanan") String kodePemesanan, Pageable pageable);  

  @Query("..[query diabaikan]..")
  Page<Pemesanan> findPagePemesananByNama(@Param("nama") String nama, Pageable pageable);  

  @Query("..[query diabaikan]..")
  Page<Pemesanan> findPagePemesananMengandungNama(@Param("nama") String nama, Pageable pageable);

}

Sekarang, bayangkan domain class Pemesanan diturunkan menjadi PemesananWeb dan PemesananKunjungan!  Kedua turunan Pemesanan ini akan ditampilkan dalam dua (2)  halaman yang berbeda!!  Karena setiap halaman wajib memiliki fitur pencarian, maka saya harus mengubah kode program di Spring Data repository menjadi mengandung delapan (8) method yang berbeda seperti berikut ini:

public interface PemesananRepository extends JpaRepository<Pemesanan, Long> {

  @Query("..[query diabaikan]..")
  Page<PemesananWeb> findPagePemesananWebByKodePemesanan(@Param("kodePemesanan") String kodePemesanan, Pageable pageable);

  @Query("..[query diabaikan]..")
  Page<PemesananWeb> findPagePemesananWebMengandungKodePemesanan(@Param("kodePemesanan") String kodePemesanan, Pageable pageable);  

  @Query("..[query diabaikan]..")
  Page<PemesananWeb> findPagePemesananWebByNama(@Param("nama") String nama, Pageable pageable);  

  @Query("..[query diabaikan]..")
  Page<PemesananWeb> findPagePemesananWebMengandungNama(@Param("nama") String nama, Pageable pageable);

  @Query("..[query diabaikan]..")
  Page<PemesananKunjungan> findPagePemesananKunjunganByKodePemesanan(@Param("kodePemesanan") String kodePemesanan, Pageable pageable);

  @Query("..[query diabaikan]..")
  Page<PemesananKunjungan> findPagePemesananKunjunganMengandungKodePemesanan(@Param("kodePemesanan") String kodePemesanan, Pageable pageable);  

  @Query("..[query diabaikan]..")
  Page<PemesananKunjungan> findPagePemesananKunjunganByNama(@Param("nama") String nama, Pageable pageable);  

  @Query("..[query diabaikan]..")
  Page<PemesananKunjungan> findPagePemesananKunjunganMengandungNama(@Param("nama") String nama, Pageable pageable);

}

Baru untuk pencarian saja, data repositorysaya sudah menjadi penuh!  Apa ada cara lain?   Jika saya berpikir untuk menghasilkan string JPQL/SQL secara manual dengan “if” , maka saya akan kehilangan fitur pageable (penghalaman) dari Spring Data.  Selain itu, menggunakan “if” dalam menghasilkan string JPQL/SQL rentan terhadap kesalahan!  Hal ini karena saya tidak akan mendapatkan “syntax error”  atau garis bawah warna merah di Eclipse jika saya salah ketik. Padahal impian semua developer adalah dapat secepat mungkin mengetahui bahwa dirinya telah berbuat kesalahan.  Yup! Developer yang tidak confidence atau sedang galau terhadap kode program yang barusan dibuatnya  biasanya akan setengah-tengah dalam melanjutkan membuat kode program.   Dan saya tidak bisa yakin JPQL/SQL yang saya buat sepenuhnya benar, bila saya belum menelusuri seluruh alur “if” yang ada!

Bagaimana dengan cara lain yang lebih elegan?  Saya bisa mencoba memakai Querydsl yang mirip dengan Criteria API.  Querydsl memungkinkan developer untuk menulis query melalui class, sehingga saat membuat kode program untuk query, developer dapat memakai Ctrl+Space dan memilih fungsi, nama atribut dan sebagainya.  Selain itu, karena ini JPQL/SQL dalam bentuk kode program, maka kesalahan ketik akan langsung ketahuan.

Sebelum dapat membuat kode program Querydsl, saya harus men-setup  Eclipse terlebih dahulu.  Langkah-langkah yang saya tempuh dapat dibaca di Men-setup Querydsl di Eclipse.

Setelah itu, saya dapat menghapus semua method (8 method pencarian di atas!) yang ada di Spring Data repository.  Saya perlu mengimplementasikan interface QueryDslPredicateExecutor.  Kode program berikut ini memperlihatkan isi Spring Data repository saya:

public interface PemesananRepository extends JpaRepository<Pemesanan, Long>, QueryDslPredicateExecutor<Pemesanan> {

  // isinya kosong

}

Selanjutnya, saya perlu menambahkan kode Querydsl pada kode program yang akan memanggil Spring Data repository.  Sebagai contoh, method yang dipakai untuk mencari pada PelangganWeb isinya akan terlihat seperti:

@Transactional(readOnly=true)
public Page getPagePencarianPemesananWeb(String field, String nilai, 
	JENISPENCARIAN jenisPencarian, Pageable pageable) {

  QPemesanan pemesanan = QPemesanan.pemesanan;
  QPemesananWeb pemesananWeb = pemesanan.as(QPemesananWeb.class);

  BooleanBuilder builder = new BooleanBuilder();

  if (field.equals("kodePemesanan")) {
	if (jenisPencarian==JENISPENCARIAN.SAMADENGAN) {				
		builder.and(pemesananWeb.kodePemesanan.equalsIgnoreCase(nilai));
	} else if (jenisPencarian==JENISPENCARIAN.MENGANDUNG) {
		builder.and(pemesananWeb.kodePemesanan.containsIgnoreCase(nilai));
	}
  } else if (field.equals("nama")) {
	if (jenisPencarian==JENISPENCARIAN.SAMADENGAN) {
		builder.and(pemesananWeb.pelangganWeb.nama.equalsIgnoreCase(nilai));
	} else if (jenisPencarian==JENISPENCARIAN.MENGANDUNG) {
		builder.and(pemesananWeb.pelangganWeb.nama.containsIgnoreCase(nilai));
	}
  }
  return pemesananRepository.findAll(builder, pageable);
}

Kode program di pencarian PemesananKunjungan tidak akan banyak berbeda.  Pada kode proram di atas, sama sekali tidak ada JPQL atau SQL.  Keuntungan penggunakan Querydsl akan semakin terlihat bila saya memungkinkan lebih banyak variasi pencarian, misalnya pencarian pencarian berdasarkan “nama” dan/atau “kode” sekaligus.

Perihal Solid Snake
I'm nothing...

One Response to Memakai Querydsl Dengan Spring Data JPA

  1. Ping-balik: Belajar Memakai Specification Di Spring Data JPA | The Solid Snake

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: