This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-07-24
Channels
- # announcements (5)
- # beginners (184)
- # calva (32)
- # cider (29)
- # clj-kondo (1)
- # cljdoc (29)
- # cljsrn (6)
- # clojure (44)
- # clojure-dev (36)
- # clojure-europe (9)
- # clojure-italy (18)
- # clojure-losangeles (1)
- # clojure-nl (3)
- # clojure-spec (7)
- # clojure-uk (30)
- # clojure-ukraine (1)
- # clojuredesign-podcast (8)
- # clojurescript (65)
- # code-reviews (21)
- # core-async (25)
- # cursive (51)
- # data-science (3)
- # datascript (2)
- # datomic (25)
- # emacs (14)
- # events (1)
- # figwheel-main (3)
- # fulcro (3)
- # graalvm (5)
- # jackdaw (17)
- # kaocha (14)
- # luminus (5)
- # off-topic (17)
- # pathom (7)
- # pedestal (2)
- # re-frame (71)
- # reagent (25)
- # shadow-cljs (83)
- # spacemacs (31)
- # sql (92)
- # tools-deps (23)
- # vim (102)
- # xtdb (5)
@seancorfield just an FYI: latest next.jdbc with built-in support for HikariCP is great. Much simpler configuration of the db "layer" now. Thank you.
Is there an example of using with hikari? maybe you can share one? Thanks
Sure: https://github.com/manuel-uberti/boodle/blob/master/src/clj/boodle/services/postgresql.clj
thanks!
There's an example in the Getting Started documentation too.
Creating a connection pool for a single SQL operation is a terrible idea @U4TE22XR8!
The expectation is that you create the connection pool when your app starts up and use that (a DataSource) throughout your program.
Creating a connection pool is even heavier work than creating a single connection so you don't want to do it every time.
thank you. It was a quick test done this morning in the office, TBH. I'm working right now on it from home. 🙂
Yeah, you probably want the pool setup in your -main
and then pass the datasource down into your code.
something like this:
(defn connect!
[config]
(let [db-spec (:postgresql config)
^HikariDataSource ds (connection/->pool HikariDataSource db-spec)]
(reset! datasource ds)))
I'm strongly against using globals for that sort of thing -- code is much easier to maintain and test when you pass stuff via parameters. But, however you do it, create the pool once at startup and use that datasource everywhere.
Yes, it's working now with the atom, but I agree with you on globals. So I'll refactor my code to pass down the "state". Thanks again for the tip.
although, with the pool created at startup, I can't use with-open
now, can I? It'll close the datasource, right?
If you create it in -main
and call into your code, passing the datasource, yes, you can 🙂
I originally had let
in the examples with an explicit .close
call at the end of the block -- which is why I changed to with-open
You don't really need to close the datasource / pool at the end of your app tho'...
sorry, but I'm not getting how to pass it down to the rest of the code. This is a web application, with APIs (compojure). The main only starts the HTTP server, which takes care of making the routes available.
Your main handler can be a closure over your "system" and can then inject it into every Ring request under a particular key.
Or use middleware
(defn add-ds [handler ds]
(fn [req]
(handler (assoc req :system/datasource ds))))
Then
(start-server (add-ds my-app datasource))
We have a whole system Component (using Stuart Sierra's library) that we pass into every Ring request.
@seancorfield I did this:
(defn -main
[& args]
(let [port (get-in config [:http :port])
db-spec (:postgresql config)
^HikariDataSource ds (connection/->pool HikariDataSource db-spec)]
(http/start-server! ds port)))
where start-server
does this:
(defn start-server!
[datasource port]
(let [app-routes (compojure/routes (make-routes datasource))]
(reset! server (httpkit/run-server app-routes {:port port}))))
And make-routes
adds the datasource correctly to the request.
However, I am still getting SQLException HikariDataSource HikariDataSource (HikariPool-1) has been closed.
after the first query. I mean, the first one works fine, but every query after that results in that exception.(BTW, the whole code is here: https://github.com/manuel-uberti/boodle/tree/datasource-in-main)
I don't see with-open
anywhere in that repo?
Just found it -- took me a while to trace through all that code
That's your bug.
You are closing the datasource with that statement.
If you pass the datasource to execute!
it will get a connection and close (return) it.
Else you could do
(with-open [con (jdbc/get-connection datasource)]
(jdbc/execute! con q))
You only need to use with-open
when you are creating something closeable.
(with-open [ds datasource] ...
does not create anything.
I wouldn't bother explicitly creating the connection, unless you wanted to reuse it in multiple operations -- as the documentation says.
As soon as you remove that with-open
it should all work 🙂
Cool. Midnight here. I'm off to bed!
I'm trying to migrate an existing db-spec over to use with jdbc-next, and I'm running into a problem that's either something to do with MS SQL Server or something I'm doing wrong - details will be in the thread.
I've always used the form
{:classname "net.sourceforge.jtds.jdbc.Driver"
:subprotocol "jtds:sqlserver"
:subname (str "//" servername "/" dbname)
:user username
:password password}
When I try to use
{:classname "net.sourceforge.jtds.jdbc.Driver"
:dbtype "mssql"
:dbname dbname
:host hostname
:user username
:password password}
I can't get it to work in either clojure.java.jdbc
or next.jdbc
I get an error No suitable driver found for jdbc:
in next.jdbc
and No suitable driver found for jdbc:
Any ideas what I'm doing wrong?
Use :dbtype "jtds"
Omit :classname
See https://cljdoc.org/d/seancorfield/next.jdbc/1.0.2/api/next.jdbc#get-datasource
Ahh, thanks - works perfectly now! The link in the getting started page goes to https://cljdoc.org/d/seancorfield/next.jdbc/1.0.3/api/next.jdbc#get-datasource which isn't working (I was planning on letting you know that, too, in case you weren't aware).
Oh, just saw your message in cljdoc so I guess you saw that too 🙂
Yeah, not sure what's going on there...
I guess, if in doubt, check the docstrings 🙂
There's also next.jdbc.connection/dbtypes
as a var you can inspect in the REPL.
Hopefully I'll remember that next time I have a problem with this - it's probably been a few years since I first got it working in old.jdbc
and I've just been copying the thing that worked from project to project 🙂
Anyone got a mysql or oracle-xe docker setup going to use against next.jdbc? I'd be interested in your journey, after some stop/starts myself.
I regularly use Percona 5.7 (MySQL) via Docker with next.jdbc
@jonpither -- what do you need to know?
I also use Docker to test against PostgreSQL (for clojure.java.jdbc
-- I haven't hooked that up for next.jdbc
stuff yet).
Thanks @seancorfield I kept getting a connection error with mysql, so I ended up cheating and installing it directly into my OS 🙂
Never 🙂
would be nice to test what I'm doing against Oracle, but I when I tried the docker route earlier, it was very difficult
Here's what I do for PostgreSQL:
docker run -p 5432:5432 --name clojure_test -e POSTGRES_PASSWORD=clojure_test -e POSTGRES_USER=clojure_test -d postgres
And then I can connect to 127.0.0.1:5432
I'd expect something very similar to work for MySQL (or any other database).
FYI we use an embedded pgsql: https://github.com/juxt/crux/blob/master/crux-test/test/crux/fixtures/postgres.clj
Here's what's in my docker-compose.yml
for Percona:
mysql:
image: percona:5.7
environment:
- MYSQL_ROOT_PASSWORD
ports:
- "3306:3306"
command:
[--character-set-server=utf8mb4, --collation-server=utf8mb4_unicode_ci]
(with an env var for my root user password for MySQL)Oooh! I didn't know there was an embedded version! That would make my testing much easier!!
Am I right that it's not on Maven Central?
I can't find any artifacts under com.opentable
that seem to be PostgreSQL...
Ah, I had the wrong group ID. Thanks!
@seancorfield Hey Sean - I'm using Apache Derby with clojure.java.jdbc
- I instinctively reached for the latest version 10.15.1.3
and ran into issues. I notice the tests in clojure.java.jdbc
and next.jdbc
for that matter, all run against the prior version 10.14.2.0
which works fine for me. I'm curious though... are there a bunch of breaking changes in the latest derby release?
I think Derby 10.15.* requires a more recent JDK than 8? What was the error -- class version mismatch 53 vs 52?
Execution error (ClassNotFoundException) at jdk.internal.loader.BuiltinClassLoader/loadClass (BuiltinClassLoader.java:583).
org.apache.derby.shared.common.security.SystemPermission
What JDK are you using?
openJDK 11
Ah, OK. So you wouldn't get the version mismatch. If 10.14.*
works, use that. I haven't tested 10.15.*
since I'm based on OpenJDK 8 at the moment
Cool 🙂 yeh no issues using 10.14.x
- was just curious. Thanks!