0Pricing
Java Academy · Pelajaran

PreparedStatement

Kueri berparameter yang aman.

PreparedStatement adalah pelajaran Java Academy gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Java Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Java Academy mencakup 4 pelajaran total.

Mengapa PreparedStatement?

Membangun SQL dengan menggabungkan masukan pengguna berbahaya dan lambat.

PreparedStatement mengatasi kedua masalah tersebut:

  • Keamanan — nilai dikirim secara terpisah dari SQL sehingga mencegah injeksi SQL.
  • Kinerja — basis data dapat mengurai dan merencanakan kueri sekali, lalu menggunakannya kembali.

Masalah Injeksi SQL

Bayangkan Anda membangun kueri dengan penggabungan string. Jika pengguna mengetik '; DROP TABLE users; -- sebagai namanya, SQL hasil penggabungan akan mengeksekusinya sebagai perintah.

Inilah injeksi SQL, salah satu kerentanan web yang paling lama dan paling merusak. PreparedStatement mencegahnya sejak awal berdasarkan rancangan.

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);
    }
}

Penanda Tempat

Dalam PreparedStatement, tuliskan ? untuk setiap nilai yang akan Anda berikan nanti.

Kemudian ikat nilai dengan penyetel bertipe:

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

Indeks parameter dimulai dari 1, sesuai dengan urutan tanda ?.

Kueri yang Aman

Buat pernyataan dengan prepareStatement, ikat parameter, lalu panggil executeQuery.

Nilai tersebut tidak pernah menyentuh teks SQL, sehingga injeksi tidak dapat terjadi apa pun yang diketik pengguna.

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());
        }
    }
}

Mengikat Beberapa Parameter

Setiap ? memiliki pemanggilan penyetel sendiri. Urutan penting: parameter 1 adalah ? pertama, parameter 2 adalah ? kedua, dan seterusnya.

Gunakan penyetel yang sesuai dengan tipe kolom — setInt, setString, setDouble, setBoolean, dan seterusnya.

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());
        }
    }
}

Menangani NULL

Untuk mengikat NULL SQL, gunakan setNull(index, type) dengan konstanta java.sql.Types.

Jangan meneruskan null Java ke setString dan berharap cara itu berhasil — nyatakan secara eksplisit:

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

Mengambil Kunci yang Dihasilkan

Setelah INSERT, Anda sering memerlukan ID yang dibuat otomatis.

Teruskan Statement.RETURN_GENERATED_KEYS saat menyiapkan pernyataan, lalu baca ps.getGeneratedKeys().

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());
        }
    }
}

Penyisipan Secara Berkelompok

Menyisipkan ribuan baris satu pernyataan setiap kali berlangsung lambat. Gunakan pemrosesan berkelompok:

  • Ikat parameter, lalu panggil ps.addBatch().
  • Ulangi untuk setiap baris.
  • Panggil ps.executeBatch() satu kali.

Cara ini mengirimkan baris secara bersamaan sehingga sangat mengurangi komunikasi bolak-balik.

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());
        }
    }
}

Menggunakan Kembali Statement

Satu PreparedStatement dapat dijalankan berkali-kali dengan parameter yang berbeda.

Ikat kembali penanda tempat, lalu panggil execute lagi. Basis data menggunakan kembali rencana eksekusi yang tersimpan dalam cache, sehingga pernyataan yang telah disiapkan lebih cepat untuk kueri berulang.

Jangan Pernah Menggabungkan

Aturan emasnya: nilai apa pun yang dapat berubah harus menjadi parameter ?.

Hanya pengenal tetap yang dikendalikan kode (seperti nama kolom yang telah masuk daftar izin) yang boleh digabungkan — dan itu pun harus divalidasi terhadap daftar yang diizinkan. Data dari pengguna selalu diikat, bukan digabungkan.

Penutupan dan Cakupan Penggunaan Kembali

PreparedStatement terikat pada Connection dan harus ditutup setelah selesai digunakan.

Di dalam blok percobaan dengan sumber daya, deklarasikan pernyataan agar pernyataan tersebut ditutup sebelum koneksi. Jika Anda menggunakan kembali pernyataan berkali-kali dalam perulangan, siapkan pernyataan itu sekali di luar perulangan dan cukup ikat kembali parameter di dalamnya — menyiapkannya ulang pada setiap iterasi akan membuang rencana yang tersimpan dalam cache.

Pemeriksaan Singkat

Mengapa PreparedStatement mencegah injeksi SQL?

Ringkasan

Anda telah belajar menulis kueri yang aman dan cepat:

  • Gunakan penanda tempat ? dan penyetel bertipe (indeks dimulai dari 1).
  • Ikat nilai dengan setString, setInt, setNull, dan sebagainya.
  • Ambil kunci otomatis dengan RETURN_GENERATED_KEYS dan getGeneratedKeys.
  • Kelompokkan banyak operasi penulisan dengan addBatch + executeBatch.
  • Jangan pernah menggabungkan input pengguna ke dalam SQL.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “PreparedStatement” gratis?

Ya — teks lengkap “PreparedStatement” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Java Academy, upgrade ke CoddyKit PRO. Kursus Java Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “PreparedStatement”?

Kueri berparameter yang aman. Kamu berlatih Java Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Java Academy?

Tidak diperlukan pengalaman sebelumnya. Java Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “PreparedStatement” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Java Academy ini?

Ya. Setiap pelajaran Java Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Dasar-Dasar JDBC
  2. PreparedStatement
  3. Transaksi
  4. Pengumpulan Koneksi dengan HikariCP
← Kembali ke Java Academy