JPA/Hibernate ile ORM
Bu bölümde, e-ticaret uygulaması için JPA (Java Persistence API) ve Hibernate ORM (Object-Relational Mapping) yapılandırmasını detaylı olarak ele alacağız. JPA ve Hibernate, Java nesneleri ile ilişkisel veritabanı tabloları arasında eşleştirme yaparak, veritabanı işlemlerini nesne odaklı bir şekilde gerçekleştirmenizi sağlar.ORM Nedir?
ORM (Object-Relational Mapping), nesne yönelimli programlama dilleri ile ilişkisel veritabanları arasında bir köprü görevi gören bir programlama tekniğidir. ORM, veritabanı tablolarını Java sınıflarına, tablo sütunlarını sınıf alanlarına ve tablo satırlarını nesnelere eşleştirir. Bu sayede, SQL sorguları yazmak yerine, Java nesneleri üzerinde işlem yaparak veritabanı işlemlerini gerçekleştirebilirsiniz.JPA Nedir?
JPA (Java Persistence API), Java EE ve Java SE uygulamalarında ilişkisel veritabanı yönetimi için bir standart sağlayan bir Java spesifikasyonudur. JPA, ORM için bir standart tanımlar ve farklı ORM sağlayıcıları (Hibernate, EclipseLink, OpenJPA vb.) bu standardı uygular.Hibernate Nedir?
Hibernate, JPA spesifikasyonunu uygulayan en popüler ORM framework’üdür. Hibernate, JPA’nın tüm özelliklerini destekler ve ek olarak kendi özelliklerini de sunar. Spring Boot, varsayılan olarak Hibernate’i JPA sağlayıcısı olarak kullanır.Spring Data JPA Nedir?
Spring Data JPA, Spring Framework’ün bir parçasıdır ve JPA tabanlı repository’lerin uygulanmasını kolaylaştırır. Spring Data JPA, CRUD (Create, Read, Update, Delete) işlemleri için hazır metodlar sağlar ve özel sorgular oluşturmak için bir DSL (Domain Specific Language) sunar.JPA/Hibernate Yapılandırması
Spring Boot, otomatik yapılandırma özelliği sayesinde, JPA ve Hibernate için temel yapılandırmayı otomatik olarak yapar. Ancak, bazı özel ayarlar içinapplication.properties dosyasında yapılandırma yapmamız gerekebilir.
application.properties
- Veritabanı Bağlantı Ayarları: Veritabanı URL’si, kullanıcı adı, şifre ve sürücü sınıfı.
- JPA/Hibernate Ayarları:
spring.jpa.hibernate.ddl-auto: Hibernate’in veritabanı şemasını nasıl yöneteceğini belirtir.updatedeğeri, mevcut şemayı güncelleyeceğini belirtir.spring.jpa.show-sql: SQL sorgularının konsola yazdırılıp yazdırılmayacağını belirtir.spring.jpa.properties.hibernate.dialect: Hibernate’in hangi veritabanı dialektini kullanacağını belirtir.spring.jpa.properties.hibernate.format_sql: SQL sorgularının formatlanıp formatlanmayacağını belirtir.spring.jpa.properties.hibernate.use_sql_comments: SQL sorgularına yorum eklenip eklenmeyeceğini belirtir.spring.jpa.properties.hibernate.type: Bağlı parametrelerin değerlerinin loglanıp loglanmayacağını belirtir.
- Hibernate İstatistikleri: Hibernate’in istatistik toplamasını ve bu istatistiklerin loglanmasını sağlar.
- İkinci Seviye Önbellek: Hibernate’in ikinci seviye önbelleğini ve sorgu önbelleğini etkinleştirir.
Farklı Ortamlar için Yapılandırma
Farklı ortamlar (geliştirme, test, üretim) için farklı JPA/Hibernate yapılandırmaları kullanmak isteyebilirsiniz. Bu durumda, profil tabanlı yapılandırma kullanabilirsiniz.application-dev.properties (Geliştirme Ortamı)
application-prod.properties (Üretim Ortamı)
Entity Sınıflarında JPA Anotasyonları
JPA, entity sınıflarını ve ilişkilerini tanımlamak için çeşitli anotasyonlar sağlar. Bu anotasyonlar, Java sınıflarının veritabanı tablolarına nasıl eşleştirileceğini belirtir.Temel JPA Anotasyonları
- @Entity: Bir sınıfın entity olduğunu belirtir.
- @Table: Entity’nin eşleştirildiği veritabanı tablosunu belirtir.
- @Id: Birincil anahtar alanını belirtir.
- @GeneratedValue: Birincil anahtar değerinin nasıl oluşturulacağını belirtir.
- @Column: Alanın eşleştirildiği veritabanı sütununu belirtir.
- @Temporal: Tarih ve zaman alanlarının nasıl eşleştirileceğini belirtir.
- @Enumerated: Enum alanlarının nasıl eşleştirileceğini belirtir.
- @Transient: Alanın veritabanına eşleştirilmeyeceğini belirtir.
İlişki Anotasyonları
- @OneToOne: Bire bir ilişkiyi belirtir.
- @OneToMany: Bire çok ilişkiyi belirtir.
- @ManyToOne: Çoka bir ilişkiyi belirtir.
- @ManyToMany: Çoka çok ilişkiyi belirtir.
- @JoinColumn: İlişki için kullanılan yabancı anahtar sütununu belirtir.
- @JoinTable: Çoka çok ilişkiler için kullanılan bağlantı tablosunu belirtir.
Örnek Entity Sınıfı
İlişki Yönetimi
JPA, entity’ler arasındaki ilişkileri yönetmek için çeşitli özellikler sağlar. Bu özellikler, ilişkilerin nasıl yükleneceğini, güncellemelerin nasıl yayılacağını ve ilişkili entity’lerin nasıl silineceğini belirler.Fetch Tipi
Fetch tipi, ilişkili entity’lerin ne zaman yükleneceğini belirler. İki tür fetch tipi vardır:- EAGER: İlişkili entity’ler, ana entity yüklendiğinde hemen yüklenir.
- LAZY: İlişkili entity’ler, ihtiyaç duyulduğunda (erişildiğinde) yüklenir.
Cascade Tipi
Cascade tipi, bir entity üzerindeki işlemlerin ilişkili entity’lere nasıl yayılacağını belirler. Örneğin, bir entity silindiğinde, ilişkili entity’lerin de silinip silinmeyeceğini belirler.- ALL: Tüm işlemler (PERSIST, MERGE, REMOVE, REFRESH, DETACH) yayılır.
- PERSIST: Kaydetme işlemi yayılır.
- MERGE: Birleştirme işlemi yayılır.
- REMOVE: Silme işlemi yayılır.
- REFRESH: Yenileme işlemi yayılır.
- DETACH: Ayırma işlemi yayılır.
orphanRemoval
orphanRemoval özelliği, bir koleksiyondan kaldırılan entity’lerin veritabanından da silinip silinmeyeceğini belirler. true olarak ayarlandığında, koleksiyondan kaldırılan entity’ler veritabanından da silinir.
mappedBy
mappedBy özelliği, ilişkinin hangi entity tarafından yönetildiğini belirtir. İlişkinin sahibi olmayan tarafta kullanılır ve ilişkinin sahibi olan entity’deki alanın adını belirtir.
ProductImage entity’sindeki product alanı ilişkinin sahibidir.
İlişki Türleri
JPA, dört tür ilişkiyi destekler: bire bir, bire çok, çoka bir ve çoka çok. Her ilişki türü, farklı anotasyonlar ve özellikler kullanılarak tanımlanır.Bire Bir İlişki (@OneToOne)
Bire bir ilişki, bir entity’nin başka bir entity ile bire bir ilişkisi olduğunu belirtir. Örneğin, bir sipariş bir ödeme ile ilişkilendirilebilir.Bire Çok İlişki (@OneToMany) ve Çoka Bir İlişki (@ManyToOne)
Bire çok ilişki, bir entity’nin birden fazla başka entity ile ilişkisi olduğunu belirtir. Çoka bir ilişki, bunun tersidir. Örneğin, bir kategori birden fazla ürüne sahip olabilir, ancak bir ürün yalnızca bir kategoriye ait olabilir.Çoka Çok İlişki (@ManyToMany)
Çoka çok ilişki, her iki entity’nin de birden fazla diğer entity ile ilişkisi olduğunu belirtir. Örneğin, bir ürün birden fazla etikete sahip olabilir ve bir etiket birden fazla ürüne ait olabilir.JPA Yaşam Döngüsü
JPA entity’leri, belirli bir yaşam döngüsüne sahiptir. Bu yaşam döngüsü, entity’nin durumunu ve veritabanı ile olan ilişkisini tanımlar.Entity Durumları
- Transient (Geçici): Entity henüz veritabanına kaydedilmemiştir ve bir
EntityManagerile ilişkilendirilmemiştir. - Managed (Yönetilen): Entity bir
EntityManagertarafından yönetilmektedir ve veritabanı ile senkronize edilecektir. - Detached (Ayrılmış): Entity daha önce bir
EntityManagertarafından yönetilmiştir, ancak artık yönetilmemektedir. - Removed (Silinmiş): Entity bir
EntityManagertarafından yönetilmektedir, ancak veritabanından silinmek üzere işaretlenmiştir.
Entity Yaşam Döngüsü Olayları
JPA, entity yaşam döngüsü olaylarını dinlemek için çeşitli anotasyonlar sağlar. Bu anotasyonlar, belirli olaylar gerçekleştiğinde çalıştırılacak metodları işaretlemek için kullanılır.- @PrePersist: Entity veritabanına kaydedilmeden önce çağrılır.
- @PostPersist: Entity veritabanına kaydedildikten sonra çağrılır.
- @PreUpdate: Entity güncellenmeden önce çağrılır.
- @PostUpdate: Entity güncellendikten sonra çağrılır.
- @PreRemove: Entity silinmeden önce çağrılır.
- @PostRemove: Entity silindikten sonra çağrılır.
- @PostLoad: Entity veritabanından yüklendikten sonra çağrılır.
JPA Sorgulama
JPA, veritabanı sorgularını gerçekleştirmek için çeşitli yöntemler sağlar. Bu yöntemler, JPQL (Java Persistence Query Language), Criteria API ve Native SQL sorgularını içerir.JPQL (Java Persistence Query Language)
JPQL, SQL’e benzer bir sorgu dilidir, ancak veritabanı tablolarını ve sütunlarını değil, entity’leri ve alanlarını hedef alır.Criteria API
Criteria API, JPQL sorgularını programatik olarak oluşturmak için bir API sağlar. Bu, tip güvenliği ve daha dinamik sorgular oluşturma yeteneği sağlar.Native SQL
JPA, native SQL sorguları çalıştırma yeteneği de sağlar. Bu, veritabanına özgü özellikleri kullanmanız gerektiğinde faydalıdır.JPA Önbelleği
JPA, performansı artırmak için çeşitli önbellek seviyeleri sağlar. Bu önbellekler, veritabanı sorgularının sayısını azaltarak uygulamanın performansını artırır.Birinci Seviye Önbellek
Birinci seviye önbellek,EntityManager seviyesinde çalışır ve varsayılan olarak etkindir. Bu önbellek, aynı EntityManager içinde aynı entity’nin tekrar yüklenmesini önler.
İkinci Seviye Önbellek
İkinci seviye önbellek,EntityManagerFactory seviyesinde çalışır ve farklı EntityManager örnekleri arasında paylaşılır. Bu önbellek, varsayılan olarak devre dışıdır ve etkinleştirmek için yapılandırma gerektirir.
@Cacheable anotasyonu kullanılır:
Sorgu Önbelleği
Sorgu önbelleği, JPQL ve Criteria API sorgularının sonuçlarını önbelleğe alır. Bu önbellek, varsayılan olarak devre dışıdır ve etkinleştirmek için yapılandırma gerektirir.setHint metodunu kullanabilirsiniz: