Terlihat bahwa query "from Person" dieksekusi seratus kali dalam kode Java, tetapi kalau dilihat outputnya, Hibernate hanya akan mengeksekusi query sekali saja pada saat pertama kali. Hibernate tidak akan mengeksekusi SQL untuk query berikutnya, tetapi menggunakan nilai yang sama yang diambil dari First level cache.
Second level cache
Sifat First level cache yang hanya hidup dalam satu scope transaksi yang sangat pendek, terkadang tidak sesuai dengan kebutuhan optimisasi data yang sering dibaca oleh aplikasi dalam proses berbeda. Second level cache memenuhi kebutuhan ini dengan melakukan cache daam satu scope aplikasi, dimana cache akan berada dalam SessionFactory, sehingga cache akan bisa terus dipertahankan selama sessionFactory tersebut tidak diclose, yang artinya aplikasi dimatikan. SessionFactory akan dibuat ketika distart aplikasinya dan diclose ketika aplikasi ditutup.
Perlu diwaspadai dalam penggunaan second level cache ini, karena cache tidak akan diupdate kalau proses update data dilakukan darii proses lain tanpa menggunakan SessionFactory yang sama, misalnya ada satu proses di background yang akan melakukan perubahan data atau
peruahan data dilakukan manual langsung ke database dari RDBMS admin tool. Walaupun bisa saja dibuat sebuah konfgurasi yang secara periodik akan mengupdate cache.
Second level cache mempunyai beberapa setrategi, antara lain : only, non strict read-write, read-read-write, dan transactional. Mari kita bahas satu per satu mode di atas.
Read-Only digunakan kalau data yang dicache tidak pernah dirubah sama sekali, misalnya entity Menu, kalau ada perubahan di Entity menu maka apalikasi harus direstart agar cachenya direfresh. Strategi ini mempunyai kinerja paling bagus dan aman digunakan dalam lingkungan cluster.
Read-Write digunakan kalau data yang dicache akan diupdate. Strategi ini tidak boleh digunakan jika transaction isolation level yang digunakan adalah Serializable. Jika digunakan dalam lingkungan cluster, harus dipastikan bahwa cache provider mendunkung locking terhadap cache data.
Nonstrict Read-Write digunakan jika data hanya sesekali diupdate dan dipastikan bahwa tidak akan pernah ada proses mengupdate data ini secara simultan dari dua buah mesin berbeda dalam satu cluster.
Transactional menyediakan dukungan penuh terhadap transactional cache dalam lingkunan cluster. Cache dengan feature ini harus digunakan bersama denga JTA provider yang mendukung clustering.
Sebelum memulai menggunakan Second level cache, yang pertama harus dilakukan adalah memilih cache provider yang sesuai, karena tidak ada satupun cache provider yang mendukung semua strategi, pilih cache provider yang sesuai dengan kebutuhan aplikasi. Ada beberapa cache provoder yang didukung oleh Hibernate, setiap cache provider mempunyai feature dan kemampuan yang berbeda-beda, silahkan pilih cache provider yang sesuai dengan kebutuhan aplikasi.
Berikut ini cache provider yang didukung oleh Hibernate
Nama Read-Only Non strict read write
Read Write Transactional
EhCache Yes Yes Yes No
OSCache Yes Yes Yes No
SwarmCache Yes Yes No No
Jboss TreeCache Yes No No Yes
Sebagai contoh, kita akan menggunakan EhCache sebagai cache provider. Berikut ini konfgurasi yang harus ditambahkan dalam hibernate.cfg.xml :
<property name="cache.provider_class"> org.hibernate.cache.EhCacheProvider </property>
<property name="cache.use_second_level_cache">true</property> Selanjutnya buat sebuah xml konfgurasi dengan isi sebagai berikut :
<?xml version="1.0" encoding="UTF-8"?> <ehcache> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <cache name="com.googlecode.projecttemplate.model.Menu" eternal="true" overflowToDisk="false" />
<cache name="com.googlecode.projecttemplate.model.Person" maxElementsInMemory="1000" eternal="false" timeToIdleSeconds="900" timeToLiveSeconds="1800" overflowToDisk="true" /> </ehcache>
Konfgurasi di atas memperlihatkan bahwa entity yang dicache adalah Menu dan Person, kemudian ada beberapa konfgurasi lain yang diset, mari kita bahas satu per satu :
• diskStore konfgurasi ini digunakan untuk meletakkan cache di disk kalau memory tidak mencukupi. Disk Store berguna kalau database dan aplikasi diletakkan dalam server berbeda, sehingga akses data dari local hardisk lebih cepat daripada akses database yang berada di hardisk server lain
• defaultCache digunakan untuk mendefnisikan attribute default dari ehcache. Attribute yang ada dalam defaultCache akan dioverride oleh attribute yang sama dalam tag cache
• cache tag digunakan untuk mendefnisikan Entity apa saja yang akan dicache dalam Hibernate, attribute name berisi nama class dari Entitynya.
• maxElementsInMemory digunakan untuk mendefnisikan berapa maximum jumlah object entity yang akan disimpan dalam cache.
• eternal true digunakan untuk menandai bahwa cache ini akan hidup selamanya, tidak diganti atau diupdate selama aplikasi berjalan. Perhatikan bahwa untuk menu nilai eternal adalah true, karena selama aplikasi berjalan menu tidak kan berubah sama sekali, sedangkan untuk Person nilai eternal adalah false, artinya ada kemungkinan nilai Persin ini bisa berubah dan cache harus mengupdate nilainya jika ada perubahan.
• overlowToDisk true menandakan bahwa cache untuk Person bisa disimpan dalam hardisk jika memory sudah tidak mencukupi. Sedangkan cache untuk Menu mempunyai nilai false, artinya semua cache untuk menu akan disimpan dalam memory dan tidak ada yang disimpan dalam hardisk.
• timeToLiveSeconds digunakan untuk mendefnisikan berapa lama cache hidup sebelum berusaha diupdate dari database. Setelah time to live dilewati maka cache akan diremove dan request berikutnya yang memerlukan cache tersebut akan diambil lagi dari database.
• timeToIdleSeconds digunakan untuk menandai berapa lama cache tidak digunakan sebelum deremove. Kalau data tersebut sudah mencapai waktu di timeTiIdleSeconds tanpa sekalipun diakses, maka data akan diremove dari cache. Hal ini dimaksudkan untuk menghindari cache diisi oleh data yang jarang digunakan, sehingga ukuranya akan semakin membengkak.
Tidak perlu ada konfgurasi untuk memberitahu hibernate tentang adanya fle ehcache.xml ini, library ehcache akan secara otomatis mencari fle ini, ehcache.xml harus berada dalam classpath agar dapat ditemukan.
Perubahan lain yang perlu dilakukan adalah disisi mappingnya, di dalam class Menu dan Person perlu ditambahkan annotation @Cache dan mendeklarasikan strategi apa yang digunakan.
@Entity
@Table(name="T_MENU")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) public class Menu impelements Serializable{ }
Seperti yang kita bahas sebelumnya, entity Menu akan menggunakan strategi read-only karena sifatnya yang tidak akan berubah selama aplikasi berjalan, jika menu akan berubah maka aplikasi harus direstart.
@Table(name="T_PERSON",uniqueConstraints={@UniqueConstraint(columnNames={"NAME"} )})
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE) public class Person implements Serializable { }
Entity Person menggunakan strategi read-write karena ada kemungkinan nilai-nilai entity ini berubah dengan adanya penambahan atau edit data person.
Second level cache paling tepat digunakan untuk data yang sering dibaca tetapi jarang ditulis seperti table-table catalog atau table master. Seperti dalam caontoh di atas adalah Entity Menu dan Entity Person. Perlu diketahui juga bahwa cache ini hidupnya di dalam SessionFactory, sehingga akan memberikan efek jika digunakan dalam arsitektur Three Tier, dimana hanya ada satu SessionFactory yang berada di thier application server. Jika aplikasinya menggunakan arsitektur client server dimana setiap client akan langsung terhubung dengan database dan setiap client mempunyai SessionFactory sendiri-sendiri, maka second level cache menjadi tidak relevan dan sebaiknya tidak digunakan dalam arsitektur client-server.