Created: 2011-07-16 18:57
Updated: 2013-12-22 04:06


clj-table is an ORM for SQL databases. It's still new and isn't quite fully-featured, but it's useful for me.

Currently, it only works with Postgres, because that's what I use. Patches welcome!


Add [clj-table "0.1.0"] to your project file.


Require clj-table.user, then call deftable

(ns clj-table.test.person
  (:require [clj-table.user :as table])

(table/deftable person {:primary-keys [:id]
                        :columns [:id :name]})

You have to manually specify primary keys and columns right now, no table introspection yet. This will define a var named person in the current ns, and bunch of functions, so you can only deftable once per ns. For the complete list of functions defined, do (clojure.contrib.ns-utils/docs <ns where you just deftable'd)

clj-table is built on clojure.contrib.sql for connectivity, so you'll need a c.c.sql connection:


(clojure.contrib.sql/with-connection db
    (person/find-one :where {:id 10}))

Returns a single row, or nil. Find-one asserts that it returns at most one row.


(clojure.contrib.sql/with-connection db
    (person/find-one :where {:gender "m"}))

where clauses

Normally, the where clause queries on strict equality, i.e. :where {:id 10} generates the sql for ["where id = ?" 10]. The where clause can also take a set, to generate an IN clause:

(clojure.contrib.sql/with-connection db
    (person/find-all :where {:id #{1 42 13}}))

performs a query for ..WHERE id IN (1, 42,13)..


(person/find-all :order-by [:id])
(song/find-all :order-by [:id :desc])


(song/find-all :limit 3)


clj-table supports Rails style associations between tables. After defining two tables:

(ns clj-table.test
  (:require [clj-table.test.album :as album])
  (:require [clj-table.test.recording :as recording]))

(table/has-many album/album recording/recording {:id :album_id} :recordings)

has-many takes two vars defined by deftable, a map of source column to dest column, and the name of the association that will appear on the source column. Then you can do

(clj-table.test.album/find-one :where {:name "Kind of Blue"} :load [:recordings])

This will return one album row, with an extra column, recordings. Since :recordings was defined as has-many, it will be a set of recordings rows. If has-one is used instead, the column will point to a single row, or nil.

Current associations are has-one, has-many, belongs-to and has-many-through.

For more examples, see test/clj-table/test.clj


Licensed under the EPL, the same as Clojure

Cookies help us deliver our services. By using our services, you agree to our use of cookies Learn more