Skip to content

Commit 49c4b20

Browse files
committed
Documentation for common JdbcClient query/update usage
See gh-30931
1 parent cf1ba98 commit 49c4b20

File tree

1 file changed

+89
-21
lines changed
  • framework-docs/modules/ROOT/pages/data-access/jdbc

1 file changed

+89
-21
lines changed

Diff for: framework-docs/modules/ROOT/pages/data-access/jdbc/core.adoc

+89-21
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ including error handling. It includes the following topics:
66

77
* xref:data-access/jdbc/core.adoc#jdbc-JdbcTemplate[Using `JdbcTemplate`]
88
* xref:data-access/jdbc/core.adoc#jdbc-NamedParameterJdbcTemplate[Using `NamedParameterJdbcTemplate`]
9+
* xref:data-access/jdbc/core.adoc#jdbc-JdbcClient[Unified JDBC Query/Update Operations: `JdbcClient`]
910
* xref:data-access/jdbc/core.adoc#jdbc-SQLExceptionTranslator[Using `SQLExceptionTranslator`]
1011
* xref:data-access/jdbc/core.adoc#jdbc-statements-executing[Running Statements]
1112
* xref:data-access/jdbc/core.adoc#jdbc-statements-querying[Running Queries]
@@ -501,8 +502,8 @@ extend from it, your sub-class inherits a `setDataSource(..)` method from the
501502
Regardless of which of the above template initialization styles you choose to use (or
502503
not), it is seldom necessary to create a new instance of a `JdbcTemplate` class each
503504
time you want to run SQL. Once configured, a `JdbcTemplate` instance is thread-safe.
504-
If your application accesses multiple
505-
databases, you may want multiple `JdbcTemplate` instances, which requires multiple `DataSources` and, subsequently, multiple differently
505+
If your application accesses multiple databases, you may want multiple `JdbcTemplate`
506+
instances, which requires multiple `DataSources` and, subsequently, multiple differently
506507
configured `JdbcTemplate` instances.
507508

508509

@@ -531,11 +532,8 @@ Java::
531532
}
532533
533534
public int countOfActorsByFirstName(String firstName) {
534-
535-
String sql = "select count(*) from T_ACTOR where first_name = :first_name";
536-
535+
String sql = "select count(*) from t_actor where first_name = :first_name";
537536
SqlParameterSource namedParameters = new MapSqlParameterSource("first_name", firstName);
538-
539537
return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
540538
}
541539
----
@@ -547,7 +545,7 @@ Kotlin::
547545
private val namedParameterJdbcTemplate = NamedParameterJdbcTemplate(dataSource)
548546
549547
fun countOfActorsByFirstName(firstName: String): Int {
550-
val sql = "select count(*) from T_ACTOR where first_name = :first_name"
548+
val sql = "select count(*) from t_actor where first_name = :first_name"
551549
val namedParameters = MapSqlParameterSource("first_name", firstName)
552550
return namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Int::class.java)!!
553551
}
@@ -579,12 +577,9 @@ Java::
579577
}
580578
581579
public int countOfActorsByFirstName(String firstName) {
582-
583-
String sql = "select count(*) from T_ACTOR where first_name = :first_name";
584-
580+
String sql = "select count(*) from t_actor where first_name = :first_name";
585581
Map<String, String> namedParameters = Collections.singletonMap("first_name", firstName);
586-
587-
return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
582+
return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
588583
}
589584
----
590585
@@ -596,7 +591,7 @@ Kotlin::
596591
private val namedParameterJdbcTemplate = NamedParameterJdbcTemplate(dataSource)
597592
598593
fun countOfActorsByFirstName(firstName: String): Int {
599-
val sql = "select count(*) from T_ACTOR where first_name = :first_name"
594+
val sql = "select count(*) from t_actor where first_name = :first_name"
600595
val namedParameters = mapOf("first_name" to firstName)
601596
return namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Int::class.java)!!
602597
}
@@ -644,7 +639,6 @@ Java::
644639
}
645640
646641
// setters omitted...
647-
648642
}
649643
----
650644
@@ -673,12 +667,9 @@ Java::
673667
}
674668
675669
public int countOfActors(Actor exampleActor) {
676-
677670
// notice how the named parameters match the properties of the above 'Actor' class
678-
String sql = "select count(*) from T_ACTOR where first_name = :firstName and last_name = :lastName";
679-
671+
String sql = "select count(*) from t_actor where first_name = :firstName and last_name = :lastName";
680672
SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor);
681-
682673
return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class);
683674
}
684675
----
@@ -694,7 +685,7 @@ Kotlin::
694685
695686
fun countOfActors(exampleActor: Actor): Int {
696687
// notice how the named parameters match the properties of the above 'Actor' class
697-
val sql = "select count(*) from T_ACTOR where first_name = :firstName and last_name = :lastName"
688+
val sql = "select count(*) from t_actor where first_name = :firstName and last_name = :lastName"
698689
val namedParameters = BeanPropertySqlParameterSource(exampleActor)
699690
return namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Int::class.java)!!
700691
}
@@ -707,8 +698,85 @@ functionality that is present only in the `JdbcTemplate` class, you can use the
707698
`getJdbcOperations()` method to access the wrapped `JdbcTemplate` through the
708699
`JdbcOperations` interface.
709700

