`

Clojure学习——持久化框架clj-record

阅读更多
clj-record是仿Ruby on Rails ActiveRecord的一个持久化框架。项目源码在github上,使用说明写的很坑爹,就不能写个能跑起来的代码么。只是断断续续学了不久clojure,被逼去看源码,试了好几次,总算写出了能跑起来的代码。

添加依赖
[mysql/mysql-connector-java "5.1.21"]
[clj-record "1.1.4"]


样例代码:假设有test库,表名users,字段id,name,email。
(默认规则:model叫user,对应的表名叫users。之前一直搞错导致没初始化成功那些crud方法。)
(ns examples.user
  (:require clj-record.boot))

(def db {:subprotocol "mysql"
         :subname "//127.0.0.1:3306/test"
         :user "root"
         :password "123456"
         :auto-commit true
         :fetch-size  1000})

(clj-record.core/init-model)

;;列举几个常用的CRUD
;;具体其他方法可以查看一下clj-record.core的源码就知道了,都在宏定义中
(create {:name "pi" :email "tiger@hello.com"})

(update {:name "pi" :email "hello@tiger.com"})

(find-records {:name "pi"})
(all-records)

(destroy-record {:id 1})
(destroy-records {:name "pi"})


查看clj-record框架的clj-record.core的源码
(defmacro init-model
  "Macro to create a model out of a clojure namespace.
  The segment of the namespace name following the last dot is used as the model-name.
  Model-specific versions of most public functions in clj-record.core are defined 
  in the model namespace (minus the model-name as first argument).
  Optional forms for associations, validation, etc. are specified here.

  See test/clj_record/test_model/manufacturer.clj for an example."
  [& init-options]
  (let [model-name (last (string/split (name (ns-name *ns*)) #"\."))
        [top-level-options option-groups] (split-out-init-options init-options)
        tbl-name (or (top-level-options :table-name) (dashes-to-underscores (pluralize model-name)))
        optional-defs (defs-from-option-groups model-name option-groups)]
    `(do
      (init-model-metadata ~model-name)
      (set-db-spec ~model-name ~'db)
      (set-table-name ~model-name ~tbl-name)
      (def ~'model-name ~model-name)
      (def ~'table-name (table-name ~model-name))
      (defn ~'model-metadata [& args#]
        (apply model-metadata-for ~model-name args#))
      (defn ~'table-name [] (table-name ~model-name))
      (defn ~'record-count
        ([] (record-count ~model-name))
        ([attributes#] (record-count ~model-name attributes#)))
      (defn ~'get-record [id#]
        (get-record ~model-name id#))
      (defn ~'all-records []
        (all-records ~model-name))
      (defn ~'find-records [attributes#]
        (find-records ~model-name attributes#))
      (defn ~'find-record [attributes#]
        (find-record ~model-name attributes#))
      (defn ~'find-by-sql [select-query-and-values#]
        (find-by-sql ~model-name select-query-and-values#))
      (defn ~'create [attributes#]
        (create ~model-name attributes#))
      (defn ~'insert [attributes#]
        (insert ~model-name attributes#))
      (defn ~'update [attributes#]
        (update ~model-name attributes#))
      (defn ~'destroy-record [record#]
        (destroy-record ~model-name record#))
      (defn ~'destroy-records [attributes#]
        (destroy-records ~model-name attributes#))
      (defn ~'delete-records [attributes#]
        (delete-records ~model-name attributes#))
      (defn ~'validate [record#]
        (~'clj-record.validation/validate ~model-name record#))
      (defn ~'after-destroy [attributes#]
        (after-destroy ~model-name attributes#))
      (defn ~'after-insert [attributes#]
        (after-insert ~model-name attributes#))
      (defn ~'after-load [rows#]
        (after-load ~model-name rows#))
      (defn ~'after-save [attributes#]
        (after-save ~model-name attributes#))
      (defn ~'after-update [attributes#]
        (after-update ~model-name attributes#))
      (defn ~'after-validation [attributes#]
        (after-validation ~model-name attributes#))
      (defn ~'before-destroy [attributes#]
        (before-destroy ~model-name attributes#))
      (defn ~'before-insert [attributes#]
        (before-insert ~model-name attributes#))
      (defn ~'before-save [attributes#]
        (before-save ~model-name attributes#))
      (defn ~'before-update [attributes#]
        (before-update ~model-name attributes#))
      (defn ~'before-validation [attributes#]
        (before-validation ~model-name attributes#))
      ~@optional-defs)))


可以看出的几点:
1、默认的db是采用全局的db变量。
2、model-name默认是文件名。或者说ns的最后一部分
3、table-name可以init的时候作为参数传入。
4、do语句后面顺便帮我们初始化了些crud等方法。一开始没看懂,后来自己学着写了个小例子,总算明白。
user=> (defmacro init [] `(do (defn ~'say [attr#] (prn attr#))))
#'user/init
user=> (init)
#'user/say
user=> (say "hello")
"hello"
nil

这种感觉就像是有一个可以操作数据库的工具类,里面有很多静态方法,全部搬运到我们新建的类中。

(附件为这个例子的lein2工程。我用的IDE是Intellij IDEA。运行之前确定数据库和表存在。汗!!!)
参考资料
https://github.com/duelinmarkers/clj-record
0
1
分享到:
评论
1 楼 zk1878 2014-08-11  
推荐 korma

相关推荐

    Clojure的HTTP客户端包clj-http.zip

    clj-http 是一个新的 Clojure HTTP 客户端开发包,主要特点是设计简单、可靠、可扩展和可测试。 示例代码: (require '[clj-http.client :as client]) (client/get "http://rest-test.heroku.com/") => {:...

    Clojure学习——使用clojure jdbc操作mysql

    标题 "Clojure学习——使用clojure jdbc操作mysql" 指出的是一个关于使用Clojure编程语言通过Java Database Connectivity (JDBC) API来操作MySQL数据库的主题。Clojure是一种基于Lisp的函数式编程语言,它运行在Java...

    clj-http-hystrix:Clojure库,将clj-http请求包装为hystrix命令

    1. **clojure** - 这个标签表明该库是用Clojure语言编写的,Clojure是一种基于Lisp的函数式编程语言,运行在Java虚拟机上。 2. **microservices** - 指的是微服务架构,一种将单一应用程序分解为一组小型、独立的...

    clj-time, 用于Clojure的日期和时间库,包装Joda时间库.zip

    clj-time, 用于Clojure的日期和时间库,包装Joda时间库 clj-time 面向Clojure的日期和时间库,包装的Joda库。 时间网站: 在 Java SE 8开始,用户被要求迁移到 java.time ( jsr-310 ),这是JDK的核心部分,它取代了...

    clj-contrib:Clojure函数库可增强clojure.core

    clj-contrib Clojure库用于增强clojure.core。 入门 使用clj-contrib库。 安装 Clojure CLI / deps.edn clj-contrib/clj-contrib { :git/url " https://github.com/wdhowe/clj-contrib.git " :sha " e4f08c52b...

    clj-launchpad:用于Clojure的Novation Launchpad库

    以下命令在clj-launchpad-demo目录中创建一个新的Clojure项目 > lein new app clj-launchpad-demo Generating a project called clj-launchpad-demo based on the ' app ' template. 在新创建的目录中,有一个...

    clj-antlr, ANTLR 4解析器的Clojure绑定.zip

    clj-antlr, ANTLR 4解析器的Clojure绑定 clj-antlr面向 ANTLR 4 解析器库的Clojure绑定,一个自适应的( * ) 。 看起来很像 Instaparse,只有更快的语法定义,更丰富的语法定义,而且没有令人愉悦的。安装只需将 clj-...

    clj-postgresql, 面向Clojure项目的PostgreSQL帮助程序.zip

    clj-postgresql, 面向Clojure项目的PostgreSQL帮助程序 clj一个用于帮助在Clojure项目中使用更高级的PostgreSQL特性的Clojure库。可用时使用 PGHOST,PGUSER和 PGDATABASE可以将 ~/.pgpass 用于密码实现 clojure....

    clj-fuzzy, 一种处理模糊字符串和语音的算法集合.zip

    clj-fuzzy, 一种处理模糊字符串和语音的算法集合 clj模糊clj模糊是一个本机Clojure库,提供了处理模糊字符串和语音的著名算法的Collection 。它可以在 Clojure 。ClojureScript 。客户端JavaScript和 Node.js. 中...

    clj-ta-lib:Clojure 技术分析库

    clj-ta-lib ========== Clojure 技术分析库。 TA-LIB 的 Clojure 包装器 错误和增强 请针对的打开问题。 用法 从 Maven 运行 这个项目可以通过repl直接从maven使用。 $ mvn package clojure:repl clj-ta-lib....

    clj-pdf-markdown:用于将markdown呈现为clj-pdf数据结构语法的库

    `clj-pdf-markdown` 是一个专门为Clojure设计的库,它实现了将Markdown格式的文本转换成`clj-pdf`数据结构的功能。这个库的目的是方便开发者将Markdown文档转换成高质量的PDF文件,使得Markdown这种轻量级的标记语言...

    clj-osf:clj-osf Clojure API 是一个可供 Clojure 开发人员使用的框架,可帮助他们生成对任何 OSF Web 服务端点的查询

    clj-osf clj-osf是一种简单的 Clojure 域特定语言 (DSL),用于查询开放语义框架 (OSF) Web 服务端点。 每个 OSF Web 服务端点都有自己的 clojure 函数。 可以链接一系列函数来生成 OSF 查询。 该函数用于生成任何...

    clj-check:Clojure CLI工具的lein-check替代方法

    通过与Clojure的测试框架如`clojure.test`或` Midje`的紧密集成,`clj-check`可以快速找出代码中的问题。 2. **代码覆盖率报告**:除了运行测试,`clj-check`还支持生成代码覆盖率报告,帮助开发者了解哪些代码段未...

    clj-wamp, web socket应用消息传递协议( 宋体) 用于Clojure和HTTP工具包.zip

    clj-wamp, web socket应用消息传递协议( 宋体) 用于Clojure和HTTP工具包 clj-wampweb socket应用程序消息传递协议( v1 )的Clojure实现,用于HTTP包服务器。提供常见的web socket消息传递模式和错误处理( RPC,PubSub...

    clj-pgcopy:从Clojure将数据快速导入Postgres

    clj-pgcopy 使用二进制格式的PostgreSQLCOPY实现,将数据快速导入到PostgreSQL。 因为有时jdbc/insert! 和朋友不够快。 该库使用基于类型的分派来确定正确的postgres二进制格式。 有关更多信息,请参见部分。 ...

    clj-http-fake:伪造clj-http请求的助手

    clj-http-fake可以与Clojure的其他测试框架如`clojure.test`或`midje`很好地集成,使测试更加完整和精确。例如,你可以在一个测试套件的`deftest`块中启动和停止模拟服务器。 ### 五、总结 clj-http-fake是Clojure...

    flycheck-clj-kondo:通过flycheck对clj-kondo进行Emacs集成

    标题"flycheck-clj-kondo:通过flycheck对clj-kondo进行Emacs集成"提到了两个关键工具:`flycheck`和`clj-kondo`,以及它们在Emacs环境中的整合。`flycheck`是一个流行的源代码错误检查工具,可以在编写代码时实时...

    clj-rss:用于生成RSS提要的库

    clj-rss 一个用于从Clojure生成RSS feed的库安装莱宁根 注意:clj-rss使用org.clojure/data.xml版本0.2.0-alpha6。用法channel-xml函数接受表示通道的标签的映射,然后接受0(或多个)项(或项的序列)的映射,并...

Global site tag (gtag.js) - Google Analytics