← Kursa Dön
📄 Text · 18 min

ORM, JPA ve Hibernate

Yazılım geliştirmenin en büyük zorluklarından biri, nesne yönelimli programlama (OOP) dünyası ile ilişkisel veritabanı (relational database) dünyası arasındaki uyumsuzluktur. Bu soruna Object-Relational Impedance Mismatch denir.

Nesne yönelimli dünyada: sınıflar, kalıtım, polimorfizm, kapsülleme ve nesne referansları vardır. İlişkisel veritabanı dünyasında ise: tablolar, satırlar, sütunlar, birincil anahtarlar, yabancı anahtarlar ve SQL sorguları vardır. Bu iki dünya temelden farklı paradigmalara sahiptir.

ORM (Object-Relational Mapping), bu iki dünya arasında köprü kuran bir teknolojidir. ORM, Java nesnelerini veritabanı tablolarına, nesne özelliklerini (field) tablo sütunlarına, nesne ilişkilerini yabancı anahtar bağlantılarına otomatik olarak eşleştirir. Böylece geliştiricinin doğrudan SQL yazmadan veritabanı işlemlerini nesne düzeyinde gerçekleştirmesini sağlar.

JDBC — Düşük Seviye Veritabanı Erişimi

ORM teknolojilerinden önce, Java'da veritabanı erişimi JDBC (Java Database Connectivity) ile yapılırdı. JDBC, doğrudan SQL sorguları yazmanızı, bağlantı yönetimi yapmanızı ve sonuç kümelerini (ResultSet) manuel olarak Java nesnelerine dönüştürmenizi gerektirir:

// JDBC ile kullanıcı sorgulama — zahmetli ve hata yapmaya açık
public User findById(Long id) {
    String sql = "SELECT id, name, email, age FROM users WHERE id = ?";
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;

    try {
        conn = dataSource.getConnection();
        stmt = conn.prepareStatement(sql);
        stmt.setLong(1, id);
        rs = stmt.executeQuery();

        if (rs.next()) {
            User user = new User();
            user.setId(rs.getLong("id"));
            user.setName(rs.getString("name"));
            user.setEmail(rs.getString("email"));
            user.setAge(rs.getInt("age"));
            return user;
        }
        return null;
    } catch (SQLException e) {
        throw new RuntimeException("Veritabanı hatası", e);
    } finally {
        // Kaynakları kapatma — unutulursa kaynak sızıntısı!
        try { if (rs != null) rs.close(); } catch (SQLException e) { }
        try { if (stmt != null) stmt.close(); } catch (SQLException e) { }
        try { if (conn != null) conn.close(); } catch (SQLException e) { }
    }
}

JDBC ile geliştirmenin sorunları:

  • Çok fazla boilerplate kod: Bağlantı açma/kapama, ResultSet parse, exception handling

  • SQL string'leri: Derleme zamanında kontrol edilmez, hata bulması zor

  • Manuel eşleştirme: Her tablo için tekrarlayan dönüşüm kodu

  • Kaynak yönetimi: Connection, Statement, ResultSet kapatmayı unutma riski

  • Taşınabilirlik: SQL diyalekt farkları (MySQL vs PostgreSQL vs Oracle)

JPA — Java Persistence API

JPA (Java Persistence API, Java 11+ sonrası Jakarta Persistence API), Java'da ORM için standart bir spesifikasyon (specification) dur. JPA bir kütüphane veya framework değildir — bir dizi interface ve annotation tanımıdır. Nasıl Java'da List bir interface ise ve ArrayList onun implementasyonu ise, JPA da bir interface seti, Hibernate ise onun implementasyonudur.

JPA'nın temel bileşenleri:

  • Entity: Veritabanı tablosuna karşılık gelen Java sınıfı (@Entity)

  • EntityManager: Entity'leri yöneten ve veritabanı işlemlerini gerçekleştiren merkezi API

  • JPQL: Java Persistence Query Language — SQL benzeri ama entity üzerinden sorgulama dili

  • Persistence Context: Entity'lerin yaşam döngüsünü yöneten ortam

// JPA ile aynı işlem — çok daha temiz
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String email;
    private int age;

    // getter/setter
}

// EntityManager ile sorgulama
public User findById(Long id) {
    return entityManager.find(User.class, id);  // Tek satır!
}

Hibernate — JPA İmplementasyonu

Hibernate, Gavin King tarafından 2001'de oluşturulan açık kaynak ORM framework'üdür. JPA spesifikasyonunun en popüler ve en yaygın kullanılan implementasyonudur. Hibernate, JPA standartlarını uygular ve üzerine ek özellikler ekler.

JPA ve Hibernate arasındaki ilişki şöyledir:

JPA (Spesifikasyon)            Hibernate (İmplementasyon)
├── @Entity                    ├── JPA annotation'larını uygular
├── EntityManager              ├── Session (EntityManager impl.)
├── JPQL                       ├── HQL (JPQL superset)
├── Criteria API               ├── Criteria API impl.
└── Transaction API            └── Transaction impl.

Diğer JPA implementasyonları:
├── EclipseLink (referans impl.)
├── OpenJPA (Apache)
└── DataNucleus

Spring Data JPA — Soyutlama Katmanı

Spring Data JPA, JPA/Hibernate üzerine bir soyutlama katmanı ekler ve veritabanı erişimini inanılmaz kolaylaştırır. Spring Data JPA ile, sadece interface tanımlayarak tam işlevsel repository'ler oluşturabilirsiniz:

// Spring Data JPA — sadece interface tanımlayın, implementasyon otomatik!
public interface UserRepository extends JpaRepository<User, Long> {

    // Method adından otomatik sorgu üretir
    List<User> findByName(String name);
    List<User> findByAgeGreaterThan(int age);
    Optional<User> findByEmail(String email);
    boolean existsByEmail(String email);
}

Katmanlar arası ilişki:

┌───────────────────────────────────┐
│       Spring Data JPA             │  ← En üst soyutlama
│  (Repository interface'leri)      │
├───────────────────────────────────┤
│           JPA                     │  ← Spesifikasyon
│  (EntityManager, @Entity, JPQL)  │
├───────────────────────────────────┤
│         Hibernate                 │  ← İmplementasyon
│  (Session, HQL, Cache)           │
├───────────────────────────────────┤
│          JDBC                     │  ← Düşük seviye
│  (Connection, Statement)         │
├───────────────────────────────────┤
│       Database Driver             │  ← Sürücü
│  (MySQL, PostgreSQL, H2)         │
└───────────────────────────────────┘

EntityManager ve Persistence Context

EntityManager, JPA'nın merkezinde yer alan API'dir. Entity'leri yönetir, sorgular çalıştırır ve transaction'ları koordine eder.

Persistence Context (Kalıcılık Bağlamı), EntityManager'ın yönettiği entity'lerin yaşadığı ortamdır. Bir entity, persistence context içinde dört durumdan birinde olabilir:

Entity Yaşam Döngüsü:

    New (Transient)
         │  persist()
         ▼
    Managed (Persistent)  ←──── find(), merge()
         │                        │
    remove()                 detach(), close()
         │                        │
         ▼                        ▼
    Removed              Detached
  • New (Transient): new User() ile oluşturulmuş ama henüz persist edilmemiş.

  • Managed (Persistent): EntityManager tarafından yönetiliyor. Değişiklikler otomatik olarak veritabanına yansır.

  • Detached: Persistence context'ten ayrılmış. Değişiklikler veritabanına yansımaz.

  • Removed: Silinmek üzere işaretlenmiş. Transaction commit'te veritabanından silinir.

// EntityManager kullanım örneği
@Service
@Transactional
public class UserService {

    @PersistenceContext
    private EntityManager entityManager;

    public User create(User user) {
        entityManager.persist(user);     // New → Managed
        return user;
    }

    public User findById(Long id) {
        return entityManager.find(User.class, id);  // → Managed
    }

    public void delete(Long id) {
        User user = entityManager.find(User.class, id);
        entityManager.remove(user);      // Managed → Removed
    }
}

Spring Boot JPA Yapılandırması

Spring Boot'ta JPA kullanmak çok kolaydır:

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>
# application.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

💡 Özet: ORM, nesne-ilişkisel uyumsuzluğu çözer. JPA bir spesifikasyon, Hibernate bir implementasyon, Spring Data JPA ise en üst soyutlama katmanıdır. Spring Boot, bu katmanları otomatik yapılandırarak geliştiriciyi altyapı detaylarından kurtarır.