emacs.d/clones/lisp/clojure-doc.org/articles/ecosystem/java_jdbc/home.html

310 lines
22 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 - Getting Started</title>
<meta name="description" content="This guide is intended to help you the Clojure Contrib JDBC wrapper: clojure.java.jdbcA modern JDBC wrapper has since been written (by the same author/maintainer) -- read about next.jdbc on cljdoc.org">
<meta property="og:description" content="This guide is intended to help you the Clojure Contrib JDBC wrapper: clojure.java.jdbcA modern JDBC wrapper has since been written (by the same author/maintainer) -- read about next.jdbc on cljdoc.org">
<meta property="og:url" content="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/home/" />
<meta property="og:title" content="java.jdbc - Getting Started" />
<meta property="og:type" content="article" />
<link rel="canonical" href="https://clojure-doc.github.io/articles/ecosystem/java_jdbc/home/">
<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 - Getting Started</h2>
</div>
<p>This guide is intended to help you the Clojure Contrib JDBC wrapper: <code>clojure.java.jdbc</code></p><p><strong>A modern JDBC wrapper has since been written (by the same author/maintainer) -- read about <a href="https://clojure-doc.org/articles/ecosystem/java_jdbc/home/cljdoc.org/d/com.github.seancorfield/next.jdbc/"><code>next.jdbc</code> on cljdoc.org</a></strong></p><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="overview">Overview</h2><p><code>java.jdbc</code> is intended to be a low-level Clojure wrapper around various Java
JDBC drivers and supports a wide range of databases. The <a href="https://github.com/clojure/java.jdbc/"><code>java.jdbc</code> source is
on GitHub</a> and there is a dedicated <a href="https://groups.google.com/forum/#!forum/clojure-java-jdbc">java.jdbc mailing
list</a>. The detailed <a href="http://clojure.github.io/java.jdbc/"><code>java.jdbc</code> reference</a> is
automatically generated from the <code>java.jdbc</code> source.</p><p>Generally, when using <code>java.jdbc</code>, you will set up a data source as a "database
spec" and pass that to the various CRUD (create, read, update, delete)
functions that <code>java.jdbc</code> provides. These operations are detailed within the
<a href="using_sql.html">Using SQL</a> page, but a quick overview is provided by the
walkthrough below.</p><p>By default, each operation opens a connection and executes the SQL inside a
transaction. You can also run multiple operations against the same connection,
either within a transaction or via connection pooling, or just with a shared
connection. You can read more about reusing connections on the <a href="reusing_connections.html">Reusing
Connections</a> page.</p><h2 id="higher-level-dsl-and-migration-libraries">Higher-level DSL and migration libraries</h2><p>If you need more abstraction than the <code>java.jdbc</code> wrapper provides, you may want
to consider using a library that provides a DSL. All of the following libraries
are built on top of <code>java.jdbc</code> and provide such abstraction:</p><ul><li><a href="https://github.com/jkk/honeysql">HoneySQL</a></li><li><a href="https://github.com/r0man/sqlingvo">SQLingvo</a></li><li><a href="http://sqlkorma.com">Korma</a></li><li><a href="https://github.com/walkable-server/walkable">Walkable</a></li></ul><p>In particular, <a href="http://sqlkorma.com">Korma</a> goes beyond a SQL DSL to provide "entities" and
"relationships" (in the style of classical Object-Relational Mappers, but
without the pain).</p><p>Another common need with SQL is for database migration libraries. Some of the
more popular options are:</p><ul><li><a href="https://github.com/macourtney/drift">Drift</a></li><li><a href="https://github.com/pjstadig/migratus">Migratus</a></li><li><a href="https://github.com/weavejester/ragtime">Ragtime</a></li></ul><h2 id="a-brief-javajdbc-walkthrough">A brief <code>java.jdbc</code> walkthrough</h2><h3 id="setting-up-a-data-source">Setting up a data source</h3><p>A "database spec" is a Clojure map that specifies how to access the data
source. Most commonly, you specify the database type, the database name,
and the username and password. For example,</p><pre><code class="clojure">(def db-spec
{:dbtype "mysql"
:dbname "mydb"
:user "myaccount"
:password "secret"})
</code></pre><p>See <a href="home.html#database-support"><strong>Database Support</strong></a> below for a complete list of
databases and drivers supported by <code>java.jdbc</code> out of the box.</p><h3 id="a-hello-world-query">A "Hello World" Query</h3><p>Querying the database can be as simple as:</p><pre><code class="clojure">(ns dbexample
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec ... ) ;; see above
(jdbc/query db-spec ["SELECT 3*5 AS result"])
=&gt; {:result 15}
</code></pre><p>Of course, we will want to do more with our database than have it perform
simple calculations. Once we can successfully connect to it, we will likely
want to create tables and manipulate data.</p><h3 id="creating-tables">Creating tables</h3><p><code>java.jdbc</code> provides <code>create-table-ddl</code> and <code>drop-table-ddl</code> to generate basic
<code>CREATE TABLE</code> and <code>DROP TABLE</code> DDL strings. Anything beyond that can be
constructed manually as a string.</p><pre><code class="clojure">(ns dbexample
(:require [clojure.java.jdbc :as jdbc]))
(def db-spec ... ) ;; see above
(def fruit-table-ddl
(jdbc/create-table-ddl :fruit
[[:name "varchar(32)"]
[:appearance "varchar(32)"]
[:cost :int]
[:grade :real]]))
</code></pre><p>We can use the function <code>db-do-commands</code> to create our table and indexes in a
single transaction:</p><pre><code class="clojure">(jdbc/db-do-commands db-spec
[fruit-table-ddl
"CREATE INDEX name_ix ON fruit ( name );"])
</code></pre><p>For more details on DDL functionality within <code>java.jdbc</code>, see the <a href="using_ddl.html">Using DDL and
Metadata Guide</a>.</p><h3 id="querying-the-database">Querying the database</h3><p>The four basic CRUD operations <code>java.jdbc</code> provides are:</p><pre><code class="clojure">(jdbc/insert! db-spec :table {:col1 42 :col2 "123"}) ;; Create
(jdbc/query db-spec ["SELECT * FROM table WHERE id = ?" 13]) ;; Read
(jdbc/update! db-spec :table {:col1 77 :col2 "456"} ["id = ?" 13]) ;; Update
(jdbc/delete! db-spec :table ["id = ?" 13]) ;; Delete
</code></pre><p>The table name can be specified as a string or a keyword.</p><p><code>insert!</code> takes a single record in hash map form to insert. <code>insert!</code> can also
take a vector of column names (as strings or keywords), followed by a vector of
column values to insert into those respective columns, much like an <code>INSERT</code>
statement in SQL. Entries in the map that have the value <code>nil</code> will cause
<code>NULL</code> values to be inserted into the corresponding columns.</p><p>If you wish to insert multiple rows (in hash map form) at once, you can use
<code>insert-multi!</code>; however, <code>insert-multi!</code> will write a separate insertion
statement for each row, so it is suggested you use the column-based form of
<code>insert-multi!</code> over the row-based form. Passing multiple column values to
<code>insert-multi!</code> will generate a single batched insertion statement and yield
better performance.</p><p><code>query</code> allows us to run selection queries on the database. Since you provide
the query string directly, you have as much flexibility as you like to perform
complex queries.</p><p><code>update!</code> takes a map of columns to update, with their new values, and a SQL
clause used to select which rows to update (prepended by <code>WHERE</code> in the
generated SQL). As with <code>insert!</code>, <code>nil</code> values in the map cause the
corresponding columns to be set to <code>NULL</code>.</p><p><code>delete!</code> takes a SQL clause used to select which rows to delete, similar to
<code>update!</code>.</p><p>By default, the table name and column names are converted to strings
corresponding to the keyword names in the underlying SQL. We can control how we
transform keywords into SQL names using an optional <code>:entities</code> argument which
is described in more detail in the <a href="using_sql.html">Using SQL</a> section.</p><h3 id="dropping-our-tables">Dropping our tables</h3><p>To clean out the database from our example, we can generate a the command to
drop the fruit table:</p><pre><code class="clojure">(def drop-fruit-table-ddl (jdbc/drop-table-ddl :fruit))
</code></pre><p>Ensure you tear down your tables and indexes in the opposite order of creation:</p><pre><code class="clojure">(jdbc/db-do-commands db-spec
["DROP INDEX name_ix;"
drop-fruit-table-ddl])
</code></pre><p>These are all the commands we need to write a simple migration for our database!</p><h2 id="database-support">Database Support</h2><p>Out of the box, <code>java.jdbc</code> understands the following <code>:dbtype</code> values (with
their default class names):</p><ul><li><code>"derby"</code> - <code>org.apache.derby.jdbc.EmbeddedDriver</code></li><li><code>"h2"</code> - <code>org.h2.Driver</code></li><li><code>"h2:mem"</code> - <code>org.h2.Driver</code></li><li><code>"hsqldb"</code> or <code>"hsql"</code> - <code>org.hsqldb.jdbcDriver</code></li><li><code>"jtds:sqlserver"</code> or <code>"jtds"</code> - <code>net.sourceforge.jtds.jdbc.Driver</code></li><li><code>"mysql"</code> - <code>com.mysql.jdbc.Driver</code></li><li><code>"oracle:oci"</code> - <code>oracle.jdbc.OracleDriver</code></li><li><code>"oracle:thin"</code> or <code>"oracle"</code> - <code>oracle.jdbc.OracleDriver</code></li><li><code>"postgresql"</code> or <code>"postgres"</code> - <code>org.postgresql.Driver</code></li><li><code>"pgsql"</code> - <code>com.impossibl.postgres.jdbc.PGDriver</code></li><li><code>"redshift"</code> - <code>com.amazon.redshift.jdbc.Driver</code></li><li><code>"sqlite"</code> - <code>org.sqlite.JDBC</code></li><li><code>"sqlserver"</code> - <code>"mssql"</code> - <code>com.microsoft.sqlserver.jdbc.SQLServerDriver</code></li></ul><p>You must specify the appropriate JDBC driver dependency in your project -- these
drivers are not included with <code>java.jdbc</code>.</p><p>You can overide the default class name by specifying <code>:classname</code> as well as
<code>:dbtype</code>.</p><p>For databases that require a hostname or IP address, <code>java.jdbc</code> assumes
<code>"127.0.0.1"</code> but that can be overidden with the <code>:host</code> option.</p><p>For databases that require a port, <code>java.jdbc</code> has the following defaults,
which can be overridden with the <code>:port</code> option:</p><ul><li>Microsoft SQL Server - 1433</li><li>MySQL - 3306</li><li>Oracle - 1521</li><li>PostgreSQL - 5432</li></ul><p>Some databases require a different format for the "database spec". Here is an example
that was required for an in-memory <a href="http://www.h2database.com">H2 database</a> prior
to <code>java.jdbc</code> release 0.7.6:</p><pre><code class="clojure">(def db-spec
{:classname "org.h2.Driver"
:subprotocol "h2:mem" ; the prefix `jdbc:` is added automatically
:subname "demo;DB_CLOSE_DELAY=-1" ; `;DB_CLOSE_DELAY=-1` very important!!!
; http://www.h2database.com/html/features.html#in_memory_databases
:user "sa" ; default "system admin" user
:password "" ; default password =&gt; empty string
})
</code></pre><p>This is the most general form of database spec, that allows you to control each
piece of the JDBC connection URL that would be created.</p><p>Note: as of <code>java.jdbc</code> 0.7.6, in-memory H2 databases are supported directly
via the simple spec form:</p><pre><code class="clojure">(def db-spec
{:dbtype "h2:mem"
:dbname "mydb"})
</code></pre><p>For file-based databases, such as H2, Derby, SQLite etc, the <code>:dbname</code> will
specify the filename:</p><pre><code class="clojure">(def db-spec
{:dbtype "h2"
:dbname "/path/to/my/database"})
</code></pre><h2 id="more-detailed-javajdbc-documentation">More detailed <code>java.jdbc</code> documentation</h2><ul><li><a href="using_sql.html">Using SQL:</a> a more detailed guide on using SQL with <code>java.jdbc</code></li><li><a href="using_ddl.html">Using DDL:</a> how to create your tables using the <code>java.jdbc</code> DDL</li><li><a href="reusing_connections.html">Reusing Connections:</a> how to reuse your database
connections</li></ul>
<div id="prev-next">
<a href="../../cookbooks/middleware/index.html">&laquo; Middleware in Clojure</a>
||
<a href="using_sql.html">java.jdbc - Manipulating data with SQL &raquo;</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 &copy; 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>