Add Data class support in JdbcCursorItemReaderBuilder & JdbcPagingItemReaderBuilder

Resolves #4578
This commit is contained in:
Juyoung Kim
2024-05-05 20:57:23 +09:00
committed by Mahmoud Ben Hassine
parent f6dcea81c8
commit 2d67b7eb3f
4 changed files with 115 additions and 6 deletions

View File

@@ -25,6 +25,7 @@ import org.springframework.jdbc.core.ArgumentTypePreparedStatementSetter;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.DataClassRowMapper;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -38,6 +39,7 @@ import org.springframework.util.StringUtils;
* @author Ankur Trapasiya
* @author Parikshit Dutta
* @author Fabio Molignoni
* @author Juyoung Kim
* @since 4.0
*/
public class JdbcCursorItemReaderBuilder<T> {
@@ -312,6 +314,18 @@ public class JdbcCursorItemReaderBuilder<T> {
return this;
}
/**
* Creates a {@link DataClassRowMapper} to be used as your {@link RowMapper}.
* @param mappedClass the class for the row mapper
* @return this instance for method chaining
* @see DataClassRowMapper
*/
public JdbcCursorItemReaderBuilder<T> dataRowMapper(Class<T> mappedClass) {
this.rowMapper = new DataClassRowMapper<>(mappedClass);
return this;
}
/**
* Set whether "autoCommit" should be overridden for the connection used by the
* cursor. If not set, defaults to Connection / Datasource default configuration.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 the original author or authors.
* Copyright 2017-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import org.springframework.batch.item.database.support.SqlitePagingQueryProvider
import org.springframework.batch.item.database.support.SybasePagingQueryProvider;
import org.springframework.batch.support.DatabaseType;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.DataClassRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.MetaDataAccessException;
import org.springframework.util.Assert;
@@ -52,6 +53,7 @@ import org.springframework.util.Assert;
* @author Drummond Dawson
* @author Mahmoud Ben Hassine
* @author Minsoo Kim
* @author Juyoung Kim
* @since 4.0
* @see JdbcPagingItemReader
*/
@@ -186,6 +188,18 @@ public class JdbcPagingItemReaderBuilder<T> {
return this;
}
/**
* Creates a {@link DataClassRowMapper} to be used as your {@link RowMapper}.
* @param mappedClass the class for the row mapper
* @return this instance for method chaining
* @see DataClassRowMapper
*/
public JdbcPagingItemReaderBuilder<T> dataRowMapper(Class<T> mappedClass) {
this.rowMapper = new DataClassRowMapper<>(mappedClass);
return this;
}
/**
* A {@link Map} of values to set on the SQL's prepared statement.
* @param parameterValues Map of values

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2023 the original author or authors.
* Copyright 2016-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,6 +47,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
* @author Ankur Trapasiya
* @author Parikshit Dutta
* @author Mahmoud Ben Hassine
* @author Juyoung Kim
*/
class JdbcCursorItemReaderBuilderTests {
@@ -334,6 +335,29 @@ class JdbcCursorItemReaderBuilderTests {
assertEquals(third, item.getThird());
}
@Test
void testDataRowMapper() throws Exception {
JdbcCursorItemReader<Bar> reader = new JdbcCursorItemReaderBuilder<Bar>()
.name("barReader")
.dataSource(this.dataSource)
.currentItemCount(1)
.maxItemCount(2)
.sql("SELECT ID, FIRST, SECOND, THIRD FROM BAR ORDER BY ID DESC")
.dataRowMapper(Bar.class)
.build();
reader.afterPropertiesSet();
reader.open(new ExecutionContext());
Bar item1 = reader.read();
assertNull(reader.read());
assertEquals(3, item1.id());
assertEquals(10, item1.first());
assertEquals("11", item1.second());
assertEquals("12", item1.third());
}
public static class Foo {
private int first;
@@ -368,6 +392,8 @@ class JdbcCursorItemReaderBuilderTests {
}
public record Bar(int id, int first, String second, String third) {}
@Configuration
public static class TestDataSourceConfiguration {
@@ -376,12 +402,24 @@ class JdbcCursorItemReaderBuilderTests {
ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
FIRST BIGINT ,
SECOND VARCHAR(5) NOT NULL,
THIRD VARCHAR(5) NOT NULL);""";
THIRD VARCHAR(5) NOT NULL);
CREATE TABLE BAR (
ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
FIRST BIGINT ,
SECOND VARCHAR(5) NOT NULL,
THIRD VARCHAR(5) NOT NULL) ;""";
private static final String INSERT_SQL = """
INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (1, '2', '3');
INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (4, '5', '6');
INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (7, '8', '9');""";
INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (7, '8', '9');
INSERT INTO BAR (FIRST, SECOND, THIRD) VALUES (1, '2', '3');
INSERT INTO BAR (FIRST, SECOND, THIRD) VALUES (4, '5', '6');
INSERT INTO BAR (FIRST, SECOND, THIRD) VALUES (7, '8', '9');
INSERT INTO BAR (FIRST, SECOND, THIRD) VALUES (10, '11', '12');
INSERT INTO BAR (FIRST, SECOND, THIRD) VALUES (13, '14', '15');""";
@Bean
public DataSource dataSource() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 the original author or authors.
* Copyright 2017-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,6 +47,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
* @author Michael Minella
* @author Drummond Dawson
* @author Mahmoud Ben Hassine
* @author Juyoung Kim
*/
class JdbcPagingItemReaderBuilderTests {
@@ -262,6 +263,34 @@ class JdbcPagingItemReaderBuilderTests {
assertEquals("12", item1.getThird());
}
@Test
void testDataRowMapper() throws Exception {
Map<String, Order> sortKeys = new HashMap<>(1);
sortKeys.put("ID", Order.DESCENDING);
JdbcPagingItemReader<Bar> reader = new JdbcPagingItemReaderBuilder<Bar>()
.name("barReader")
.dataSource(this.dataSource)
.currentItemCount(1)
.maxItemCount(2)
.selectClause("SELECT ID, FIRST, SECOND, THIRD")
.fromClause("BAR")
.sortKeys(sortKeys)
.dataRowMapper(Bar.class)
.build();
reader.afterPropertiesSet();
reader.open(new ExecutionContext());
Bar item1 = reader.read();
assertNull(reader.read());
assertEquals(3, item1.id());
assertEquals(10, item1.first());
assertEquals("11", item1.second());
assertEquals("12", item1.third());
}
@Test
void testValidation() {
var builder = new JdbcPagingItemReaderBuilder<Foo>();
@@ -354,6 +383,8 @@ class JdbcPagingItemReaderBuilderTests {
}
public record Bar(int id, int first, String second, String third) {}
@Configuration
public static class TestDataSourceConfiguration {
@@ -362,6 +393,12 @@ class JdbcPagingItemReaderBuilderTests {
ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
FIRST BIGINT ,
SECOND VARCHAR(5) NOT NULL,
THIRD VARCHAR(5) NOT NULL) ;
CREATE TABLE BAR (
ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
FIRST BIGINT ,
SECOND VARCHAR(5) NOT NULL,
THIRD VARCHAR(5) NOT NULL) ;""";
private static final String INSERT_SQL = """
@@ -369,7 +406,13 @@ class JdbcPagingItemReaderBuilderTests {
INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (4, '5', '6');
INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (7, '8', '9');
INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (10, '11', '12');
INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (13, '14', '15');""";
INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (13, '14', '15');
INSERT INTO BAR (FIRST, SECOND, THIRD) VALUES (1, '2', '3');
INSERT INTO BAR (FIRST, SECOND, THIRD) VALUES (4, '5', '6');
INSERT INTO BAR (FIRST, SECOND, THIRD) VALUES (7, '8', '9');
INSERT INTO BAR (FIRST, SECOND, THIRD) VALUES (10, '11', '12');
INSERT INTO BAR (FIRST, SECOND, THIRD) VALUES (13, '14', '15');""";
@Bean
public DataSource dataSource() {