Hibernate second level cache nedir?
Hibernate, bir Java nesne/ilişkisel eşleme (ORM) çerçevesidir ve uygulamaların veritabanı işlemlerini kolaylaştırmak için kullanılır. Hibernate'de "ikinci seviye önbellek" (second level cache), uygulamanın performansını artırmak için veri erişimini hızlandırmak adına kullanılır.
Bir Hibernate uygulamasında, birincil önbellek otomatik olarak uygulamalar tarafından kullanılır ve herhangi bir ek yapılandırmaya ihtiyaç duymaz. Bu, bir veriye ilk erişildiğinde veritabanından alınan ve bir oturum boyunca kullanılan veriyi ifade eder. Bununla birlikte, bu veri her oturum için ayrı ayrı alınır ve diğer oturumlarla paylaşılmaz.
Buna karşın, ikinci seviye önbellek birden fazla oturum arasında paylaşılır. Bu, daha önce yüklenmiş bir nesne aynı uygulama tarafından tekrar talep edildiğinde, Hibernate'in bu veriyi ikinci seviye önbellekten alabileceği ve bu sayede veritabanına tekrar erişim yapmasına gerek kalmayacağı anlamına gelir. Bu, genellikle uygulamanın performansını önemli ölçüde artırabilir.
Hibernate, ikinci seviye önbellek için birçok popüler önbellek sağlayıcıyı destekler, örneğin EhCache, Infinispan ve Hazlecast. İkinci seviye önbelleği kullanma kararı ve hangi önbellek sağlayıcısını kullanacağınız genellikle uygulamanızın gereksinimlerine ve ölçeklenebilirlik gerekliliklerine bağlıdır.
Hibernate'de ikinci seviye önbellek kullanmanın bazı avantajları vardır:
Performansı Artırır: Veritabanı işlemleri genellikle zaman alır ve bu da uygulamanın performansını etkileyebilir. İkinci seviye önbellek kullanmak, aynı veriye birden fazla kez erişim ihtiyacını azaltır, böylece veritabanı üzerindeki yükü azaltır ve genel performansı artırır.
Ağ Trafiğini Azaltır: Veritabanından veri almak, genellikle ağ üzerinden bir miktar veri transferi gerektirir. Bu, özellikle büyük veri setleriyle çalışırken önemli bir faktör olabilir. İkinci seviye önbellek, ağ trafiğini azaltarak ve gerekli veri transferlerini minimuma indirerek bu yükü azaltır.
Veritabanı Bağlantılarını Azaltır: Her veritabanı bağlantısı, bir miktar sistem kaynağı gerektirir. İkinci seviye önbellek, veritabanı ile yapılacak olan gereksiz bağlantıları önleyerek sistem kaynaklarının daha verimli bir şekilde kullanılmasını sağlar.
Bununla birlikte, ikinci seviye önbelleğin dikkatli bir şekilde yönetilmesi gerekir. Önbellekte tutulan verinin güncel olmaması durumunda, uygulama eski veya yanıltıcı bilgilere dayalı kararlar alabilir. Bu nedenle, önbelleğin düzenli olarak güncellenmesi ve verinin zamanında geçersiz kılınması önemlidir.
Ayrıca, farklı önbellek sağlayıcıları farklı özelliklere sahip olabilir ve her uygulama için en iyi önbellek sağlayıcısını seçmek önemlidir. Önbellek sağlayıcısının seçimi, veritabanı erişiminin gerekliliklerine, uygulamanın ölçeğine ve önbelleğin yönetilme şekline bağlı olabilir.
Hibernate'deki ikinci seviye önbellek (second level cache), oturum fabrikası düzeyinde bulunur. Bu, farklı oturumlar (Session) arasında paylaşılan verinin saklandığı yerdir.
Her Hibernate oturumu (Session), birinci seviye önbellek (first level cache) olarak da bilinen kendi önbelleğine sahiptir. Bir oturum boyunca alınan tüm nesneler bu önbellekte saklanır. Ancak, bu önbellek sadece o oturum için geçerlidir ve oturum sona erdiğinde önbellek de boşaltılır.
Buna karşılık, ikinci seviye önbellek bir oturum fabrikası (SessionFactory) düzeyinde bulunur. Bu, tüm oturumlar arasında paylaşılan ve oturumlar sona erdikten sonra bile veriyi tutabilen bir önbellektir. İkinci seviye önbellek, aynı veriye birden fazla oturumdan erişim gerektiğinde verimlilik sağlar.
Sonuç olarak, ikinci seviye önbellek birden çok oturum arasında paylaşılan veriyi tutar ve bu veriyi tüm oturumlar arasında kullanılabilir hale getirir. Bu, özellikle verinin sık sık kullanıldığı durumlarda performansı önemli ölçüde artırabilir.
Hibernate ve Spring Boot ile ikinci seviye önbellekleme yapmak için bir Cache Provizyonu (Cache Provider) kullanılmalıdır. EhCache, Hazelcast, Infinispan gibi çeşitli cache provizyonları vardır. Bu örnekte, popüler bir cache provizyonu olan EhCache kullanılacak.
Öncelikle projenize EhCache ve Hibernate'in EhCache'i desteklemesi için gereken bağımlılıkları ekleyin:
xml
Copy code
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
</dependency>
</dependencies>
Daha sonra application.properties dosyanızda aşağıdaki Hibernate ikinci seviye önbellekleme ayarlarını yapın:
properties
Copy code
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
Bunlar sırasıyla:
İkinci seviye önbelleklemeyi aktif eder
Sorgu önbellekleme özelliğini aktif eder
Cache bölgesi için fabrika sınıfını ayarlar
Entity sınıflarınızda önbelleklemeyi aktifleştirmek için @Cacheable ve @Cache annotation'ları kullanın:
java
Copy code
import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Book {
@Id
private Long id;
// other fields, getters and setters...
}
Bu örnekte @Cacheable annotation'ı entity sınıfının önbelleklenebilir olduğunu belirtir ve @Cache annotation'ı önbelleklemenin nasıl yapılacağını belirler. Yukarıdaki durumda, READ_WRITE stratejisi, verinin okuma ve yazma işlemlerinde önbelleklenmesini sağlar.
Son olarak, EhCache yapılandırmasını ehcache.xml dosyası ile yapmanız gerekiyor:
xml
Copy code
<ehcache>
<defaultCache
maxElementsInMemory="100"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="200" >
</defaultCache>
<cache
name="com.example.Book"
maxElementsInMemory="100"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="200" >
</cache>
</ehcache>
Bu XML dosyasında, genel ve özelleştirilmiş önbellek politikalarını tanımlarsınız. Bu örnekte, com.example.Book entity'si için özel bir önbellek politikası tanımlanmıştır. Bu dosyayı classpath içinde (genellikle src/main/resources klasörü) oluşturmanız gerekiyor.
Sonuç olarak, bu yaklaşım ile Hibernate ve Spring Boot kullanarak ikinci seviye önbellekleme yapabilirsiniz.
Bahsettiğim bu adımlar genellikle Spring Boot ve Hibernate ile ikinci seviye önbelleklemeyi gerçekleştirmek için gerekli olan adımlardır. Ancak, uygulamanızın ihtiyaçlarına bağlı olarak bazı ek adımlar gerekebilir.
Örneğin, önbellek ayarlarını dinamik olarak değiştirmeniz gerekiyorsa, EhCache Manager'ı kullanabilirsiniz.
java
Copy code
import net.sf.ehcache.CacheManager;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CacheConfig {
@Bean
public EhCacheCacheManager cacheManager() {
return new EhCacheCacheManager(CacheManager.create());
}
}
Eğer daha fazla kontrol veya önbellek ile ilgili daha fazla bilgiye ihtiyacınız varsa, Spring'in CacheManager ve Cache arayüzlerini kullanabilirsiniz. CacheManager önbellekleri almak ve yönetmek için kullanılırken, Cache belirli bir önbellek üzerinde işlem yapmak için kullanılır.
java
Copy code
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
@Component
public class CacheService {
private final CacheManager cacheManager;
@Autowired
public CacheService(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
public void evictSingleCacheValue(String cacheName, String cacheKey) {
Cache cache = cacheManager.getCache(cacheName);
if (cache != null) {
cache.evict(cacheKey);
}
}
public void evictAllCacheValues(String cacheName) {
Cache cache = cacheManager.getCache(cacheName);
if (cache != null) {
cache.clear();
}
}
}
Bu örnekte CacheService, bir önbellekteki belirli bir değeri kaldırmak veya bir önbellekteki tüm değerleri kaldırmak için kullanılabilir.
Ayrıca, önbellekleme hatalarını işlemek için Spring'in @CacheEvict annotation'ını kullanabilirsiniz. Bu annotation, bir metot çağrısı sonrasında belirli bir önbellekteki değerleri kaldırmak için kullanılır. Örneğin, bir kitap güncellendikten sonra, bu kitapla ilgili önbellekteki tüm değerlerin kaldırılması gerekebilir.
java
Copy code
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
@Service
public class BookService {
@Autowired
private BookRepository bookRepository;
@CacheEvict(cacheNames = "books", allEntries = true)
public void updateBook(Book book) {
bookRepository.save(book);
}
}
Bu örnekte @CacheEvict annotation'ı updateBook metodu çağrıldıktan sonra "books" önbellekteki tüm değerlerin kaldırılmasını sağlar. Bu sayede, önbellekte tutulan güncellenmiş kitap bilgilerinin güncel olduğundan emin olabiliriz.
Elbette, belirli senaryolarda, belirli bir önbellekteki değerleri otomatik olarak güncellemek isteyebilirsiniz. Bu durumda @CachePut annotation'ını kullanabilirsiniz. Bu annotation, bir metot çağrıldıktan sonra belirli bir önbellekteki bir değeri otomatik olarak günceller.
java
Copy code
import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;
@Service
public class BookService {
@Autowired
private BookRepository bookRepository;
@CachePut(cacheNames = "books", key = "#book.id")
public Book updateBook(Book book) {
return bookRepository.save(book);
}
}
Bu örnekte @CachePut annotation'ı updateBook metodu çağrıldıktan sonra "books" önbellekteki belirli bir değerin (bu durumda güncellenen kitabın ID'si) otomatik olarak güncellenmesini sağlar.
Bir diğer konu da önbelleğin boyutudur. Önbelleğin boyutunu kontrol altında tutmak önemlidir çünkü aşırı büyük bir önbellek hem belleği hem de performansı olumsiz etkileyebilir. EhCache yapılandırma dosyası (ehcache.xml), önbelleğin maksimum boyutunu kontrol etmek için kullanılabilir.
xml
Copy code
<ehcache>
<defaultCache
maxElementsInMemory="100"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="200" >
</defaultCache>
<cache
name="com.example.Book"
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="200" >
</cache>
</ehcache>
Bu örnekte, "com.example.Book" önbelleğinin boyutu maksimum 500 element olarak belirlenmiştir.
Son olarak, önbellek durumunu izlemek için JMX (Java Management Extensions) kullanılabilir. JMX, Java uygulamalarını izlemek ve yönetmek için bir standarttır ve EhCache bu standartı destekler. JMX'i kullanarak önbellekte ne kadar alanın kullanıldığını, kaç önbellek girişinin olduğunu ve daha fazlasını görebilirsiniz.
xml
Copy code
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true">
<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, multicastGroupPort=4446, timeToLive=32"/>
<cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" properties="port=40001, remoteObjectPort=40002"/>
<defaultCache maxElementsInMemory="100" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="200"/>
<cache name="com.example.Book" maxElementsInMemory="500" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="200">
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" properties="replicatePuts=true, replicateUpdates=true, replicateUpdatesViaCopy=true, replicateRemovals=true"/>
</cache>
</ehcache>
Bu örnekte, EhCache'nin JMX'i desteklemek için yapılandırıldığını ve ayrıca RMICacheManagerPeerListenerFactory ve RMICacheReplicatorFactory'nin kullandığı portların belirtildiğini görüyoruz.
Önbellekleme karmaşık bir konudur ve bu kılavuz genel bir bakış sunmaktadır. Önbelleklemenin yararlarına ulaşmak için uygulamanızın ihtiyaçlarını ve senaryolarını dikkatlice değerlendirmeniz gerekmektedir.