Clarify SettableParameter and ReadableColumn usage

This commit is contained in:
Sean Corfield 2019-07-22 15:47:22 -07:00
parent 1b8e4b8c9c
commit c246c5db6f
2 changed files with 20 additions and 4 deletions

View file

@ -23,14 +23,17 @@ You can provide the parameters in the `prepare` call or you can provide them via
## Prepared Statement Parameters
If parameters are provided in the vector along with the SQL statement, in the call to `prepare`, then `set-parameter` is called for each of them. This is part of the `SettableParameter` protocol:
If parameters are provided in the vector along with the SQL statement, in the call to `prepare`, then `set-parameter` is behind the scenes called for each of them. This is part of the `SettableParameter` protocol:
* `(set-parameter v ps i)` -- by default this calls `(.setObject ps i v)` (for `nil` and `Object`)
This can be extended to any Clojure data type, to provide a customized way to add specific types of values as parameters to any `PreparedStatement`. For example, to have all `java.time.LocalDate` and `java.time.LocalDateTime` objects converted to `java.sql.Timestamp` automatically:
This can be extended to any Clojure data type, to provide a customized way to add specific types of values as parameters to any `PreparedStatement`. For example, to have all `java.time.Instant`, `java.time.LocalDate` and `java.time.LocalDateTime` objects converted to `java.sql.Timestamp` automatically:
```clojure
(extend-protocol p/SettableParameter
java.time.Instant
(set-parameter [^java.time.Instant v ^PreparedStatement s ^long i]
(.setTimestamp ps i (java.sql.Timestamp/from v)))
java.time.LocalDate
(set-parameter [^java.time.LocalDate v ^PreparedStatement s ^long i]
(.setTimestamp ps i (java.sql.Timestamp/valueOf (.atStartOfDay v))))
@ -55,6 +58,8 @@ If you need more specialized parameter handling than the protocol can provide, t
By default, `next.jdbc` assumes that you are providing a single set of parameter values and then executing the prepared statement. If you want to run a single prepared statement with multiple groups of parameters, you might want to take advantage of the increased performance that may come from using JDBC's batching machinery.
You could do this manually:
```clojure
;; assuming require next.jdbc.prepare :as p
(with-open [con (jdbc/get-connection ds)
@ -78,7 +83,7 @@ Here we set parameters and add them in batches to the prepared statement, then w
(.executeBatch ps)) ; returns int[]
```
A helper function is provided in `next.jdbc.prepare` to automate the execution of batched parameters:
Both of those are somewhat ugly and contain a fair bit of boilerplate and Java interop, so a helper function is provided in `next.jdbc.prepare` to automate the execution of batched parameters:
```clojure
(with-open [con (jdbc/get-connection ds)

View file

@ -73,7 +73,18 @@ In addition, inside `plan`, as each value is looked up by name in the current st
The default implementation of this protocol is for these two functions to return `nil` as `nil`, a `Boolean` value as a canonical `true` or `false` value (unfortunately, JDBC drivers cannot be relied on to return unique values here!), and for all other objects to be returned as-is.
Common extensions here could include converting `java.sql.Timestamp` to `java.time.Instant` for example but `next.jdbc` makes no assumptions beyond `nil` and `Boolean`.
`next.jdbc` makes no assumptions beyond `nil` and `Boolean`, but common extensions here could include converting `java.sql.Timestamp` to `java.time.Instant` for example:
```clojure
(extend-protocol rs/ReadableColumn
java.sql.Timestamp
(read-column-by-label ^java.time.Instant [^java.sql.Timestamp v _]
(.toInstant v))
(read-column-by-index ^java.time.Instant [^java.sql.Timestamp v _2 _3]
(.toInstant v)))
```
Remember that a protocol extension will apply to all code running in your application so with the above code **all** timestamp values coming from the database will be converted to `java.time.Instant` for all queries.
Note that the converse, converting Clojure values to database-specific types is handled by the `SettableParameters`, discussed in the next section (Prepared Statements).