【问题标题】:Use a database with Clojure将数据库与 Clojure 一起使用
【发布时间】:2025-12-11 19:25:01
【问题描述】:

有哪些方法可以使用 Clojure 中的数据库?

我从 Clojure 了解到,您可以使用 Java 做任何事情,但这意味着我最终可能会使用与 Clojure 简单性相冲突的过于复杂的东西(如 Hibernate)。有什么建议或cmets?

【问题讨论】:

    标签: database clojure


    【解决方案1】:

    clojure-contrib 有一个 sql 库,它是 JDBC (java.sql.DriverManager) 的一个瘦包装器。随附的测试文件有一些使用示例。

    【讨论】:

    【解决方案2】:

    我现在(截至 2011 年底)推荐 Korma - “用于 Clojure 的美味 SQL”

    这是一个漂亮的小 SQL DSL,这是网站上的一个示例:

    (select users
      (aggregate (count :*) :cnt)
      (where (or (> :visits 20)
                 (< :last_login a-year-ago))))
    

    【讨论】:

    【解决方案3】:

    为了任何从 Google 来到这里的人,我想添加一个截至 2011 年 11 月的答案。

    Clojure 1.3 中当前的核心 SQL 访问库是 clojure.java.jdbc。在此基础上构建了一些非常好的库,例如 ClojureQLKorma

    【讨论】:

      【解决方案4】:

      如果您愿意使用 Java 库,但想要一些简单的东西,也许您会喜欢 Persist。只需 10 分钟即可查看它是否符合您的需求。

      【讨论】:

        【解决方案5】:

        SQL 数据库最新最好的似乎是HoneySQLYesql

        HoneySQL 是一个非常优雅的 DSL,用于生成 SQL 查询。有传言说它甚至可以修改语句以进行高度优化,请参阅 2015 年 2 月 24 日的 clojure-group 线程“Current best-of-breed JDBC libraries?”。

        Niels van Klaveren 在上述帖子中说:

        “基本上,它 [HoneySQL] 生成 SQL 脚本来重新链接外键引用以清理数据库中的重复项。它需要一个带有(至少)from 表、group-by 和 @ 987654326@ 子句作为基本定义,什么被认为是双精度的,以及应该保留记录的顺序。结合 JDBC 元数据,查询有效地被重写以生成:

        • 临时替换表
        • 查询以统一唯一索引,以防止在更新外键引用时发生冲突
        • 更新所有外键引用的查询
        • 删除语句以删除所有重复项

        为了创建性能最佳但仍独立于数据库的 SQL,我不得不使用额外的子句来扩展 honeysql,例如 OVERPARTITION BY。我不会说它轻而易举,但似乎效果很好。

        ...

        这将 SQL (有时)GB 的脚本减少到大约 100 行 SQL,有时,运行时间从 19 小时减少到 1.5 分钟。”

        Yesql,另一方面,旨在完全简单。它定义了一些函数来加载参数化的.sql-files。

        它的网页提到了以下“USP”:

        • 没有语法上的意外。您的数据库不遵守 SQL 标准——它们都不遵守——但 Yesql 不在乎。您永远不会花时间寻找“等效的 sexp 语法”。您永远不需要回退到 (raw-sql "some('funky'::SYNTAX)") 函数。
        • 更好的编辑器支持。您的编辑器可能已经拥有很好的 SQL 支持。通过将 SQL 保留为 SQL,您可以使用它。
        • 团队互操作性。您的 DBA 可以读写您在 Clojure 项目中使用的 SQL。
        • 更轻松的性能调整。需要解释那个查询计划吗?当您的查询是普通 SQL 时,这会容易得多。
        • 查询重用。将相同的 SQL 文件放到其他项目中,因为它们只是普通的 SQL。将它们作为子模块共享。

        【讨论】:

          【解决方案6】:

          我在 Clojure 中使用Berkeley DB 构建一个简单的键/值数据库。见here

          【讨论】:

            【解决方案7】:

            ClojureQL 包含关系代数。

            【讨论】:

              【解决方案8】:

              现在有 Datomic 和许多类似的解决方案,例如 DataScript,它们也提供非常有趣的关系(非 sql!)数据库功能。

              【讨论】:

                【解决方案9】:

                如果您需要持久连接和/或与多个数据库的连接,并且不想经常重新建立连接,我建议您使用数据库连接池。类似于 BoneCP 或 Tomcat CP。

                您可以将这些包中的数据源提供给 (clojure.contrib.sql/with-connection ...)。

                【讨论】:

                • 嗨@jartur,你的链接是404。
                【解决方案10】:

                然后是 SQLLite。看看这个简单的例子:https://github.com/ogrim/clojure-sqlite-example

                【讨论】:

                  【解决方案11】:

                  首先,从

                  导入库
                   (ns clojureexercise.test
                      (:require [clojure.java.jdbc :as sql])) ;;sql will alias used further in code to access java jdbc feature.
                  

                  其次,下面的函数可以让你连接MySQL服务器。就像在 Java 中一样,我们声明数据库变量来启动 DB,这与我们必须定义数据库连接的方式相同,在下面的代码中,您可以看到 db 变量是在 dbconnect 函数中定义的。 db 变量将在运行查询中进一步使用。

                  (defn dbconnect []
                    (def db{   
                           :classname "com.mysql.jdbc.Driver" 
                           :subprotocol "mysql"
                           :subname "//127.0.0.1:3306/testdb" ;;testdb is the name of database
                           :user "root"
                           :password "password"}))
                  

                  现在,

                  ;;Inserting Data into Database 
                  ;;Table Name is patientinfo, consist columns {id, firstname, lastname, birthdate, gender}
                   (defn insertdata []
                    (sql/insert! db :patientinfo                    ;;used sql alias and db variable to insert data into table 
                    {:id 1 :firstname "Satyam" :lastname "Ramawat" 
                     :birthdate "1/1/2018" :gender "Male" }))
                  

                  我会详细说明:

                  sql/插入!数据库:患者信息

                  sql 将启用插入查询功能,db 将允许系统了解在哪个数据库连接的哪个表上插入记录。

                  【讨论】:

                    【解决方案12】:

                    你也可以试试 CLJ-Record,https://github.com/duelinmarkers/clj-record

                    【讨论】: