CRUD İşlemlerini Gerçekleştirme
İlişkisel veritabanlarınızdaki verileri Clojure'dan oluşturmayı, okumayı, güncellemeyi ve silmeyi öğrenin.
CRUD İşlemlerini Gerçekleştirme, CoddyKit'te ücretsiz bir Clojure Functional Programming & JVM Backend Development 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, Clojure Functional Programming & JVM Backend Development öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Clojure Functional Programming & JVM Backend Development kursu toplamda 4 dersten oluşur.
Bu dersin bazı bölümleri henüz çevrilmemiş olup İngilizce olarak gösterilmektedir.
What is CRUD?
When you build applications, you'll constantly interact with databases. The fundamental operations for managing data are often summarized by the acronym CRUD.
- Create: Adding new data.
- Read: Retrieving existing data.
- Update: Modifying existing data.
- Delete: Removing data.
In this lesson, we'll master how to perform these essential operations using Clojure's next.jdbc library.
Database Connection Setup
Before we perform CRUD operations, we need a database connection. We'll use next.jdbc with an in-memory SQLite database for our examples.
Remember from the previous lesson, we define a database specification (db-spec) and obtain a data source (ds) or a direct connection.
We'll create a simple users table for our examples.
Create: Inserting New Records
To add new data, we use the next.jdbc.sql/insert! function. It takes a connection, table name, and a map of column-value pairs.
Try running this example to create a users table and insert your first user:
(ns coddykit.core
(:require [next.jdbc :as jdbc]
[next.jdbc.sql :as sql]))
(defn -main
"Insert a new user into the database."
[& args]
(let [db-spec {:dbtype "sqlite" :dbname ":memory:"}]
(with-open [conn (jdbc/get-connection db-spec)]
(jdbc/execute! conn ["DROP TABLE IF EXISTS users;"])
(jdbc/execute! conn ["CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"])
(println "Inserting new user...")
(let [new-user {:name "Alice" :email "alice@example.com"}
result (sql/insert! conn :users new-user)]
(println "Insert result:" result))
(println "\nUsers in database:")
(doseq [user (sql/select! conn ["SELECT * FROM users"])]
(println user)))))Create: Inserting Multiple Records
What if you need to add many records at once? The next.jdbc.sql/insert-multi! function is perfect for this. It takes a sequence of maps, each representing a row to insert.
It's more efficient than calling insert! repeatedly in a loop.
(ns coddykit.core
(:require [next.jdbc :as jdbc]
[next.jdbc.sql :as sql]))
(defn -main
"Insert multiple users into the database."
[& args]
(let [db-spec {:dbtype "sqlite" :dbname ":memory:"}]
(with-open [conn (jdbc/get-connection db-spec)]
(jdbc/execute! conn ["DROP TABLE IF EXISTS users;"])
(jdbc/execute! conn ["CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"])
(println "Inserting multiple users...")
(let [new-users [{:name "Bob" :email "bob@example.com"}
{:name "Charlie" :email "charlie@example.com"}]
result (sql/insert-multi! conn :users new-users)]
(println "Insert result:" result))
(println "\nUsers in database:")
(doseq [user (sql/select! conn ["SELECT * FROM users"])]
(println user)))))Read: Fetching All Data
To retrieve all records from a table, use next.jdbc.sql/select-all!. It takes a connection and the table name (as a keyword or string).
The function returns a sequence of maps, where each map represents a row.
(ns coddykit.core
(:require [next.jdbc :as jdbc]
[next.jdbc.sql :as sql]))
(defn -main
"Select all users from the database."
[& args]
(let [db-spec {:dbtype "sqlite" :dbname ":memory:"}]
(with-open [conn (jdbc/get-connection db-spec)]
(jdbc/execute! conn ["DROP TABLE IF EXISTS users;"])
(jdbc/execute! conn ["CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"])
(sql/insert! conn :users {:name "Alice" :email "alice@example.com"})
(sql/insert! conn :users {:name "Bob" :email "bob@example.com"})
(println "Fetching all users...")
(let [all-users (sql/select-all! conn :users)]
(doseq [user all-users]
(println user))))))Read: Filtering Data with `WHERE`
Often, you only want specific records. Use next.jdbc.sql/select! with a WHERE clause to filter results. The WHERE clause is provided as a map.
For example, to find users with a specific name or email:
(ns coddykit.core
(:require [next.jdbc :as jdbc]
[next.jdbc.sql :as sql]))
(defn -main
"Select users with a specific name."
[& args]
(let [db-spec {:dbtype "sqlite" :dbname ":memory:"}]
(with-open [conn (jdbc/get-connection db-spec)]
(jdbc/execute! conn ["DROP TABLE IF EXISTS users;"])
(jdbc/execute! conn ["CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"])
(sql/insert! conn :users {:name "Alice" :email "alice@example.com"})
(sql/insert! conn :users {:name "Bob" :email "bob@example.com"})
(sql/insert! conn :users {:name "Alice" :email "alice2@example.com"})
(println "Fetching users named Alice...")
(let [alices (sql/select! conn :users {:name "Alice"})]
(doseq [user alices]
(println user))))))Update: Modifying Existing Data
To change existing records, use next.jdbc.sql/update!. It takes a connection, table name, a map of columns to update, and a WHERE clause map to specify which records to modify.
Always be careful with your WHERE clause when updating!
(ns coddykit.core
(:require [next.jdbc :as jdbc]
[next.jdbc.sql :as sql]))
(defn -main
"Update a user's email address."
[& args]
(let [db-spec {:dbtype "sqlite" :dbname ":memory:"}]
(with-open [conn (jdbc/get-connection db-spec)]
(jdbc/execute! conn ["DROP TABLE IF EXISTS users;"])
(jdbc/execute! conn ["CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"])
(sql/insert! conn :users {:name "Alice" :email "alice@example.com"})
(println "Original user:")
(println (first (sql/select! conn :users {:name "Alice"})))
(println "\nUpdating Alice's email...")
(let [result (sql/update! conn :users {:email "alice.new@example.com"} {:name "Alice"})]
(println "Update result:" result))
(println "\nUpdated user:")
(println (first (sql/select! conn :users {:name "Alice"})))))Delete: Removing Data
To remove records from a table, use next.jdbc.sql/delete!. Similar to update!, it requires a connection, table name, and a WHERE clause map to specify which records to remove.
A missing or empty WHERE clause can delete ALL records, so use with extreme caution!
(ns coddykit.core
(:require [next.jdbc :as jdbc]
[next.jdbc.sql :as sql]))
(defn -main
"Delete a user from the database."
[& args]
(let [db-spec {:dbtype "sqlite" :dbname ":memory:"}]
(with-open [conn (jdbc/get-connection db-spec)]
(jdbc/execute! conn ["DROP TABLE IF EXISTS users;"])
(jdbc/execute! conn ["CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)"])
(sql/insert! conn :users {:name "Alice" :email "alice@example.com"})
(sql/insert! conn :users {:name "Bob" :email "bob@example.com"})
(println "Users before delete:")
(doseq [user (sql/select-all! conn :users)] (println user))
(println "\nDeleting Bob...")
(let [result (sql/delete! conn :users {:name "Bob"})]
(println "Delete result:" result))
(println "\nUsers after delete:")
(doseq [user (sql/select-all! conn :users)] (println user)))))Atomic Operations with Transactions
Sometimes you need multiple CRUD operations to succeed or fail as a single, atomic unit. This is where transactions come in.
If any operation within a transaction fails, all changes are rolled back, ensuring data consistency. Use next.jdbc/with-transaction for this.
(ns coddykit.core
(:require [next.jdbc :as jdbc]
[next.jdbc.sql :as sql]))
(defn -main
"Demonstrate a database transaction."
[& args]
(let [db-spec {:dbtype "sqlite" :dbname ":memory:"}]
(with-open [conn (jdbc/get-connection db-spec)]
(jdbc/execute! conn ["DROP TABLE IF EXISTS accounts;"])
(jdbc/execute! conn ["CREATE TABLE accounts (id INTEGER PRIMARY KEY, name TEXT, balance INTEGER)"])
(sql/insert! conn :accounts {:name "Alice" :balance 100})
(sql/insert! conn :accounts {:name "Bob" :balance 50})
(println "Balances before transaction:")
(doseq [acc (sql/select-all! conn :accounts)] (println acc))
(println "\nAttempting to transfer $20 from Alice to Bob...")
(try
(jdbc/with-transaction [tx conn]
(sql/update! tx :accounts {:balance [- :balance 20]} {:name "Alice"})
(sql/update! tx :accounts {:balance [+ :balance 20]} {:name "Bob"})
(println "Transfer successful!"))
(catch Exception e
(println "Transfer failed:" (.getMessage e))))
(println "\nBalances after transaction:")
(doseq [acc (sql/select-all! conn :accounts)] (println acc)))))CRUD Quick Check
You've learned the core functions for interacting with databases. Let's test your understanding!
Recap: Mastering CRUD
Congratulations! You've mastered the essential CRUD operations for database interaction in Clojure using next.jdbc:
- Create:
insert!andinsert-multi!to add data. - Read:
select!andselect-all!to retrieve data. - Update:
update!to modify existing data. - Delete:
delete!to remove data.
You also learned about using transactions with with-transaction for atomic operations, ensuring data integrity. These are the building blocks for almost any data-driven application!
Sıkça Sorulan Sorular
“CRUD İşlemlerini Gerçekleştirme” dersi ücretsiz mi?
Evet — “CRUD İşlemlerini Gerçekleştirme” 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 Clojure Functional Programming & JVM Backend Development kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Clojure Functional Programming & JVM Backend Development kursu toplamda 4 dersten oluşur.
“CRUD İşlemlerini Gerçekleştirme” dersinde ne öğreneceğim?
İlişkisel veritabanlarınızdaki verileri Clojure'dan oluşturmayı, okumayı, güncellemeyi ve silmeyi öğrenin. Clojure Functional Programming & JVM Backend Development 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.
Clojure Functional Programming & JVM Backend Development öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Clojure Functional Programming & JVM Backend Development, 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.
“CRUD İşlemlerini Gerçekleştirme” 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 Clojure Functional Programming & JVM Backend Development dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Clojure Functional Programming & JVM Backend Development 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
- next.jdbc ile Veritabanlarına Bağlanma
- CRUD İşlemlerini Gerçekleştirme
- Veritabanı Geçişleri ve Şema Yönetimi
- Bağlantı Havuzlama ve İşlemler