I am working with Spring Batch
version 3.0.7
with Mysql
I had the problem that the person_reader
table has the id
column defined how varchar
and thus the following happens for a simple select
ordered:
id
--
1
10 <--- !!!
2
3
...
What is need it is
id
--
1
2
3
...
10 <--- ok!
...
The solution is use ORDER BY cast(id as unsigned)
If I use JdbcCursorItemReader
I can use in peace:
setSql("SELECT id, first_name, last_name FROM person_reader ORDER BY cast(id as unsigned)");
It works fine. Until here all is ok.
Note: for the batch process, is very important read the data in the correct order.
The problem is with JdbcPagingItemReader
First Try:
JdbcPagingItemReader<Person> itemReader = new JdbcPagingItemReader<>();
itemReader.setDataSource(dataSource);
itemReader.setPageSize(100);
itemReader.setRowMapper(new PersonRowMapper());
MySqlPagingQueryProvider pagingQueryProvider = new MySqlPagingQueryProvider();
pagingQueryProvider.setSelectClause("SELECT id, first_name, last_name");
pagingQueryProvider.setFromClause("FROM person_reader ORDER BY cast(id as unsigned)");
Map<String, Order> sortKeys= new HashMap<>();
sortKeys.put("id", Order.ASCENDING);
pagingQueryProvider.setSortKeys(sortKeys);
itemReader.setQueryProvider(pagingQueryProvider);
Observe:
setFromClause("FROM person_reader ORDER BY cast(id as unsigned)")
put("id", Order.ASCENDING)
The following error appears:
org.springframework.jdbc.BadSqlGrammarException: StatementCallback;
bad SQL grammar [SELECT id, first_name, last_name FROM person_reader ORDER BY cast(id as unsigned) ORDER BY id ASC LIMIT 100];
nested exception is java.sql.SQLSyntaxErrorException:
You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use near 'ORDER BY id ASC LIMIT 100' at line 1
Has sense, the SQL
generated SELECT id, first_name, last_name FROM person_reader ORDER BY cast(id as unsigned) ORDER BY id ASC LIMIT 100
is not correct.
Second Try
JdbcPagingItemReader<Person> itemReader = new JdbcPagingItemReader<>();
itemReader.setDataSource(dataSource);
itemReader.setPageSize(100);
itemReader.setRowMapper(new PersonRowMapper());
MySqlPagingQueryProvider pagingQueryProvider = new MySqlPagingQueryProvider();
pagingQueryProvider.setSelectClause("SELECT id, first_name, last_name");
pagingQueryProvider.setFromClause("FROM person_reader");
Map<String, Order> sortKeys= new HashMap<>();
sortKeys.put("cast(id as unsigned)", Order.ASCENDING);
pagingQueryProvider.setSortKeys(sortKeys);
itemReader.setQueryProvider(pagingQueryProvider);
Observe:
setFromClause("FROM person_reader")
put("cast(id as unsigned)", Order.ASCENDING)
The following error appears:
org.springframework.jdbc.UncategorizedSQLException: StatementCallback;
uncategorized SQLException for SQL [SELECT id, first_name, last_name FROM person_reader ORDER BY cast(id as unsigned) ASC LIMIT 100];
SQL state [S0022]; error code [0]; Column 'cast(id as unsigned)' not found.;
nested exception is java.sql.SQLException: Column 'cast(id as unsigned)' not found.
Has sense about the 'missing' column
Order
is an enum
and thus it can't be extended.
What is the correct approach?
Alpha
If I use in MySQL
's workbench the following:
SELECT id, first_name, last_name, cast(id as unsigned) as sb_sort_column FROM person_reader ORDER BY sb_sort_column ASC
It works fine. If I use:
MySqlPagingQueryProvider pagingQueryProvider = new MySqlPagingQueryProvider();
pagingQueryProvider.setSelectClause("SELECT id, first_name, last_name, cast(id as unsigned) as sb_sort_column");
pagingQueryProvider.setFromClause("FROM person_reader");
Map<String, Order> sortKeys= new HashMap<>();
sortKeys.put("sb_sort_column", Order.ASCENDING);
pagingQueryProvider.setSortKeys(sortKeys);
itemReader.setQueryProvider(pagingQueryProvider);
The following error arises:
org.springframework.jdbc.BadSqlGrammarException:
PreparedStatementCallback;
bad SQL grammar [SELECT id, first_name, last_name, cast(id as unsigned) as sb_sort_column FROM person_reader WHERE ((sb_sort_column > ?)) ORDER BY sb_sort_column ASC LIMIT 100];
nested exception is java.sql.SQLSyntaxErrorException:
Unknown column 'sb_sort_column' in 'where clause'
From above see carefully the 3rd line about the sql
statement generated.