Spring JdbcTemplateの例のクエリ

Spring JdbcTemplateクエリの例

SpringJdbcTemplateを使用してデータベースにデータをクエリまたは抽出する方法を示すいくつかの例を次に示します。

使用される技術:

  • Spring Boot 2.1.2.RELEASE

  • Spring JDBC 5.1.4.RELEASE

  • メーベン3

  • Java 8

要するに:

  • 単一の行または値の場合はjdbcTemplate.queryForObject

  • 複数の行またはリストのjdbcTemplate.query

Note
記事がSpringコア2.5.xからSpring Boot2.1.xに更新されました

P.S You may also interested in this Spring Boot JDBC Examples

1. 単一行のクエリ

Springでは、jdbcTemplate.queryForObject()を使用してデータベースから単一の行レコードをクエリし、行マッパーを介して行をオブジェクトに変換できます。

1.1 Custom RowMapper

CustomerRowMapper.java

import org.springframework.jdbc.core.RowMapper;

import java.sql.ResultSet;
import java.sql.SQLException;

public class CustomerRowMapper implements RowMapper {

    @Override
    public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {

        Customer customer = new Customer();
        customer.setID(rs.getLong("ID"));
        customer.setName(rs.getString("NAME"));
        customer.setAge(rs.getInt("AGE"));
        customer.setCreatedDate(rs.getTimestamp("created_date").toLocalDateTime());

        return customer;

    }
}
import org.springframework.jdbc.core.JdbcTemplate;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public Customer findByCustomerId(Long id) {

        String sql = "SELECT * FROM CUSTOMER WHERE ID = ?";

        return jdbcTemplate.queryForObject(sql, new Object[]{id}, new CustomerRowMapper());

    }

1.2 Spring BeanPropertyRowMapper, this class saves you a lot of time for the mapping.

import org.springframework.jdbc.core.BeanPropertyRowMapper;

    public Customer findByCustomerId2(Long id) {

        String sql = "SELECT * FROM CUSTOMER WHERE ID = ?";

        return (Customer) jdbcTemplate.queryForObject(
            sql,
            new Object[]{id},
            new BeanPropertyRowMapper(Customer.class));

    }

1.3 In Java 8, we can map it directly:

    public Customer findByCustomerId3(Long id) {

        String sql = "SELECT * FROM CUSTOMER WHERE ID = ?";

        return jdbcTemplate.queryForObject(sql, new Object[]{id}, (rs, rowNum) ->
                new Customer(
                        rs.getLong("id"),
                        rs.getString("name"),
                        rs.getInt("age"),
                        rs.getTimestamp("created_date").toLocalDateTime()
                ));

    }

2. 複数行のクエリ

複数の行の場合、jdbcTemplate.query()を使用します

2.1 Custom RowMapper

    public List findAll() {

        String sql = "SELECT * FROM CUSTOMER";

        List customers = jdbcTemplate.query(
                sql,
                new CustomerRowMapper());

        return customers;

    }

2.2 BeanPropertyRowMapper

    public List findAll() {

        String sql = "SELECT * FROM CUSTOMER";

        List customers = jdbcTemplate.query(
                sql,
                new BeanPropertyRowMapper(Customer.class));

        return customers;
    }

2.3 Java 8

    public List findAll() {

        String sql = "SELECT * FROM CUSTOMER";

        return jdbcTemplate.query(
                sql,
                (rs, rowNum) ->
                        new Customer(
                                rs.getLong("id"),
                                rs.getString("name"),
                                rs.getInt("age"),
                                rs.getTimestamp("created_date").toLocalDateTime()
                        )
        );
    }

2.4 jdbcTemplate.queryForList, it works, but not recommend, the mapping in Map may not same as the object, need casting.

    public List findAll() {

        String sql = "SELECT * FROM CUSTOMER";

        List customers = new ArrayList<>();

        List> rows = jdbcTemplate.queryForList(sql);

        for (Map row : rows) {
            Customer obj = new Customer();

            obj.setID(((Integer) row.get("ID")).longValue());
            obj.setName((String) row.get("NAME"));
            // Spring returns BigDecimal, need convert
            obj.setAge(((BigDecimal) row.get("AGE")).intValue());
            obj.setCreatedDate(((Timestamp) row.get("CREATED_DATE")).toLocalDateTime());
            customers.add(obj);
        }

        return customers;
    }

3. 単一の値のクエリ

