Queries
JdbcTemplate offers APIs for reading result sets; method names do not force a connection or operation to be read-only. Most take an SQL string plus arguments (object or array) and return objects built from the result set; some provide callbacks/mappers for custom processing.
Choose a Method First
| Goal | Method |
|---|---|
| Query multiple Bean or Map rows | queryForList |
| Query one Bean row | queryForObject |
| Query one Map row | queryForMap |
| Query a single value, such as count or sum | queryForLong, queryForObject |
| Query two columns as a Map | queryForPairs |
| Customize row mapping | RowMapper |
| Customize whole ResultSet handling | ResultSetExtractor |
| Process large results row by row | RowCallbackHandler or streaming query |
Query Result Sets
Query a collection of objects or maps and return them.
- ObjectMapping
- Map
- Signatures
// Raw SQL (independent example)
{
List<User> users = jdbc.queryForList(
"select * from users where id > 2", User.class);
}
// Positional arguments (independent example)
{
Object[] args = new Object[]{ 2 };
List<User> result = jdbc.queryForList(
"select * from users where id > ?", args, User.class);
}
// Named arguments (independent example)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("id", 2);
List<User> result = jdbc.queryForList(
"select * from users where id > :id", namedArgs, User.class);
}
// Raw SQL (independent example)
{
List<Map<String, Object>> users = jdbc.queryForList(
"select * from users where id > 2");
}
// Positional arguments (independent example)
{
Object[] args = new Object[]{ 2 };
List<Map<String, Object>> result = jdbc.queryForList(
"select * from users where id > ?", args);
}
// Named arguments (independent example)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("id", 2);
List<Map<String, Object>> result = jdbc.queryForList(
"select * from users where id > :id", namedArgs);
}
// Use object mapping or type handlers
List<T> queryForList(String sql, Class<T> elementType);
List<T> queryForList(String sql, Object args, Class<T> elementType);
List<T> queryForList(String sql, PreparedStatementSetter pss, Class<T> elementType);
// Use RowMapper
List<T> queryForList(String sql, RowMapper<T> rowMapper);
List<T> queryForList(String sql, Object args, RowMapper<T> rowMapper);
List<T> queryForList(String sql, PreparedStatementSetter pss, RowMapper<T> rowMapper);
// Receive List/Map without mapping
List<Map<String, Object>> queryForList(String sql);
List<Map<String, Object>> queryForList(String sql, Object args);
List<Map<String, Object>> queryForList(String sql, PreparedStatementSetter pss);
Query a Single Object
Return one row mapped to the specified type. Common use: aggregates or primary-key lookups. No rows returns null; multiple rows raise an exception. Use wrapper types for potentially null scalar results.
- ObjectMapping
- Map
- Signatures
// Raw SQL (independent example)
{
User user = jdbc.queryForObject(
"select * from users where id = 2", User.class);
}
// Positional arguments (independent example)
{
Object[] args = new Object[]{ 2 };
User user = jdbc.queryForObject(
"select * from users where id = ?", args, User.class);
}
// Named arguments (independent example)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("id", 2);
User user = jdbc.queryForObject(
"select * from users where id = :id", namedArgs, User.class);
}
// Raw SQL (independent example)
{
Map<String, Object> user = jdbc.queryForMap(
"select * from users where id = 2");
}
// Positional arguments (independent example)
{
Object[] args = new Object[]{ 2 };
Map<String, Object> user = jdbc.queryForMap(
"select * from users where id = ?", args);
}
// Named arguments (independent example)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("id", 2);
Map<String, Object> user = jdbc.queryForMap(
"select * from users where id = :id", namedArgs);
}
// Use object mapping or type handlers
T queryForObject(String sql, Class<T> requiredType);
T queryForObject(String sql, Object args, Class<T> requiredType);
T queryForObject(String sql, PreparedStatementSetter pss, Class<T> requiredType);
// Use RowMapper
T queryForObject(String sql, RowMapper<T> rowMapper);
T queryForObject(String sql, Object args, RowMapper<T> rowMapper);
T queryForObject(String sql, PreparedStatementSetter pss, RowMapper<T> rowMapper);
// Receive List/Map without mapping
Map<String, Object> queryForMap(String sql);
Map<String, Object> queryForMap(String sql, Object args);
Map<String, Object> queryForMap(String sql, PreparedStatementSetter pss);
Query Key-Value Pairs
Use the first and second columns of the result set as Map key/value.
- Example
- Signatures
// Raw SQL (independent example)
{
Map<Long, String> userMap = jdbc.queryForPairs(
"select uid, name from user where age > 2", Long.class, String.class);
}
// Positional arguments (independent example)
{
Object[] args = new Object[]{ 2 };
Map<Long, String> userMap = jdbc.queryForPairs(
"select uid, name from user where age > ?", Long.class, String.class, args);
}
// Named arguments (independent example)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("age", 2);
Map<Long, String> userMap = jdbc.queryForPairs(
"select uid, name from user where age > :age", Long.class, String.class, namedArgs);
}
// pairKey and pairValue use object mapping or type handlers.
Map<K, V> queryForPairs(String sql,
Class<K> pairKey, Class<V> pairValue);
Map<K, V> queryForPairs(String sql,
Class<K> pairKey, Class<V> pairValue, Object args);
Map<K, V> queryForPairs(String sql,
Class<K> pairKey, Class<V> pairValue, PreparedStatementSetter args);
Query Values
Values are the smallest mappable units (types registered in TypeHandlerRegistry), e.g., String, Int, Date. Two common cases:
- Value lists, e.g., an ID collection.
- Aggregate info, e.g., counts or averages.
- Single value
- Multiple value
- Signatures
// Raw SQL (independent example)
{
long count = jdbc.queryForLong(
"select count(*) from user where age > 2");
}
// Positional arguments (independent example)
{
Object[] args = new Object[]{ 2 };
long count = jdbc.queryForLong(
"select count(*) from user where age > ?", args);
}
// Named arguments (independent example)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("age", 2);
long count = jdbc.queryForLong(
"select count(*) from user where age > :age", namedArgs);
}
jdbc.queryForObject("select count(*) from users", Integer.class);is equivalent.
// Raw SQL (independent example)
{
List<String> result = jdbc.queryForList(
"select name from users", String.class);
}
// Positional arguments (independent example)
{
Object[] args = new Object[]{ "Bob" };
List<String> result = jdbc.queryForList(
"select name from users where name = ?", args, String.class);
}
// Named arguments (independent example)
{
Map<String, Object> namedArgs = CollectionUtils.asMap("name", "Bob");
List<String> result = jdbc.queryForList(
"select name from users where name = :name", namedArgs, String.class);
}
// Query Long values
Long queryForLong(String sql);
Long queryForLong(String sql, Object args);
Long queryForLong(String sql, PreparedStatementSetter args);
// Query int values
Integer queryForInt(String sql);
Integer queryForInt(String sql, Object args);
Integer queryForInt(String sql, PreparedStatementSetter args);
// Query String values
String queryForString(String sql);
String queryForString(String sql, Object args);
String queryForString(String sql, PreparedStatementSetter args);
Result Receiving
These examples cover the most common return shapes. For more control over result mapping, choose from the following table; see Receiving Results for details.
| Goal | Use | Details |
|---|---|---|
| Convert each row to an object | RowMapper | RowMapper |
| Receive column names and values without an entity class | List<Map<String,Object>> | List/Map |
| Consume large results row by row without collecting in memory | RowCallbackHandler | RowCallbackHandler |
Control the whole ResultSet traversal yourself | ResultSetExtractor | ResultSetExtractor |
| Serialize or deserialize single-column values | TypeHandler | Type Handling |
Use ResultSetExtractor
User user = jdbc.query(
"select * from users where id = ?",
new Object[]{ 1 },
(ResultSetExtractor<User>) rs -> {
if (!rs.next()) {
return null;
}
User u = new User();
u.setId(rs.getLong("id"));
u.setName(rs.getString("name"));
return u;
}
);
Row-by-Row Processing
Callbacks avoid collecting all results in application memory. On-demand server reads still depend on the JDBC driver, fetchSize and connection settings.
RowCallbackHandler handler = (rs, rowNum) -> {
// Process each row without collecting a List
};
jdbc.query("select * from users where age > ?", new Object[]{ 18 }, handler);
Map Case Sensitivity
By default, Map result keys are case-insensitive. Different databases may return column names with different casing, such as uppercase in Oracle or lowercase in MySQL. If you need strict case-sensitive keys, see List/Map.
Query Argument Notes
In query-related APIs, arguments are passed uniformly as Object. Supported types include:
- Positional arguments (put multiple values in an array or collection; the method takes
Object args, not varargs)- Arrays, Collection, types registered in TypeRegistry
- Named arguments
- Map, entity Bean, SqlArg (name will be fixed as
arg0)
- Map, entity Bean, SqlArg (name will be fixed as
- Custom: fully custom argument-setting logic for scenarios requiring manual type control.
- Dynamic SQL
- Use Rules to bind arguments when building query commands, supporting named arguments.
- Using
${...}for SQL text substitution does not participate in PreparedStatement but is still a form of argument passing.
Argument types are ultimately processed through TypeHandler to ensure correct mapping between JDBC types and Java types.