0Pricing
Clojure Functional Programming & JVM Backend Development · Lektion

CRUD-Operationen durchführen

Beherrschen Sie das Erstellen, Lesen, Aktualisieren und Löschen von Daten in relationalen Datenbanken aus Clojure

CRUD-Operationen durchführen ist eine kostenlose Clojure Functional Programming & JVM Backend Development-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Clojure Functional Programming & JVM Backend Development-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Clojure Functional Programming & JVM Backend Development-Kurs umfasst insgesamt 4 Lektionen.

Teile dieser Lektion wurden noch nicht übersetzt und werden auf Englisch angezeigt.

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! and insert-multi! to add data.
  • Read: select! and select-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!

Häufig gestellte Fragen

Ist die Lektion „CRUD-Operationen durchführen“ kostenlos?

Ja — der vollständige Text von „CRUD-Operationen durchführen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Clojure Functional Programming & JVM Backend Development-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Clojure Functional Programming & JVM Backend Development-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „CRUD-Operationen durchführen“?

Beherrschen Sie das Erstellen, Lesen, Aktualisieren und Löschen von Daten in relationalen Datenbanken aus Clojure Du übst Clojure Functional Programming & JVM Backend Development mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Clojure Functional Programming & JVM Backend Development zu starten?

Keine Vorkenntnisse erforderlich. Clojure Functional Programming & JVM Backend Development auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „CRUD-Operationen durchführen“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Clojure Functional Programming & JVM Backend Development-Lektion Code schreiben und ausführen?

Ja. Jede Clojure Functional Programming & JVM Backend Development-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Mit next.jdbc eine Verbindung zu Datenbanken herstellen
  2. CRUD-Operationen durchführen
  3. Datenbankmigrationen und Schemaverwaltung
  4. Connection Pooling und Transaktionen
← Zurück zu Clojure Functional Programming & JVM Backend Development