290 lines
17 KiB
HTML
290 lines
17 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||
|
<head>
|
||
|
<meta charset="utf-8"/>
|
||
|
<title>Clojure Guides: java.jdbc - How to reuse database connections</title>
|
||
|
|
||
|
|
||
|
<meta name="description" content="Contents">
|
||
|
|
||
|
<meta property="og:description" content="Contents">
|
||
|
|
||
|
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/reusing_connections/" />
|
||
|
<meta property="og:title" content="java.jdbc - How to reuse database connections" />
|
||
|
<meta property="og:type" content="article" />
|
||
|
|
||
|
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/reusing_connections/">
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
|
<link href="https://fonts.googleapis.com/css?family=Alegreya:400italic,700italic,400,700" rel="stylesheet"
|
||
|
type="text/css">
|
||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
|
||
|
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
|
||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css">
|
||
|
<link href="../../../css/screen.css" rel="stylesheet" type="text/css" />
|
||
|
</head>
|
||
|
<body>
|
||
|
|
||
|
|
||
|
<nav class="navbar navbar-default">
|
||
|
<div class="container">
|
||
|
<div class="navbar-header">
|
||
|
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||
|
<span class="sr-only">Toggle navigation</span>
|
||
|
<span class="icon-bar"></span>
|
||
|
<span class="icon-bar"></span>
|
||
|
<span class="icon-bar"></span>
|
||
|
</button>
|
||
|
<a class="navbar-brand" href="../../../index.html">Clojure Guides</a>
|
||
|
</div>
|
||
|
<div id="navbar" class="navbar-collapse collapse">
|
||
|
<ul class="nav navbar-nav navbar-right">
|
||
|
<li ><a href="../../../index.html">Home</a></li>
|
||
|
<li><a href="https://github.com/clojure-doc/clojure-doc.github.io">Contribute</a></li>
|
||
|
</ul>
|
||
|
</div><!--/.nav-collapse -->
|
||
|
</div><!--/.container-fluid -->
|
||
|
</nav>
|
||
|
|
||
|
|
||
|
<div class="container">
|
||
|
|
||
|
|
||
|
<div class="row">
|
||
|
<div class="col-lg-9">
|
||
|
<div id="content">
|
||
|
|
||
|
<div id="custom-page">
|
||
|
<div id="page-header">
|
||
|
<h2>java.jdbc - How to reuse database connections</h2>
|
||
|
</div>
|
||
|
|
||
|
<h2 id="contents">Contents</h2><ul><li><a href="home.html">Overview</a></li><li><a href="using_sql.html">Using SQL</a></li><li><a href="using_ddl.html">Using DDL</a></li><li><a href="reusing_connections.html">Reusing Connections</a></li></ul><h2 id="reusing-connections">Reusing Connections</h2><p>Since you rarely want every database operation to create a new connection,
|
||
|
there are two ways to reuse connections:</p><ul><li>Grouping Operations using <code>with-db-connection</code>: If you don't want to deal
|
||
|
with a connection pooling library, you can use this macro to automatically open a
|
||
|
connection and maintain it for a body of code, with each operation executed in its
|
||
|
own transaction, then close the connection.</li><li>Grouping Operations using <code>with-db-transaction</code>: If you want to execute multiple
|
||
|
operations in a single transaction, you can use this macro to automatically open a
|
||
|
connection, start a transaction, execute multiple operations, commit the transaction,
|
||
|
and then close the connection.</li><li>Connection Pooling: This is the recommended approach and is fairly
|
||
|
straightforward, with a number of connection pooling libraries available. See
|
||
|
<em>How To Use Connection Pooling</em> below for more information.</li></ul><h2 id="using-with-db-connection">Using <code>with-db-connection</code></h2><p>This macro provides the simplest way to reuse connections, without having to
|
||
|
add a dependency on an external connection pooling library:</p><pre><code class="clojure">(ns dbexample
|
||
|
(:require [clojure.java.jdbc :as jdbc]))
|
||
|
|
||
|
(def db-spec ... ) ;; see above
|
||
|
|
||
|
(jdbc/with-db-connection [db-con db-spec]
|
||
|
(let [;; fetch some rows using this connection
|
||
|
rows (jdbc/query db-con ["SELECT * FROM table WHERE id = ?" 42])]
|
||
|
;; insert a copy of the first row using the same connection
|
||
|
(jdbc/insert! db-con :table (dissoc (first rows) :id))))
|
||
|
</code></pre><p>The <code>query</code> and the <code>insert!</code> are each run in their own transaction and committed
|
||
|
if they succeed. If you want to run multiple operations in a single transaction
|
||
|
see the next section about <code>with-db-transaction</code>.</p><h2 id="using-with-db-transaction">Using <code>with-db-transaction</code></h2><p>This macro provides a way to reuse connections, committing or rolling back
|
||
|
multiple operations in a single transaction:</p><pre><code class="clojure">(ns dbexample
|
||
|
(:require [clojure.java.jdbc :as jdbc]))
|
||
|
|
||
|
(def db-spec ... ) ;; see above
|
||
|
|
||
|
(jdbc/with-db-transaction [t-con db-spec]
|
||
|
(let [;; fetch some rows using this connection
|
||
|
rows (jdbc/query t-con ["SELECT * FROM table WHERE id = ?" 42])]
|
||
|
;; insert a copy of the first row using the same connection
|
||
|
(jdbc/insert! t-con :table (dissoc (first rows) :id))))
|
||
|
</code></pre><p>If any operation inside <code>with-db-transaction</code> fails (throws an exception), then
|
||
|
all of the operations performed so far are rolled back. If all the operations
|
||
|
succeed, then the entire transaction is committed.</p><p>Transactions are not nested (since not all databases support that) so if this is
|
||
|
used another active transaction, the outer transaction (and connection) are used
|
||
|
as-is. If the isolation levels of the outer and inner transaction do not match
|
||
|
you will get an <code>IllegalStateException</code>.</p><p>See also <code>db-set-rollback-only!</code>, <code>db-unset-rollback-only!</code>, and <code>db-is-rollback-only</code>
|
||
|
for additional control over the commit/rollback behavior of the enclosing transaction.</p><h2 id="using-connection-pooling">Using Connection Pooling</h2><p><code>java.jdbc</code> does not provide connection pooling directly but it is relatively
|
||
|
easy to add to your project. There are several connection pooling libraries out
|
||
|
there, but here we will provide instructions for the popular <code>c3p0</code> library.</p><p>The basic idea is to add your chosen connection pooling library to your
|
||
|
project, import the appropriate class(es), define a function that consumes a
|
||
|
"database spec" and produces a map containing a <code>:datasource</code> key whose value
|
||
|
is the constructed pooled <code>DataSource</code> object, then use that hash map in place of your
|
||
|
bare <code>db-spec</code> variable. You are responsible for creating the pooled data
|
||
|
source object and passing the map containing it into any functions that need a
|
||
|
database connection.</p><h3 id="using-the-c3p0-library">Using the c3p0 library</h3><p>For more information on c3p0, consult the <a href="http://www.mchange.com/projects/c3p0/">c3p0
|
||
|
documentation</a>.</p><p>If you're using Leiningen, you can add the following to your dependencies:</p><pre><code class="clojure">[com.mchange/c3p0 "0.9.5.2"] ;; check the documentation for latest version
|
||
|
</code></pre><p>For a Maven-based project, you would add:</p><pre><code class="xml"><dependency>
|
||
|
<groupId>com.mchange</groupId>
|
||
|
<artifactId>c3p0</artifactId>
|
||
|
<version>0.9.5.2</version>
|
||
|
</dependency>
|
||
|
</code></pre><h3 id="create-the-pooled-datasource-from-your-db-spec">Create the pooled datasource from your db-spec</h3><p>Define your <code>db-spec</code> using the long form, for example (for MySQL):</p><pre><code class="clojure">(def db-spec
|
||
|
{:classname "com.mysql.jdbc.Driver"
|
||
|
:subprotocol "mysql"
|
||
|
:subname "//127.0.0.1:3306/mydb"
|
||
|
:user "myaccount"
|
||
|
:password "secret"})
|
||
|
</code></pre><p>We have to use the long form here because c3p0 operates on the class name, subprotocol,
|
||
|
and subname elements. Of course, you don't really need to define a <code>db-spec</code> here
|
||
|
because you're not going to use it with <code>java.jdbc</code> directly, only with c3p0.</p><p>Import the c3p0 class as part of your namespace declaration, for example:</p><pre><code class="clojure">(ns example.db
|
||
|
(:import (com.mchange.v2.c3p0 ComboPooledDataSource)))
|
||
|
</code></pre><p>Define a function that creates a pooled datasource:</p><pre><code class="clojure">(defn pool
|
||
|
[spec]
|
||
|
(let [cpds (doto (ComboPooledDataSource.)
|
||
|
(.setDriverClass (:classname spec))
|
||
|
(.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
|
||
|
(.setUser (:user spec))
|
||
|
(.setPassword (:password spec))
|
||
|
;; expire excess connections after 30 minutes of inactivity:
|
||
|
(.setMaxIdleTimeExcessConnections (* 30 60))
|
||
|
;; expire connections after 3 hours of inactivity:
|
||
|
(.setMaxIdleTime (* 3 60 60)))]
|
||
|
{:datasource cpds}))
|
||
|
</code></pre><p>Now you can create a single connection pool:</p><pre><code class="clojure">(def pooled-db (delay (pool db-spec)))
|
||
|
|
||
|
(defn db-connection [] @pooled-db)
|
||
|
</code></pre><p>And then call <code>(db-connection)</code> wherever you need access to it. If you're using
|
||
|
a <a href="https://github.com/stuartsierra/component">component</a> lifecycle for your
|
||
|
application, you won't need <code>pooled-db</code> or <code>db-connection</code>. You'll just create
|
||
|
<code>(pool db-spec)</code> as part of your application's initialization and pass it
|
||
|
around as part of your system configuration.</p>
|
||
|
|
||
|
<div id="prev-next">
|
||
|
|
||
|
<a href="using_ddl.html">« java.jdbc - Using DDL and Metadata</a>
|
||
|
|
||
|
|
||
|
||
|
||
|
|
||
|
|
||
|
<a href="../core_typed/home/index.html">core.typed - User Documentation Home »</a>
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="col-md-3">
|
||
|
<div id="sidebar">
|
||
|
<h3>Links</h3>
|
||
|
<ul id="links">
|
||
|
|
||
|
<li><a href="../../about/index.html">About</a></li>
|
||
|
|
||
|
<li><a href="../../content/index.html">Table of Contents</a></li>
|
||
|
|
||
|
<li><a href="../../tutorials/getting_started/index.html">Getting Started with Clojure</a></li>
|
||
|
|
||
|
<li><a href="../../tutorials/introduction/index.html">Introduction to Clojure</a></li>
|
||
|
|
||
|
<li><a href="../../tutorials/emacs/index.html">Clojure with Emacs</a></li>
|
||
|
|
||
|
<li><a href="../../tutorials/vim_fireplace/index.html">Clojure with Vim and fireplace.vim</a></li>
|
||
|
|
||
|
<li><a href="../../tutorials/eclipse/index.html">Starting with Eclipse and Counterclockwise For Clojure Development</a></li>
|
||
|
|
||
|
<li><a href="../../tutorials/basic_web_development/index.html">Basic Web Development</a></li>
|
||
|
|
||
|
<li><a href="../../tutorials/parsing_xml_with_zippers/index.html">Parsing XML in Clojure</a></li>
|
||
|
|
||
|
<li><a href="../../tutorials/growing_a_dsl_with_clojure/index.html">Growing a DSL with Clojure</a></li>
|
||
|
|
||
|
<li><a href="../../language/core_overview/index.html">Overview of clojure.core, the standard Clojure library</a></li>
|
||
|
|
||
|
<li><a href="../../language/namespaces/index.html">Clojure Namespaces and Vars</a></li>
|
||
|
|
||
|
<li><a href="../../language/collections_and_sequences/index.html">Collections and Sequences in Clojure</a></li>
|
||
|
|
||
|
<li><a href="../../language/functions/index.html">Functions in Clojure</a></li>
|
||
|
|
||
|
<li><a href="../../language/laziness/index.html">Laziness in Clojure</a></li>
|
||
|
|
||
|
<li><a href="../../language/interop/index.html">Clojure interoperability with Java</a></li>
|
||
|
|
||
|
<li><a href="../../language/macros/index.html">Clojure Macros and Metaprogramming</a></li>
|
||
|
|
||
|
<li><a href="../../language/polymorphism/index.html">Polymorphism in Clojure: Protocols and Multimethods</a></li>
|
||
|
|
||
|
<li><a href="../../language/concurrency_and_parallelism/index.html">Concurrency and Parallelism in Clojure</a></li>
|
||
|
|
||
|
<li><a href="../../language/glossary/index.html">Clojure Terminology Guide</a></li>
|
||
|
|
||
|
<li><a href="../libraries_directory/index.html">A Directory of Clojure Libraries</a></li>
|
||
|
|
||
|
<li><a href="../libraries_authoring/index.html">Library Development and Distribution</a></li>
|
||
|
|
||
|
<li><a href="../generating_documentation/index.html">Generating Documentation</a></li>
|
||
|
|
||
|
<li><a href="../data_processing/index.html">Data Processing (Help Wanted)</a></li>
|
||
|
|
||
|
<li><a href="../web_development/index.html">Web Development (Overview)</a></li>
|
||
|
|
||
|
<li><a href="../maven/index.html">How to use Maven to build Clojure projects</a></li>
|
||
|
|
||
|
<li><a href="../community/index.html">Clojure Community</a></li>
|
||
|
|
||
|
<li><a href="../user_groups/index.html">Clojure User Groups</a></li>
|
||
|
|
||
|
<li><a href="../running_cljug/index.html">Running a Clojure User Group</a></li>
|
||
|
|
||
|
<li><a href="../books/index.html">Books about Clojure and ClojureScript</a></li>
|
||
|
|
||
|
<li><a href="../../cookbooks/data_structures/index.html">Data Structures (Help wanted)</a></li>
|
||
|
|
||
|
<li><a href="../../cookbooks/strings/index.html">Strings</a></li>
|
||
|
|
||
|
<li><a href="../../cookbooks/math/index.html">Mathematics with Clojure</a></li>
|
||
|
|
||
|
<li><a href="../../cookbooks/date_and_time/index.html">Date and Time (Help wanted)</a></li>
|
||
|
|
||
|
<li><a href="../../cookbooks/files_and_directories/index.html">Working with Files and Directories in Clojure</a></li>
|
||
|
|
||
|
<li><a href="../../cookbooks/middleware/index.html">Middleware in Clojure</a></li>
|
||
|
|
||
|
<li><a href="home.html">java.jdbc - Getting Started</a></li>
|
||
|
|
||
|
<li><a href="using_sql.html">java.jdbc - Manipulating data with SQL</a></li>
|
||
|
|
||
|
<li><a href="using_ddl.html">java.jdbc - Using DDL and Metadata</a></li>
|
||
|
|
||
|
<li><a href="reusing_connections.html">java.jdbc - How to reuse database connections</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/home/index.html">core.typed - User Documentation Home</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/user_documentation/index.html">core.typed - User Documentation</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/rationale/index.html">core.typed - Rationale</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/quick_guide.html">core.typed - Quick Guide</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/start/introduction_and_motivation/index.html">core.typed - Getting Started: Introduction and Motivation</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/types/index.html">core.typed - Types</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/start/annotations/index.html">core.typed - Annotations</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/poly_fn/index.html">core.typed - Polymorphic Functions</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/filters/index.html">core.typed - Filters</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/mm_protocol_datatypes/index.html">core.typed - Protocols</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/loops/index.html">core.typed - Looping constructs</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/function_types/index.html">core.typed - Functions</a></li>
|
||
|
|
||
|
<li><a href="../core_typed/limitations/index.html">core.typed - Limitations</a></li>
|
||
|
|
||
|
</ul>
|
||
|
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<footer>Copyright © 2021 Multiple Authors
|
||
|
<p style="text-align: center;">Powered by <a href="http://cryogenweb.org">Cryogen</a></p></footer>
|
||
|
</div>
|
||
|
<script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
|
||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
|
||
|
<script src="../../../js/highlight.pack.js" type="application/javascript"></script>
|
||
|
<script>hljs.initHighlightingOnLoad();</script>
|
||
|
|
||
|
|
||
|
</body>
|
||
|
</html>
|