Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys · Oppitunti

CRUD-operaatioiden suorittaminen

Hallitsette tietojen luomisen, lukemisen, päivittämisen ja poistamisen relaatio­tietokannoista Clojurella.

Oppitunti 2/411 vaihetta

CRUD-operaatioiden suorittaminen on ilmainen Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys-kurssilla on yhteensä 4 oppituntia.

Mitä CRUD tarkoittaa?

Sovelluksia rakentaessanne olette jatkuvasti vuorovaikutuksessa tietokantojen kanssa. Tietojen hallinnan perusoperaatiot tiivistetään usein lyhenteeseen CRUD.

  • Create: uusien tietojen lisääminen.
  • Read: olemassa olevien tietojen hakeminen.
  • Update: olemassa olevien tietojen muokkaaminen.
  • Delete: tietojen poistaminen.

Tässä oppitunnissa opitte suorittamaan nämä keskeiset operaatiot Clojuren next.jdbc-kirjaston avulla.

Tietokantayhteyden määritys

Ennen CRUD-operaatioiden suorittamista tarvitsemme tietokantayhteyden. Käytämme esimerkeissä next.jdbc-kirjastoa ja muistissa toimivaa SQLite-tietokantaa.

Muistattehan edellisestä oppitunnista, että määrittelemme tietokannan määrityksen (db-spec) ja haemme tietolähteen (ds) tai suoran yhteyden.

Luomme esimerkkejä varten yksinkertaisen users-taulun.

Create: uusien tietueiden lisääminen

Uusien tietojen lisäämiseen käytämme next.jdbc.sql/insert!-funktiota. Se saa parametrikseen yhteyden, taulun nimen ja sarake–arvo-parien kartan.

Suorittakaa tämä esimerkki luodaksenne users-taulun ja lisätäksenne ensimmäisen käyttäjänne:

(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: useiden tietueiden lisääminen

Entä jos useita tietueita on lisättävä kerralla? next.jdbc.sql/insert-multi!-funktio sopii tähän erinomaisesti. Se saa parametrikseen karttojen sarjan, jossa kukin kartta edustaa lisättävää riviä.

Se on tehokkaampi kuin insert!-funktion kutsuminen toistuvasti silmukassa.

(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: kaikkien tietojen hakeminen

Voitte hakea kaikki taulun tietueet käyttämällä next.jdbc.sql/select-all!-funktiota. Se saa parametrikseen yhteyden ja taulun nimen (avainsanana tai merkkijonona).

Funktio palauttaa karttojen sarjan, jossa kukin kartta edustaa yhtä riviä.

(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: tietojen suodattaminen `WHERE`-ehdolla

Usein haluatte vain tietyt tietueet. Käyttäkää tulosten suodattamiseen next.jdbc.sql/select!-funktiota yhdessä WHERE-ehdon kanssa. WHERE-ehto annetaan karttana.

Voitte esimerkiksi etsiä käyttäjiä tietyn nimen tai sähköpostiosoitteen perusteella:

(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: olemassa olevien tietojen muokkaaminen

Olemassa olevien tietueiden muuttamiseen käytetään next.jdbc.sql/update!-funktiota. Se saa parametrikseen yhteyden, taulun nimen, päivitettävien sarakkeiden kartan ja WHERE-ehtokartan, joka määrittää muokattavat tietueet.

Olkaa aina tarkkoja WHERE-ehdon kanssa päivityksiä tehdessänne!

(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: tietojen poistaminen

Taulun tietueiden poistamiseen käytetään next.jdbc.sql/delete!-funktiota. Kuten update!, se tarvitsee yhteyden, taulun nimen ja poistettavat tietueet määrittävän WHERE-ehtokartan.

Puuttuva tai tyhjä WHERE-ehto voi poistaa KAIKKI tietueet, joten toimikaa erittäin varovasti!

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

Atomiset operaatiot transaktioilla

Joskus useiden CRUD-operaatioiden on onnistuttava tai epäonnistuttava yhtenä atomisena kokonaisuutena. Tällöin tarvitaan transaktioita.

Jos jokin transaktion sisäinen operaatio epäonnistuu, kaikki muutokset perutaan, mikä varmistaa tietojen eheyden. Käyttäkää tähän next.jdbc/with-transaction-toimintoa.

(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-pikatarkistus

Olette oppineet tietokantojen käsittelyn keskeiset funktiot. Testataanpa ymmärrystänne!

Kertaus: CRUD-operaatioiden hallinta

Onneksi olkoon! Hallitsette nyt tietokantojen käsittelyn keskeiset CRUD-operaatiot Clojuren next.jdbc-kirjastolla:

  • Create: insert! ja insert-multi! tietojen lisäämiseen.
  • Read: select! ja select-all! tietojen hakemiseen.
  • Update: update! olemassa olevien tietojen muokkaamiseen.
  • Delete: delete! tietojen poistamiseen.

Opitte myös käyttämään transaktioita yhdessä with-transaction-toiminnon kanssa atomisiin operaatioihin, mikä varmistaa tietojen eheyden. Nämä ovat lähes kaikkien tietopohjaisten sovellusten rakennuspalikoita!

Aloita maksutta

Opi Clojure tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
12
Oppitunnit
48

Usein kysytyt kysymykset

Onko oppitunti ”CRUD-operaatioiden suorittaminen” ilmainen?

Kyllä – oppitunnin ”CRUD-operaatioiden suorittaminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys-kurssin, päivitä CoddyKit PROhon. Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”CRUD-operaatioiden suorittaminen”?

Hallitsette tietojen luomisen, lukemisen, päivittämisen ja poistamisen relaatio­tietokannoista Clojurella. Harjoittelet Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”CRUD-operaatioiden suorittaminen”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys-oppitunnilla?

Kyllä. Jokainen Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Tietokantayhteydet next.jdbc:llä
  2. CRUD-operaatioiden suorittaminen
  3. Tietokantamigraatiot ja skeeman hallinta
  4. Yhteyspoolit ja transaktiot
← Takaisin: Clojure-funktionaalinen ohjelmointi ja JVM-backend-kehitys