データベースから単一の行をクエリするのと同じで、jdbcTemplate.queryForObject()を使用します

3.1 Single column name

    public String findCustomerNameById(Long id) {

        String sql = "SELECT NAME FROM CUSTOMER WHERE ID = ?";

        return jdbcTemplate.queryForObject(
                sql, new Object[]{id}, String.class);

    }

3.2 Count

    public int count() {

        String sql = "SELECT COUNT(*) FROM CUSTOMER";

        // queryForInt() is Deprecated
        // https://www.example.com/spring/jdbctemplate-queryforint-is-deprecated/
        //int total = jdbcTemplate.queryForInt(sql);

        return jdbcTemplate.queryForObject(sql, Integer.class);

    }

4. Test

Spring BootCommandLineRunnerアプリケーションを実行し、テーブルを作成してAPIをテストします。

pom.xml

    
        org.springframework.boot
        spring-boot-starter-jdbc
    

    
    
        com.h2database
        h2
    

StartApplication.java

package com.example;

import com.example.customer.Customer;
import com.example.customer.CustomerRepository;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.core.JdbcTemplate;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

@SpringBootApplication
public class StartApplication implements CommandLineRunner {

    private static final Logger log = LoggerFactory.getLogger(StartApplication.class);

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    CustomerRepository customerRepository;

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

    @Override
    public void run(String... args) {

        log.info("StartApplication...");

        startCustomerApp();

    }

    // Tested with H2 database
    void startCustomerApp() {

        jdbcTemplate.execute("DROP TABLE customer IF EXISTS");
        jdbcTemplate.execute("CREATE TABLE customer(" +
                "id SERIAL, name VARCHAR(255), age NUMERIC(2), created_date timestamp)");

        List list = Arrays.asList(
                new Customer("Customer A", 19),
                new Customer("Customer B", 20),
                new Customer("Customer C", 21),
                new Customer("Customer D", 22)
        );

        list.forEach(x -> {
            log.info("Saving...{}", x.getName());
            customerRepository.save(x);
        });

        log.info("[FIND_BY_ID]");
        log.info("{}", customerRepository.findByCustomerId(1L));
        log.info("{}", customerRepository.findByCustomerId2(2L));
        log.info("{}", customerRepository.findByCustomerId3(3L));

        log.info("[FIND_ALL]");
        log.info("{}", customerRepository.findAll());
        log.info("{}", customerRepository.findAll2());
        log.info("{}", customerRepository.findAll3());
        log.info("{}", customerRepository.findAll4());

        log.info("[FIND_NAME_BY_ID]");
        log.info("{}", customerRepository.findCustomerNameById(4L));

        log.info("[COUNT]");
        log.info("{}", customerRepository.count());

    }

}

出力

INFO  com.example.StartApplication - Saving...Customer A
INFO  com.example.StartApplication - Saving...Customer B
INFO  com.example.StartApplication - Saving...Customer C
INFO  com.example.StartApplication - Saving...Customer D
INFO  com.example.StartApplication - [FIND_BY_ID]
INFO  com.example.StartApplication - Customer{ID=1, name='Customer A', age=19, createdDate=2019-08-01T15:48:45.950848}
INFO  com.example.StartApplication - Customer{ID=2, name='Customer B', age=20, createdDate=2019-08-01T15:48:45.961819}
INFO  com.example.StartApplication - Customer{ID=3, name='Customer C', age=21, createdDate=2019-08-01T15:48:45.961819}
INFO  com.example.StartApplication - [FIND_ALL]
INFO  com.example.StartApplication - [
    Customer{ID=1, name='Customer A', age=19, createdDate=2019-08-01T15:48:45.950848},
    Customer{ID=2, name='Customer B', age=20, createdDate=2019-08-01T15:48:45.961819},
    Customer{ID=3, name='Customer C', age=21, createdDate=2019-08-01T15:48:45.961819},
    Customer{ID=4, name='Customer D', age=22, createdDate=2019-08-01T15:48:45.961819}
    ]
//...omitted, duplicate code
INFO  com.example.StartApplication - [FIND_NAME_BY_ID]
INFO  com.example.StartApplication - Customer D
INFO  com.example.StartApplication - [COUNT]
INFO  com.example.StartApplication - 4

ソースコードをダウンロード

$ git clone https://github.com/example/spring-boot.git
$ cd spring-jdbc
$ find com.example.customer