Master Spring Boot 3.2 JdbcClient: Fluent API for Simple DB Operations

This guide introduces Spring Boot 3.2's new JdbcClient, explains how to add the dependency, inject it, and perform fluent, chainable CRUD operations—including queries by ID, custom conditions, named parameters, map parameters, row mapping, and inserts—while highlighting its advantages over traditional ORM tools.

Programmer DD
Programmer DD
Programmer DD
Master Spring Boot 3.2 JdbcClient: Fluent API for Simple DB Operations

Overview

Spring Boot 3.2 adds a new JdbcClient for database access. It wraps JdbcTemplate with a fluent API, enabling chainable calls and easier SQL handling.

Introducing JdbcClient

JdbcClient is a lightweight framework that supports complex SQL while remaining simple and readable.

Adding JdbcClient

First, include the spring-data-jdbc starter:

implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'

Then inject it into a service:

@Component
public class DbService {
    @Autowired
    private JdbcClient jdbcClient;
}

Query Operations

Query by primary key:

public MyData findDataById(Long id) {
    return jdbcClient.sql("select * from my_data where id = ?")
        .params(id)
        .query(MyData.class)
        .single();
}

Query by custom condition:

public List<MyData> findDataByName(String name) {
    return jdbcClient.sql("select * from my_data where name = ?")
        .params(name)
        .query(MyData.class)
        .list();
}

Named‑parameter query:

public Integer insertDataWithNamedParam(MyData myData) {
    Integer rowsAffected = jdbcClient.sql("insert into my_data values(:id,:name)")
        .param("id", myData.id())
        .param("name", myData.name())
        .update();
    return rowsAffected;
}

Map‑based parameters:

public List<MyData> findDataByParamMap(Map<String, ?> paramMap) {
    return jdbcClient.sql("select * from my_data where name = :name")
        .params(paramMap)
        .query(MyData.class)
        .list();
}

RowMapper for complex results:

public List<MyData> findDataWithRowMapper() {
    return jdbcClient.sql("select * from my_data")
        .query((rs, rowNum) -> new MyData(rs.getLong("id"), rs.getString("name")))
        .list();
}

Count query:

public Integer countByName(String name) {
    return jdbcClient.sql("select count(*) from my_data where name = ?")
        .params(name)
        .query(Integer.class)
        .single();
}

Insert Operations

Insert with positional parameters:

public Integer insertDataWithParam(MyData myData) {
    Integer rowsAffected = jdbcClient.sql("insert into my_data values(?,?)")
        .param(myData.id())
        .param(myData.name())
        .update();
    return rowsAffected;
}

Insert with named parameters:

public Integer insertDataWithNamedParam(MyData myData) {
    Integer rowsAffected = jdbcClient.sql("insert into my_data values(:id,:name)")
        .param("id", myData.id())
        .param("name", myData.name())
        .update();
    return rowsAffected;
}

Insert using an object as a parameter source:

public Integer insertDataWithObject(MyData myData) {
    Integer rowsAffected = jdbcClient.sql("insert into my_data values(:id,:name)")
        .paramSource(myData)
        .update();
    return rowsAffected;
}

Full Demo Application

@Slf4j
@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    private DbService dbService;

    @Override
    public void run(String... args) {
        MyData myData = new MyData(1L, "test");
        log.info("insert rows: {}", dbService.insertDataWithObject(myData));

        MyData myData2 = new MyData(2L, "test");
        dbService.insertDataWithParam(myData2);

        MyData myData3 = new MyData(3L, "author");
        dbService.insertDataWithNamedParam(myData3);

        log.info("findDataById: {}", dbService.findDataById(1L));
        log.info("findDataByName: {}", dbService.findDataByName("test"));
        log.info("findDataWithRowMapper: {}", dbService.findDataWithRowMapper());
        log.info("findDataByParamMap: {}", dbService.findDataByParamMap(Map.of("name", "author")));
        log.info("countByName: {}", dbService.countByName("test"));
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

The examples demonstrate that most common database operations can be performed with JdbcClient, offering a simpler and more flexible alternative to heavyweight ORM frameworks.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSQLdatabaseSpring BootJdbcClientFluent API
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.