710-
See also xref:data-access/jdbc/core.adoc#jdbc-JdbcTemplate-idioms[`JdbcTemplate` Best Practices] for guidelines on using the
711-
`NamedParameterJdbcTemplate` class in the context of an application.
701+
See also xref:data-access/jdbc/core.adoc#jdbc-JdbcTemplate-idioms[`JdbcTemplate` Best Practices]
702+
for guidelines on using the `NamedParameterJdbcTemplate` class in the context of an application.
703+
704+
705+
[[jdbc-JdbcClient]]
706+
== Unified JDBC Query/Update Operations: `JdbcClient`
707+
708+
As of 6.1, the named parameter statements of `NamedParameterJdbcTemplate` and the positional
709+
parameter statements of a regular `JdbcTemplate` are available through a unified client API
710+
with a fluent interaction model.
711+
712+
E.g. with named parameters:
713+
714+
[source,java,indent=0,subs="verbatim,quotes"]
715+
----
716+
private JdbcClient jdbcClient = JdbcClient.create(dataSource);
717+
718+
public int countOfActorsByFirstName(String firstName) {
719+
return this.jdbcClient.sql("select count(*) from t_actor where first_name = :first_name")
720+
.param("first_name", firstName);
721+
.query().singleValue(Integer.class);
722+
}
723+
----
724+
725+
E.g. with positional parameters:
726+
727+
[source,java,indent=0,subs="verbatim,quotes"]
728+
----
729+
private JdbcClient jdbcClient = JdbcClient.create(dataSource);
730+
731+
public int countOfActorsByFirstName(String firstName) {
732+
return this.jdbcClient.sql("select count(*) from t_actor where first_name = ?")
733+
.param(firstName);
734+
.query().singleValue(Integer.class);
735+
}
736+
----
737+
738+
`RowMapper` capabilities are available as well, with flexible result resolution:
739+
740+
[source,java,indent=0,subs="verbatim,quotes"]
741+
----
742+
List<Actor> actors = this.jdbcClient.sql("select first_name, last_name from t_actor")
743+
.query((rs, rowNum) -> new Actor(rs.getString("first_name"), rs.getString("last_name")))
744+
.list();
745+
----
746+
747+
With a required single object result:
748+
749+
[source,java,indent=0,subs="verbatim,quotes"]
750+
----
751+
Actor actor = this.jdbcClient.sql("select first_name, last_name from t_actor where id = ?",
752+
.param(1212L);
753+
.query((rs, rowNum) -> new Actor(rs.getString("first_name"), rs.getString("last_name")))
754+
.single();
755+
----
756+
757+
With a `java.util.Optional` result:
758+
759+
[source,java,indent=0,subs="verbatim,quotes"]
760+
----
761+
Optional<Actor> actor = this.jdbcClient.sql("select first_name, last_name from t_actor where id = ?",
762+
.param(1212L);
763+
.query((rs, rowNum) -> new Actor(rs.getString("first_name"), rs.getString("last_name")))
764+
.optional();
765+
----
766+
767+
And for an update statement:
768+
769+
[source,java,indent=0,subs="verbatim,quotes"]
770+
----
771+
this.jdbcClient.sql("insert into t_actor (first_name, last_name) values (?, ?)")
772+
.param("Leonor").param("Watling");
773+
.update();
774+
----
775+
776+
NOTE: `JdbcClient` is a flexible but simplified facade for JDBC query/update statements.
777+
Advanced capabilities such as batch inserts and stored procedure calls typically require
778+
extra customization: consider Spring's `SimpleJdbcInsert` and `SimpleJdbcCall` classes or
779+
plain direct `JdbcTemplate` usage for any such capabilities not available on `JdbcClient`.
712780

713781

714782
[[jdbc-SQLExceptionTranslator]]

0 commit comments

Comments
 (0)