Clarify SettableParameter and ReadableColumn usage
This commit is contained in:
parent
1b8e4b8c9c
commit
c246c5db6f
2 changed files with 20 additions and 4 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue