Migrate to Asciidoctor Tabs
This commit is contained in:
@@ -17,8 +17,11 @@ the prepared statement. This method is called the number of times that you
|
||||
specified in the `getBatchSize` call. The following example updates the `t_actor` table
|
||||
based on entries in a list, and the entire list is used as the batch:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -47,8 +50,10 @@ based on entries in a list, and the entire list is used as the batch:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -71,6 +76,7 @@ based on entries in a list, and the entire list is used as the batch:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
If you process a stream of updates or reading from a file, you might have a
|
||||
preferred batch size, but the last batch might not have that number of entries. In this
|
||||
@@ -94,8 +100,11 @@ in an array of bean-style objects (with getter methods corresponding to paramete
|
||||
|
||||
The following example shows a batch update using named parameters:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -114,8 +123,10 @@ The following example shows a batch update using named parameters:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -130,6 +141,7 @@ The following example shows a batch update using named parameters:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
For an SQL statement that uses the classic `?` placeholders, you pass in a list
|
||||
containing an object array with the update values. This object array must have one entry
|
||||
@@ -139,8 +151,11 @@ defined in the SQL statement.
|
||||
The following example is the same as the preceding example, except that it uses classic
|
||||
JDBC `?` placeholders:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -165,8 +180,10 @@ JDBC `?` placeholders:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -184,6 +201,7 @@ JDBC `?` placeholders:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
All of the batch update methods that we described earlier return an `int` array
|
||||
containing the number of affected rows for each batch entry. This count is reported by
|
||||
@@ -223,8 +241,11 @@ update calls into batches of the size specified.
|
||||
|
||||
The following example shows a batch update that uses a batch size of 100:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -250,8 +271,10 @@ The following example shows a batch update that uses a batch size of 100:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -270,6 +293,7 @@ The following example shows a batch update that uses a batch size of 100:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The batch update method for this call returns an array of `int` arrays that contains an
|
||||
array entry for each batch with an array of the number of affected rows for each update.
|
||||
|
||||
@@ -48,8 +48,11 @@ To configure a `DriverManagerDataSource`:
|
||||
|
||||
The following example shows how to configure a `DriverManagerDataSource` in Java:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
|
||||
@@ -57,8 +60,10 @@ The following example shows how to configure a `DriverManagerDataSource` in Java
|
||||
dataSource.setUsername("sa");
|
||||
dataSource.setPassword("");
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val dataSource = DriverManagerDataSource().apply {
|
||||
setDriverClassName("org.hsqldb.jdbcDriver")
|
||||
@@ -67,6 +72,7 @@ The following example shows how to configure a `DriverManagerDataSource` in Java
|
||||
password = ""
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The following example shows the corresponding XML configuration:
|
||||
|
||||
|
||||
@@ -57,54 +57,75 @@ See the attendant {api-spring-framework}/jdbc/core/JdbcTemplate.html[javadoc] fo
|
||||
|
||||
The following query gets the number of rows in a relation:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val rowCount = jdbcTemplate.queryForObject<Int>("select count(*) from t_actor")!!
|
||||
----
|
||||
======
|
||||
|
||||
The following query uses a bind variable:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
int countOfActorsNamedJoe = this.jdbcTemplate.queryForObject(
|
||||
"select count(*) from t_actor where first_name = ?", Integer.class, "Joe");
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val countOfActorsNamedJoe = jdbcTemplate.queryForObject<Int>(
|
||||
"select count(*) from t_actor where first_name = ?", arrayOf("Joe"))!!
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
The following query looks for a `String`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
String lastName = this.jdbcTemplate.queryForObject(
|
||||
"select last_name from t_actor where id = ?",
|
||||
String.class, 1212L);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val lastName = this.jdbcTemplate.queryForObject<String>(
|
||||
"select last_name from t_actor where id = ?",
|
||||
arrayOf(1212L))!!
|
||||
----
|
||||
======
|
||||
|
||||
The following query finds and populates a single domain object:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
Actor actor = jdbcTemplate.queryForObject(
|
||||
"select first_name, last_name from t_actor where id = ?",
|
||||
@@ -116,8 +137,10 @@ The following query finds and populates a single domain object:
|
||||
},
|
||||
1212L);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val actor = jdbcTemplate.queryForObject(
|
||||
"select first_name, last_name from t_actor where id = ?",
|
||||
@@ -125,11 +148,15 @@ The following query finds and populates a single domain object:
|
||||
Actor(rs.getString("first_name"), rs.getString("last_name"))
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The following query finds and populates a list of domain objects:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
List<Actor> actors = this.jdbcTemplate.query(
|
||||
"select first_name, last_name from t_actor",
|
||||
@@ -140,20 +167,26 @@ The following query finds and populates a list of domain objects:
|
||||
return actor;
|
||||
});
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val actors = jdbcTemplate.query("select first_name, last_name from t_actor") { rs, _ ->
|
||||
Actor(rs.getString("first_name"), rs.getString("last_name"))
|
||||
----
|
||||
======
|
||||
|
||||
If the last two snippets of code actually existed in the same application, it would make
|
||||
sense to remove the duplication present in the two `RowMapper` lambda expressions and
|
||||
extract them out into a single field that could then be referenced by DAO methods as needed.
|
||||
For example, it may be better to write the preceding code snippet as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
private final RowMapper<Actor> actorRowMapper = (resultSet, rowNum) -> {
|
||||
Actor actor = new Actor();
|
||||
@@ -166,8 +199,10 @@ For example, it may be better to write the preceding code snippet as follows:
|
||||
return this.jdbcTemplate.query("select first_name, last_name from t_actor", actorRowMapper);
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val actorMapper = RowMapper<Actor> { rs: ResultSet, rowNum: Int ->
|
||||
Actor(rs.getString("first_name"), rs.getString("last_name"))
|
||||
@@ -177,6 +212,7 @@ For example, it may be better to write the preceding code snippet as follows:
|
||||
return jdbcTemplate.query("select first_name, last_name from t_actor", actorMapper)
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
[[jdbc-JdbcTemplate-examples-update]]
|
||||
=== Updating (`INSERT`, `UPDATE`, and `DELETE`) with `JdbcTemplate`
|
||||
@@ -186,52 +222,70 @@ Parameter values are usually provided as variable arguments or, alternatively, a
|
||||
|
||||
The following example inserts a new entry:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
this.jdbcTemplate.update(
|
||||
"insert into t_actor (first_name, last_name) values (?, ?)",
|
||||
"Leonor", "Watling");
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
jdbcTemplate.update(
|
||||
"insert into t_actor (first_name, last_name) values (?, ?)",
|
||||
"Leonor", "Watling")
|
||||
----
|
||||
======
|
||||
|
||||
The following example updates an existing entry:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
this.jdbcTemplate.update(
|
||||
"update t_actor set last_name = ? where id = ?",
|
||||
"Banjo", 5276L);
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
jdbcTemplate.update(
|
||||
"update t_actor set last_name = ? where id = ?",
|
||||
"Banjo", 5276L)
|
||||
----
|
||||
======
|
||||
|
||||
The following example deletes an entry:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
this.jdbcTemplate.update(
|
||||
"delete from t_actor where id = ?",
|
||||
Long.valueOf(actorId));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
jdbcTemplate.update("delete from t_actor where id = ?", actorId.toLong())
|
||||
----
|
||||
======
|
||||
|
||||
[[jdbc-JdbcTemplate-examples-other]]
|
||||
=== Other `JdbcTemplate` Operations
|
||||
@@ -241,33 +295,45 @@ method is often used for DDL statements. It is heavily overloaded with variants
|
||||
callback interfaces, binding variable arrays, and so on. The following example creates a
|
||||
table:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
jdbcTemplate.execute("create table mytable (id integer, name varchar(100))")
|
||||
----
|
||||
======
|
||||
|
||||
The following example invokes a stored procedure:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
this.jdbcTemplate.update(
|
||||
"call SUPPORT.REFRESH_ACTORS_SUMMARY(?)",
|
||||
Long.valueOf(unionId));
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
jdbcTemplate.update(
|
||||
"call SUPPORT.REFRESH_ACTORS_SUMMARY(?)",
|
||||
unionId.toLong())
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
More sophisticated stored procedure support is xref:data-access/jdbc/object.adoc#jdbc-StoredProcedure[covered later].
|
||||
@@ -288,8 +354,11 @@ that shared `DataSource` bean into your DAO classes. The `JdbcTemplate` is creat
|
||||
the setter for the `DataSource`. This leads to DAOs that resemble the following:
|
||||
|
||||
--
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcCorporateEventDao implements CorporateEventDao {
|
||||
|
||||
@@ -302,8 +371,10 @@ the setter for the `DataSource`. This leads to DAOs that resemble the following:
|
||||
// JDBC-backed implementations of the methods on the CorporateEventDao follow...
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcCorporateEventDao(dataSource: DataSource) : CorporateEventDao {
|
||||
|
||||
@@ -312,6 +383,7 @@ the setter for the `DataSource`. This leads to DAOs that resemble the following:
|
||||
// JDBC-backed implementations of the methods on the CorporateEventDao follow...
|
||||
}
|
||||
----
|
||||
======
|
||||
--
|
||||
|
||||
The following example shows the corresponding XML configuration:
|
||||
@@ -350,8 +422,11 @@ support for dependency injection. In this case, you can annotate the class with
|
||||
method with `@Autowired`. The following example shows how to do so:
|
||||
|
||||
--
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@Repository // <1>
|
||||
public class JdbcCorporateEventDao implements CorporateEventDao {
|
||||
@@ -366,6 +441,7 @@ method with `@Autowired`. The following example shows how to do so:
|
||||
// JDBC-backed implementations of the methods on the CorporateEventDao follow...
|
||||
}
|
||||
----
|
||||
======
|
||||
<1> Annotate the class with `@Repository`.
|
||||
<2> Annotate the `DataSource` setter method with `@Autowired`.
|
||||
<3> Create a new `JdbcTemplate` with the `DataSource`.
|
||||
@@ -440,8 +516,11 @@ section describes only those areas of the `NamedParameterJdbcTemplate` class tha
|
||||
from the `JdbcTemplate` itself -- namely, programming JDBC statements by using named
|
||||
parameters. The following example shows how to use `NamedParameterJdbcTemplate`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
// some JDBC-backed DAO class...
|
||||
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
@@ -460,8 +539,9 @@ parameters. The following example shows how to use `NamedParameterJdbcTemplate`:
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
private val namedParameterJdbcTemplate = NamedParameterJdbcTemplate(dataSource)
|
||||
|
||||
@@ -471,6 +551,7 @@ parameters. The following example shows how to use `NamedParameterJdbcTemplate`:
|
||||
return namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Int::class.java)!!
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Notice the use of the named parameter notation in the value assigned to the `sql`
|
||||
variable and the corresponding value that is plugged into the `namedParameters`
|
||||
@@ -483,8 +564,11 @@ methods exposed by the `NamedParameterJdbcOperations` and implemented by the
|
||||
|
||||
The following example shows the use of the `Map`-based style:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
// some JDBC-backed DAO class...
|
||||
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
@@ -502,8 +586,10 @@ The following example shows the use of the `Map`-based style:
|
||||
return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
// some JDBC-backed DAO class...
|
||||
private val namedParameterJdbcTemplate = NamedParameterJdbcTemplate(dataSource)
|
||||
@@ -514,6 +600,7 @@ The following example shows the use of the `Map`-based style:
|
||||
return namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Int::class.java)!!
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
One nice feature related to the `NamedParameterJdbcTemplate` (and existing in the same
|
||||
Java package) is the `SqlParameterSource` interface. You have already seen an example of
|
||||
@@ -531,8 +618,11 @@ of named parameter values.
|
||||
|
||||
The following example shows a typical JavaBean:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class Actor {
|
||||
|
||||
@@ -556,17 +646,23 @@ The following example shows a typical JavaBean:
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
data class Actor(val id: Long, val firstName: String, val lastName: String)
|
||||
----
|
||||
======
|
||||
|
||||
The following example uses a `NamedParameterJdbcTemplate` to return the count of the
|
||||
members of the class shown in the preceding example:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
// some JDBC-backed DAO class...
|
||||
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
@@ -585,8 +681,10 @@ members of the class shown in the preceding example:
|
||||
return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
// some JDBC-backed DAO class...
|
||||
private val namedParameterJdbcTemplate = NamedParameterJdbcTemplate(dataSource)
|
||||
@@ -600,6 +698,7 @@ members of the class shown in the preceding example:
|
||||
return namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Int::class.java)!!
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Remember that the `NamedParameterJdbcTemplate` class wraps a classic `JdbcTemplate`
|
||||
template. If you need access to the wrapped `JdbcTemplate` instance to access
|
||||
@@ -651,8 +750,11 @@ name from the database metadata of the database in use.
|
||||
|
||||
You can extend `SQLErrorCodeSQLExceptionTranslator`, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class CustomSQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator {
|
||||
|
||||
@@ -664,8 +766,10 @@ You can extend `SQLErrorCodeSQLExceptionTranslator`, as the following example sh
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class CustomSQLErrorCodesTranslator : SQLErrorCodeSQLExceptionTranslator() {
|
||||
|
||||
@@ -677,6 +781,7 @@ You can extend `SQLErrorCodeSQLExceptionTranslator`, as the following example sh
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
In the preceding example, the specific error code (`-12345`) is translated, while other errors are
|
||||
left to be translated by the default translator implementation. To use this custom
|
||||
@@ -685,8 +790,11 @@ translator, you must pass it to the `JdbcTemplate` through the method
|
||||
processing where this translator is needed. The following example shows how you can use this custom
|
||||
translator:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@@ -710,8 +818,10 @@ translator:
|
||||
" where id = ?", pct, orderId);
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
// create a JdbcTemplate and set data source
|
||||
private val jdbcTemplate = JdbcTemplate(dataSource).apply {
|
||||
@@ -728,6 +838,7 @@ translator:
|
||||
" where id = ?", pct, orderId)
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The custom translator is passed a data source in order to look up the error codes in
|
||||
`sql-error-codes.xml`.
|
||||
@@ -741,8 +852,11 @@ Running an SQL statement requires very little code. You need a `DataSource` and
|
||||
`JdbcTemplate`. The following example shows what you need to include for a minimal but
|
||||
fully functional class that creates a new table:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -760,8 +874,10 @@ fully functional class that creates a new table:
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import javax.sql.DataSource
|
||||
import org.springframework.jdbc.core.JdbcTemplate
|
||||
@@ -775,6 +891,7 @@ fully functional class that creates a new table:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[jdbc-statements-querying]]
|
||||
@@ -786,8 +903,11 @@ Java class that is passed in as an argument. If the type conversion is invalid,
|
||||
`InvalidDataAccessApiUsageException` is thrown. The following example contains two
|
||||
query methods, one for an `int` and one that queries for a `String`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -809,8 +929,10 @@ query methods, one for an `int` and one that queries for a `String`:
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import javax.sql.DataSource
|
||||
import org.springframework.jdbc.core.JdbcTemplate
|
||||
@@ -826,6 +948,7 @@ class RunAQuery(dataSource: DataSource) {
|
||||
get() = jdbcTemplate.queryForObject("select name from mytable")
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
In addition to the single result query methods, several methods return a list with an
|
||||
entry for each row that the query returned. The most generic method is `queryForList(..)`,
|
||||
@@ -833,8 +956,11 @@ which returns a `List` where each element is a `Map` containing one entry for ea
|
||||
using the column name as the key. If you add a method to the preceding example to retrieve a
|
||||
list of all the rows, it might be as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@@ -846,8 +972,10 @@ list of all the rows, it might be as follows:
|
||||
return this.jdbcTemplate.queryForList("select * from mytable");
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
private val jdbcTemplate = JdbcTemplate(dataSource)
|
||||
|
||||
@@ -855,6 +983,7 @@ list of all the rows, it might be as follows:
|
||||
return jdbcTemplate.queryForList("select * from mytable")
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The returned list would resemble the following:
|
||||
|
||||
@@ -869,8 +998,11 @@ The returned list would resemble the following:
|
||||
|
||||
The following example updates a column for a certain primary key:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -888,8 +1020,10 @@ The following example updates a column for a certain primary key:
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import javax.sql.DataSource
|
||||
import org.springframework.jdbc.core.JdbcTemplate
|
||||
@@ -903,6 +1037,7 @@ The following example updates a column for a certain primary key:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
In the preceding example,
|
||||
an SQL statement has placeholders for row parameters. You can pass the parameter values
|
||||
@@ -922,8 +1057,11 @@ update. There is no standard single way to create an appropriate `PreparedStatem
|
||||
(which explains why the method signature is the way it is). The following example works
|
||||
on Oracle but may not work on other platforms:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
final String INSERT_SQL = "insert into my_test (name) values(?)";
|
||||
final String name = "Rob";
|
||||
@@ -937,8 +1075,10 @@ on Oracle but may not work on other platforms:
|
||||
|
||||
// keyHolder.getKey() now contains the generated key
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val INSERT_SQL = "insert into my_test (name) values(?)"
|
||||
val name = "Rob"
|
||||
@@ -950,6 +1090,7 @@ on Oracle but may not work on other platforms:
|
||||
|
||||
// keyHolder.getKey() now contains the generated key
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -44,8 +44,11 @@ The `EmbeddedDatabaseBuilder` class provides a fluent API for constructing an em
|
||||
database programmatically. You can use this when you need to create an embedded database in a
|
||||
stand-alone environment or in a stand-alone integration test, as in the following example:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
EmbeddedDatabase db = new EmbeddedDatabaseBuilder()
|
||||
.generateUniqueName(true)
|
||||
@@ -60,8 +63,10 @@ stand-alone environment or in a stand-alone integration test, as in the followin
|
||||
|
||||
db.shutdown()
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val db = EmbeddedDatabaseBuilder()
|
||||
.generateUniqueName(true)
|
||||
@@ -76,6 +81,7 @@ stand-alone environment or in a stand-alone integration test, as in the followin
|
||||
|
||||
db.shutdown()
|
||||
----
|
||||
======
|
||||
|
||||
See the {api-spring-framework}/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.html[javadoc for `EmbeddedDatabaseBuilder`]
|
||||
for further details on all supported options.
|
||||
@@ -83,8 +89,11 @@ for further details on all supported options.
|
||||
You can also use the `EmbeddedDatabaseBuilder` to create an embedded database by using Java
|
||||
configuration, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
@Configuration
|
||||
public class DataSourceConfig {
|
||||
@@ -102,8 +111,10 @@ configuration, as the following example shows:
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
@Configuration
|
||||
class DataSourceConfig {
|
||||
@@ -121,6 +132,7 @@ configuration, as the following example shows:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[jdbc-embedded-database-types]]
|
||||
@@ -168,8 +180,11 @@ configuring the embedded database as a bean in the Spring `ApplicationContext` a
|
||||
in xref:data-access/jdbc/embedded-database-support.adoc#jdbc-embedded-database-xml[Creating an Embedded Database by Using Spring XML] and xref:data-access/jdbc/embedded-database-support.adoc#jdbc-embedded-database-java[Creating an Embedded Database Programmatically]. The following listing
|
||||
shows the test template:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class DataAccessIntegrationTestTemplate {
|
||||
|
||||
@@ -198,8 +213,10 @@ shows the test template:
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class DataAccessIntegrationTestTemplate {
|
||||
|
||||
@@ -227,6 +244,7 @@ shows the test template:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[jdbc-embedded-database-unique-names]]
|
||||
|
||||
@@ -40,8 +40,11 @@ abstract `mapRow(..)` method to convert each row of the supplied `ResultSet` int
|
||||
object of the type specified. The following example shows a custom query that maps the
|
||||
data from the `t_actor` relation to an instance of the `Actor` class:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class ActorMappingQuery extends MappingSqlQuery<Actor> {
|
||||
|
||||
@@ -61,8 +64,10 @@ data from the `t_actor` relation to an instance of the `Actor` class:
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class ActorMappingQuery(ds: DataSource) : MappingSqlQuery<Actor>(ds, "select id, first_name, last_name from t_actor where id = ?") {
|
||||
|
||||
@@ -79,6 +84,7 @@ data from the `t_actor` relation to an instance of the `Actor` class:
|
||||
}
|
||||
|
||||
----
|
||||
======
|
||||
|
||||
The class extends `MappingSqlQuery` parameterized with the `Actor` type. The constructor
|
||||
for this customer query takes a `DataSource` as the only parameter. In this
|
||||
@@ -93,8 +99,11 @@ thread-safe after it is compiled, so, as long as these instances are created whe
|
||||
is initialized, they can be kept as instance variables and be reused. The following
|
||||
example shows how to define such a class:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
private ActorMappingQuery actorMappingQuery;
|
||||
|
||||
@@ -107,13 +116,16 @@ example shows how to define such a class:
|
||||
return actorMappingQuery.findObject(id);
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
private val actorMappingQuery = ActorMappingQuery(dataSource)
|
||||
|
||||
fun getCustomer(id: Long) = actorMappingQuery.findObject(id)
|
||||
----
|
||||
======
|
||||
|
||||
The method in the preceding example retrieves the customer with the `id` that is passed in as the
|
||||
only parameter. Since we want only one object to be returned, we call the `findObject` convenience
|
||||
@@ -122,19 +134,25 @@ list of objects and took additional parameters, we would use one of the `execute
|
||||
methods that takes an array of parameter values passed in as varargs. The following
|
||||
example shows such a method:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public List<Actor> searchForActors(int age, String namePattern) {
|
||||
return actorSearchMappingQuery.execute(age, namePattern);
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
fun searchForActors(age: Int, namePattern: String) =
|
||||
actorSearchMappingQuery.execute(age, namePattern)
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[jdbc-SqlUpdate]]
|
||||
@@ -149,8 +167,11 @@ However, you do not have to subclass the `SqlUpdate`
|
||||
class, since it can easily be parameterized by setting SQL and declaring parameters.
|
||||
The following example creates a custom update method named `execute`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
import java.sql.Types;
|
||||
import javax.sql.DataSource;
|
||||
@@ -177,8 +198,10 @@ The following example creates a custom update method named `execute`:
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import java.sql.Types
|
||||
import javax.sql.DataSource
|
||||
@@ -205,6 +228,7 @@ The following example creates a custom update method named `execute`:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
[[jdbc-StoredProcedure]]
|
||||
@@ -219,18 +243,24 @@ To define a parameter for the `StoredProcedure` class, you can use an `SqlParame
|
||||
of its subclasses. You must specify the parameter name and SQL type in the constructor,
|
||||
as the following code snippet shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
new SqlParameter("in_id", Types.NUMERIC),
|
||||
new SqlOutParameter("out_first_name", Types.VARCHAR),
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
SqlParameter("in_id", Types.NUMERIC),
|
||||
SqlOutParameter("out_first_name", Types.VARCHAR),
|
||||
----
|
||||
======
|
||||
|
||||
The SQL type is specified using the `java.sql.Types` constants.
|
||||
|
||||
@@ -259,8 +289,11 @@ returned date from the results `Map`. The results `Map` has an entry for each de
|
||||
output parameter (in this case, only one) by using the parameter name as the key.
|
||||
The following listing shows our custom StoredProcedure class:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
import java.sql.Types;
|
||||
import java.util.Date;
|
||||
@@ -306,8 +339,10 @@ The following listing shows our custom StoredProcedure class:
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import java.sql.Types
|
||||
import java.util.Date
|
||||
@@ -343,12 +378,16 @@ The following listing shows our custom StoredProcedure class:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The following example of a `StoredProcedure` has two output parameters (in this case,
|
||||
Oracle REF cursors):
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -374,8 +413,10 @@ Oracle REF cursors):
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import java.util.HashMap
|
||||
import javax.sql.DataSource
|
||||
@@ -401,6 +442,7 @@ Oracle REF cursors):
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Notice how the overloaded variants of the `declareParameter(..)` method that have been
|
||||
used in the `TitlesAndGenresStoredProcedure` constructor are passed `RowMapper`
|
||||
@@ -410,8 +452,11 @@ functionality. The next two examples provide code for the two `RowMapper` implem
|
||||
The `TitleMapper` class maps a `ResultSet` to a `Title` domain object for each row in
|
||||
the supplied `ResultSet`, as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
@@ -428,8 +473,10 @@ the supplied `ResultSet`, as follows:
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import java.sql.ResultSet
|
||||
import com.foo.domain.Title
|
||||
@@ -441,12 +488,16 @@ the supplied `ResultSet`, as follows:
|
||||
Title(rs.getLong("id"), rs.getString("name"))
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The `GenreMapper` class maps a `ResultSet` to a `Genre` domain object for each row in
|
||||
the supplied `ResultSet`, as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
@@ -460,8 +511,10 @@ the supplied `ResultSet`, as follows:
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import java.sql.ResultSet
|
||||
import com.foo.domain.Genre
|
||||
@@ -474,13 +527,17 @@ the supplied `ResultSet`, as follows:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
To pass parameters to a stored procedure that has one or more input parameters in its
|
||||
definition in the RDBMS, you can code a strongly typed `execute(..)` method that would
|
||||
delegate to the untyped `execute(Map)` method in the superclass, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
import java.sql.Types;
|
||||
import java.util.Date;
|
||||
@@ -511,8 +568,10 @@ delegate to the untyped `execute(Map)` method in the superclass, as the followin
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
import java.sql.Types
|
||||
import java.util.Date
|
||||
@@ -539,6 +598,7 @@ delegate to the untyped `execute(Map)` method in the superclass, as the followin
|
||||
mapOf<String, Any>(CUTOFF_DATE_PARAM to cutoffDate))
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -63,8 +63,11 @@ dependency injection.
|
||||
|
||||
The following example shows how to create and insert a BLOB:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
final File blobIn = new File("spring2004.jpg");
|
||||
final InputStream blobIs = new FileInputStream(blobIn);
|
||||
@@ -86,6 +89,7 @@ The following example shows how to create and insert a BLOB:
|
||||
blobIs.close();
|
||||
clobReader.close();
|
||||
----
|
||||
======
|
||||
<1> Pass in the `lobHandler` that (in this example) is a plain `DefaultLobHandler`.
|
||||
<2> Using the method `setClobAsCharacterStream` to pass in the contents of the CLOB.
|
||||
<3> Using the method `setBlobAsBinaryStream` to pass in the contents of the BLOB.
|
||||
@@ -134,8 +138,11 @@ Now it is time to read the LOB data from the database. Again, you use a `JdbcTem
|
||||
with the same instance variable `lobHandler` and a reference to a `DefaultLobHandler`.
|
||||
The following example shows how to do so:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
List<Map<String, Object>> l = jdbcTemplate.query("select id, a_clob, a_blob from lob_table",
|
||||
new RowMapper<Map<String, Object>>() {
|
||||
@@ -149,6 +156,7 @@ The following example shows how to do so:
|
||||
}
|
||||
});
|
||||
----
|
||||
======
|
||||
<1> Using the method `getClobAsString` to retrieve the contents of the CLOB.
|
||||
<2> Using the method `getBlobAsBytes` to retrieve the contents of the BLOB.
|
||||
|
||||
@@ -203,8 +211,11 @@ implemented. This interface is used as part of the declaration of an `SqlOutPara
|
||||
The following example shows returning the value of an Oracle `STRUCT` object of the user
|
||||
declared type `ITEM_TYPE`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class TestItemStoredProcedure extends StoredProcedure {
|
||||
|
||||
@@ -223,8 +234,10 @@ declared type `ITEM_TYPE`:
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class TestItemStoredProcedure(dataSource: DataSource) : StoredProcedure() {
|
||||
|
||||
@@ -239,6 +252,7 @@ declared type `ITEM_TYPE`:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
You can use `SqlTypeValue` to pass the value of a Java object (such as `TestItem`) to a
|
||||
stored procedure. The `SqlTypeValue` interface has a single method (named
|
||||
@@ -246,8 +260,11 @@ stored procedure. The `SqlTypeValue` interface has a single method (named
|
||||
can use it to create database-specific objects, such as `StructDescriptor` instances
|
||||
or `ArrayDescriptor` instances. The following example creates a `StructDescriptor` instance:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
final TestItem testItem = new TestItem(123L, "A test item",
|
||||
new SimpleDateFormat("yyyy-M-d").parse("2010-12-31"));
|
||||
@@ -265,8 +282,10 @@ or `ArrayDescriptor` instances. The following example creates a `StructDescripto
|
||||
}
|
||||
};
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
val (id, description, expirationDate) = TestItem(123L, "A test item",
|
||||
SimpleDateFormat("yyyy-M-d").parse("2010-12-31"))
|
||||
@@ -279,6 +298,7 @@ or `ArrayDescriptor` instances. The following example creates a `StructDescripto
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
You can now add this `SqlTypeValue` to the `Map` that contains the input parameters for the
|
||||
`execute` call of the stored procedure.
|
||||
@@ -288,8 +308,11 @@ procedure. Oracle has its own internal `ARRAY` class that must be used in this c
|
||||
you can use the `SqlTypeValue` to create an instance of the Oracle `ARRAY` and populate
|
||||
it with values from the Java `ARRAY`, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
final Long[] ids = new Long[] {1L, 2L};
|
||||
|
||||
@@ -301,8 +324,10 @@ it with values from the Java `ARRAY`, as the following example shows:
|
||||
}
|
||||
};
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class TestItemStoredProcedure(dataSource: DataSource) : StoredProcedure() {
|
||||
|
||||
@@ -317,6 +342,7 @@ it with values from the Java `ARRAY`, as the following example shows:
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -19,8 +19,11 @@ Configuration methods for this class follow the `fluid` style that returns the i
|
||||
of the `SimpleJdbcInsert`, which lets you chain all configuration methods. The following
|
||||
example uses only one configuration method (we show examples of multiple methods later):
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -41,8 +44,10 @@ example uses only one configuration method (we show examples of multiple methods
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -59,6 +64,7 @@ example uses only one configuration method (we show examples of multiple methods
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The `execute` method used here takes a plain `java.util.Map` as its only parameter. The
|
||||
important thing to note here is that the keys used for the `Map` must match the column
|
||||
@@ -75,8 +81,11 @@ the `SimpleJdbcInsert`, in addition to specifying the table name, it specifies t
|
||||
of the generated key column with the `usingGeneratedKeyColumns` method. The following
|
||||
listing shows how it works:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -99,8 +108,10 @@ listing shows how it works:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -118,6 +129,7 @@ listing shows how it works:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The main difference when you run the insert by using this second approach is that you do not
|
||||
add the `id` to the `Map`, and you call the `executeAndReturnKey` method. This returns a
|
||||
@@ -134,8 +146,11 @@ use a `KeyHolder` that is returned from the `executeAndReturnKeyHolder` method.
|
||||
You can limit the columns for an insert by specifying a list of column names with the
|
||||
`usingColumns` method, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -159,8 +174,10 @@ You can limit the columns for an insert by specifying a list of column names wit
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -180,6 +197,7 @@ You can limit the columns for an insert by specifying a list of column names wit
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The execution of the insert is the same as if you had relied on the metadata to determine
|
||||
which columns to use.
|
||||
@@ -195,8 +213,11 @@ which is a very convenient class if you have a JavaBean-compliant class that con
|
||||
your values. It uses the corresponding getter method to extract the parameter
|
||||
values. The following example shows how to use `BeanPropertySqlParameterSource`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -217,8 +238,10 @@ values. The following example shows how to use `BeanPropertySqlParameterSource`:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -235,12 +258,16 @@ values. The following example shows how to use `BeanPropertySqlParameterSource`:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
Another option is the `MapSqlParameterSource` that resembles a `Map` but provides a more
|
||||
convenient `addValue` method that can be chained. The following example shows how to use it:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -263,8 +290,10 @@ convenient `addValue` method that can be chained. The following example shows ho
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -283,6 +312,7 @@ convenient `addValue` method that can be chained. The following example shows ho
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
As you can see, the configuration is the same. Only the executing code has to change to
|
||||
use these alternative input classes.
|
||||
@@ -325,8 +355,11 @@ The following example of a `SimpleJdbcCall` configuration uses the preceding sto
|
||||
procedure (the only configuration option, in addition to the `DataSource`, is the name
|
||||
of the stored procedure):
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -352,8 +385,10 @@ of the stored procedure):
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -374,6 +409,7 @@ of the stored procedure):
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The code you write for the execution of the call involves creating an `SqlParameterSource`
|
||||
containing the IN parameter. You must match the name provided for the input value
|
||||
@@ -397,8 +433,11 @@ To do the latter, you can create your own `JdbcTemplate` and set the `setResults
|
||||
property to `true`. Then you can pass this customized `JdbcTemplate` instance into
|
||||
the constructor of your `SimpleJdbcCall`. The following example shows this configuration:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -414,8 +453,10 @@ the constructor of your `SimpleJdbcCall`. The following example shows this confi
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -426,6 +467,7 @@ the constructor of your `SimpleJdbcCall`. The following example shows this confi
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
By taking this action, you avoid conflicts in the case used for the names of your
|
||||
returned `out` parameters.
|
||||
@@ -456,8 +498,11 @@ of IN parameter names to include for a given signature.
|
||||
The following example shows a fully declared procedure call and uses the information from
|
||||
the preceding example:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -481,8 +526,10 @@ the preceding example:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -501,6 +548,7 @@ the preceding example:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The execution and end results of the two examples are the same. The second example specifies all
|
||||
details explicitly rather than relying on metadata.
|
||||
@@ -515,18 +563,24 @@ To do so, you typically specify the parameter name and SQL type in the construct
|
||||
is specified by using the `java.sql.Types` constants. Earlier in this chapter, we saw declarations
|
||||
similar to the following:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
new SqlParameter("in_id", Types.NUMERIC),
|
||||
new SqlOutParameter("out_first_name", Types.VARCHAR),
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
SqlParameter("in_id", Types.NUMERIC),
|
||||
SqlOutParameter("out_first_name", Types.VARCHAR),
|
||||
----
|
||||
======
|
||||
|
||||
The first line with the `SqlParameter` declares an IN parameter. You can use IN parameters
|
||||
for both stored procedure calls and for queries by using the `SqlQuery` and its
|
||||
@@ -578,8 +632,11 @@ that returns an actor's full name:
|
||||
To call this function, we again create a `SimpleJdbcCall` in the initialization method,
|
||||
as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -602,8 +659,10 @@ as the following example shows:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -621,6 +680,7 @@ as the following example shows:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The `executeFunction` method used returns a `String` that contains the return value from the
|
||||
function call.
|
||||
@@ -656,8 +716,11 @@ to map follows the JavaBean rules, you can use a `BeanPropertyRowMapper` that is
|
||||
passing in the required class to map to in the `newInstance` method.
|
||||
The following example shows how to do so:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public class JdbcActorDao implements ActorDao {
|
||||
|
||||
@@ -680,8 +743,10 @@ The following example shows how to do so:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
class JdbcActorDao(dataSource: DataSource) : ActorDao {
|
||||
|
||||
@@ -699,6 +764,7 @@ The following example shows how to do so:
|
||||
// ... additional methods
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The `execute` call passes in an empty `Map`, because this call does not take any parameters.
|
||||
The list of actors is then retrieved from the results map and returned to the caller.
|
||||
|
||||
Reference in New Issue
Block a user