0Pricing
Java Academy · Ders

PreparedStatement

Güvenli parametreli sorgular

PreparedStatement, CoddyKit'te ücretsiz bir Java Academy dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Java Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Java Academy kursu toplamda 4 dersten oluşur.

Neden PreparedStatement?

SQL'i kullanıcı girdisini birleştirerek oluşturmak tehlikeli ve yavaştır.

PreparedStatement her iki sorunu da çözer:

  • Güvenlik — değerler SQL'den ayrı gönderilir ve SQL enjeksiyonu önlenir.
  • Performans — veritabanı sorguyu bir kez ayrıştırıp planlayabilir ve ardından yeniden kullanabilir.

SQL Enjeksiyonu Sorunu

Dize birleştirme kullanarak bir sorgu oluşturduğunuzu düşünün. Kullanıcı adı olarak '; DROP TABLE users; -- yazarsa, birleştirilen SQL bunu komut olarak çalıştırır.

Bu, en eski ve en zararlı web güvenlik açıklarından biri olan SQL enjeksiyonudur. PreparedStatement bunu tasarımı gereği imkânsız hâle getirir.

public class Main {
    public static void main(String[] args) {
        String userInput = "'; DROP TABLE users; --";
        // Dangerous: never do this
        String unsafe = "SELECT * FROM users WHERE name = '" + userInput + "'";
        System.out.println("Injected SQL becomes:");
        System.out.println(unsafe);
    }
}

Yer Tutucular

Bir PreparedStatement içinde, daha sonra sağlayacağınız her değer için bir ? yazarsınız.

Ardından değerleri tür uyumlu ayarlayıcılarla bağlarsınız:

  • ps.setString(1, name)
  • ps.setInt(2, age)

Parametre dizinleri 1 tabanlıdır ve ? işaretlerinin sırasıyla eşleşir.

Güvenli Bir Sorgu

İfadeyi prepareStatement ile oluşturun, parametreleri bağlayın ve ardından executeQuery çağırın.

Değer SQL metnine hiç dokunmadığı için kullanıcı ne yazarsa yazsın enjeksiyon gerçekleşemez.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/shop";
        String sql = "SELECT id FROM users WHERE name = ?";
        try (Connection conn = DriverManager.getConnection(url, "app", "secret");
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setString(1, "Ada");
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) System.out.println(rs.getInt("id"));
            }
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

Birden Çok Parametreyi Bağlama

Her ? için ayrı bir ayarlayıcı çağrısı yapılır. Sıra önemlidir: 1. parametre ilk ?, 2. parametre ikinci ? ve bu şekilde devam eder.

