

Show HN: OJ – A Clojure library for talking to your database - taylorlapeyre
https://github.com/taylorlapeyre/oj

======
krick
I don't get few things.

1\. Queries are executed by passing your query and db-config to oj/exec. So,
does it mean that with any new query there will be new connection to db? How
do you manage transaction, when doing inserts/updates? I suppose there must be
some magic I don't understand, because if that stuff actually is unsupported
that would make all thing pretty much unusable, wouldn't it? Well, if you are
not using MySQL/MyISAM anyway.

2\. I suppose that library does some internal sanitizing, because it is what
such libraries usually are for after all. There isn't much sense in using
keywords instead of strings if it is the same plain SQL you would write
manually (well, you wouldn't make a typo in the word WHERE, but that's all).
But I don't see any mentions of types whatsoever. So if I pass some variable
foo to that query, how does it know how to validate and sanitize it? If it is
allowed to be NULL? If it should be passed to query as INT or string or maybe
DATETIME? As it is minimalistic I would assume it doesn't use schema (and how
would it if it's not an ORM, but just some query composer?), so how does it
work then?

There are few other things I frowned on, but these are the major points.

~~~
taylorlapeyre
I'll try to address your concerns, but keep in mind: this is a very new
project.

1\. When you "exec" a query, all I'm really doing is compiling the query map
into an SQL statement and passing it into java.jdbc[1] with the database
configuration that is given. This database config can be stored as a regular
Clojure map in a config namespace in your project or however you wish. To
answer your question, yes, at the moment java.jdbc is called for each query
that is executed and I can only assume that that means that a new connection
is made. Obviously there is room for improvement here, which will be addressed
in the future.

2\. I've provided a thorough specification for what makes a Clojure map a
"query map" in the SPEC file[2]. Before any query map is compiled into SQL, it
gets validated by a function that ensures that it meets the specification. If
not, it throws an error.

Hopefully this answers some of your concerns! Like I said, this is a new
project that I made for fun and for personal use. I plan on working on it for
a long time, and I'm sure that many things will be improved! I hope that
others find it useful (or at least interesting) as well.

[1]:
[https://github.com/clojure/java.jdbc/](https://github.com/clojure/java.jdbc/)

[2]:
[https://github.com/taylorlapeyre/oj/blob/master/doc/SPEC](https://github.com/taylorlapeyre/oj/blob/master/doc/SPEC)

~~~
mschaef
Regarding point 1, java.jdbc can accept a variety of types of connection maps.
The simplest scenario is you pass in a map that contains the connection
information, and you get a new connection and transaction for each call.
However, you can also pass in live connections/transactions that can be
reused. The with-db-transaction form is one way to accomplish this. It's
really pretty flexible.

(And btw, your library looks really quite good! I'm glad people are trying to
address the issue of generating SQL within Clojure.)

------
johnbellone
While we're on the Clojure topic, what's the preferred quick-start guide to
learn the language and tool-chain?

~~~
taylorlapeyre
I like Clojure for the Brave and True [1], although it can be a little goofy
at times.

Leiningen [2] is the standard build tool, and Clojars is the standard package
repository [3].

For web development, Ring [4] is the standard HTTP solution, while Compojure
[5] is generally used for routing.

[http://www.clojure-toolbox.com](http://www.clojure-toolbox.com) is good for
everything else.

[1]: [http://www.braveclojure.com](http://www.braveclojure.com)

[2]: [http://leiningen.org](http://leiningen.org)

[3]: [https://clojars.org](https://clojars.org)

[4]: [https://github.com/ring-clojure/ring](https://github.com/ring-
clojure/ring)

[5]:
[https://github.com/weavejester/compojure](https://github.com/weavejester/compojure)

~~~
ohpauleez
It's also worth mentioning Pedestal[1] - in place of Ring and Compojure.
Pedestal is set of libraries for building web services that is fast and secure
by default. It fully embraces async capabilities (unlike Ring which is
inherently synchronous), and maintains most Ring compatibility. It sits upon
battled-tested technologies (Jetty, Tomcat, JBoss, Undertow, etc).

[1]
[https://github.com/pedestal/pedestal](https://github.com/pedestal/pedestal)

------
bkirkbri
Looks really promising. We're using HoneySQL now, but OJ might be even
lighter.

~~~
kyllo
If you're looking for a _really_ light SQL library for Clojure, I recommend
yesql:
[https://github.com/krisajenkins/yesql](https://github.com/krisajenkins/yesql)

~~~
handojin
+1 - This is by far the sanest approach to rdbms interaction I've seen. It's
kind of sad that we're stuck with SQL but while we're stuck with it we should
stick to it. :P

~~~
lgas
I agree and it's what I've used for all of my pet clojure projects that need
to talk to a database. However, the drawback it suffers versus a lot of the
approaches taking by most of the alternative libraries is that it doesn't
provide any way to compose queries.

I'm talking about the kind of stuff something like Korma or SQLAlchemy enable
where you build up a query to be executed dynamically based on, for example,
user filters.

I haven't need anything like that on any of my pet projects so I've been
deliriously happy with Yesql. But, while working on those pet projects I do
often find myself thinking about whatever I'm doing in my day job and I
haven't come up with a good way to support composability within the context of
Yesql. I would love to see a solution to that.

------
Rodeoclash
It would be good to have a section which compared this to other Clojure
database libs. I've only used Korma but I would like to know what you're doing
differently to them.

~~~
taylorlapeyre
I explain the difference between OJ and Korma here:

[https://github.com/taylorlapeyre/oj/issues/4](https://github.com/taylorlapeyre/oj/issues/4)