Sütun türüyle eşleşen ayarlayıcıyı kullanın: setInt, setString, setDouble, setBoolean ve benzerleri.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/shop";
        String sql = "INSERT INTO users(name, age, active) VALUES (?, ?, ?)";
        try (Connection conn = DriverManager.getConnection(url, "app", "secret");
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setString(1, "Grace");
            ps.setInt(2, 42);
            ps.setBoolean(3, true);
            int rows = ps.executeUpdate();
            System.out.println("Inserted " + rows + " row");
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

NULL İşleme

Bir SQL NULL değerini bağlamak için bir java.sql.Types sabitiyle birlikte setNull(index, type) kullanın.

Bir Java null değerini setString yöntemine verip çalışmasını ummayın; açıkça belirtin:

  • ps.setNull(2, java.sql.Types.INTEGER)

Oluşturulan Anahtarları Alma

Bir INSERT işleminden sonra çoğu zaman otomatik oluşturulan kimliğe ihtiyaç duyarsınız.

Hazırlama sırasında Statement.RETURN_GENERATED_KEYS değerini geçirin ve ardından ps.getGeneratedKeys() ile okuyun.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/shop";
        String sql = "INSERT INTO users(name) VALUES (?)";
        try (Connection conn = DriverManager.getConnection(url, "app", "secret");
             PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
            ps.setString(1, "Linus");
            ps.executeUpdate();
            try (ResultSet keys = ps.getGeneratedKeys()) {
                if (keys.next()) System.out.println("New id: " + keys.getLong(1));
            }
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

Toplu INSERT İşlemleri

Binlerce satırı tek tek eklemek yavaştır. Toplu işlem kullanın:

  • Parametreleri bağlayın ve ardından ps.addBatch() çağrısını yapın.
  • Her satır için tekrarlayın.
  • Bir kez ps.executeBatch() çağrısını yapın.

Bu işlem satırları birlikte göndererek veritabanına yapılan gidiş gelişleri büyük ölçüde azaltır.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:postgresql://localhost:5432/shop";
        String sql = "INSERT INTO tags(label) VALUES (?)";
        String[] labels = {"java", "jdbc", "sql"};
        try (Connection conn = DriverManager.getConnection(url, "app", "secret");
             PreparedStatement ps = conn.prepareStatement(sql)) {
            for (String label : labels) {
                ps.setString(1, label);
                ps.addBatch();
            }
            int[] counts = ps.executeBatch();
            System.out.println("Batched " + counts.length + " inserts");
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }
}

Bir İfadeyi Yeniden Kullanma

Tek bir PreparedStatement, farklı parametrelerle birçok kez çalıştırılabilir.

Yer tutuculara değerleri yeniden bağlayın ve execute çağrısını tekrar yapın. Veritabanı önbelleğe alınmış yürütme planını yeniden kullanır; hazırlanan ifadelerin tekrarlanan sorgularda daha hızlı olmasının nedeni budur.

Asla Birleştirmeyin

Altın kural şudur: değişken olan her değer bir ? parametresi olmalıdır.

Yalnızca sabit ve kod tarafından denetlenen tanımlayıcılar (izin verilenler listesinde bulunan bir sütun adı gibi) birleştirilebilir; o durumda bile izin verilenler listesine göre doğrulama yapın. Kullanıcı tarafından sağlanan veriler her zaman bağlanmalı, asla birleştirilmemelidir.

Kapatma ve Yeniden Kullanım Kapsamı

Bir PreparedStatement, kendi Connection nesnesine bağlıdır ve işiniz bittiğinde kapatılmalıdır.

Kaynaklarla try içinde ifadeyi bağlantıdan önce kapanacak şekilde bildirin. Bir ifadeyi döngü içinde birçok kez yeniden kullanıyorsanız, döngünün dışında bir kez hazırlayın ve döngünün içinde yalnızca parametreleri yeniden bağlayın; her yinelemede yeniden hazırlamak önbelleğe alınmış planı boşa çıkarır.

Kısa Kontrol

PreparedStatement SQL enjeksiyonunu neden önler?

Özet

Güvenli ve hızlı sorgular yazmayı öğrendiniz:

  • ? yer tutucularını ve türü belirli ayarlayıcıları (1 tabanlı dizin) kullanın.
  • Değerleri setString, setInt, setNull vb. ile bağlayın.
  • Otomatik anahtarları RETURN_GENERATED_KEYS ve getGeneratedKeys ile alın.
  • Çok sayıda yazma işlemini addBatch + executeBatch ile toplu olarak gerçekleştirin.
  • Kullanıcı girdisini SQL ile asla birleştirmeyin.

Sıkça Sorulan Sorular

“PreparedStatement” dersi ücretsiz mi?

Evet — “PreparedStatement” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Java Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Java Academy kursu toplamda 4 dersten oluşur.

“PreparedStatement” dersinde ne öğreneceğim?

Güvenli parametreli sorgular Java Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

Java Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Java Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.

“PreparedStatement” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu Java Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Java Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. JDBC Temelleri
  2. PreparedStatement
  3. İşlemler
  4. HikariCP ile Bağlantı Havuzlama
← Java Academy Sayfasına Dön