spring-batch icon indicating copy to clipboard operation
spring-batch copied to clipboard

Remove alias of sort key when PagingQueryProvider has sort key with alias and group by clause.

Open pongdangx2 opened this issue 10 months ago • 3 comments

Hello.

Motivation

I tried to build a batch application.

Environment

  • Spring boot, Spring batch
  • mysql
  • kotlin

Problem

I use MySqlPagingQueryProvider like below, and Query built by this provider only works for first page query.
(Because of sort key's alias)

 provider.setSelectClause(
        """
            SELECT 
                  t1.member_id         AS member_id
                , t2.kyc_id            AS kyc_id
                , SUM(t1.balance) AS total_balance
        """.trimIndent()
        )
        provider.setFromClause(
        """
            FROM cash_history t1
             LEFT JOIN kyc t2
               ON t1.member_id = t2.member_id
        """.trimIndent()
        )
        provider.setWhereClause(
        """
            WHERE t1.balance_year_month = '202412'
                  AND kyc_id is NOT NULL
        """.trimIndent()
        )
        provider.setGroupClause("GROUP BY t1.member_id")
        provider.setSortKeys(mapOf("t1.member_id" to Order.ASCENDING))

Generated Remaining Query

SELECT *
FROM (SELECT t1.member_id         AS member_id,
             t2.kyc_id            AS kyc_id,
             SUM(t1.balance) AS total_balance
      FROM cash_history t1
               LEFT JOIN kyc t2
                         ON t1.member_id = t2.member_id
      WHERE t1.balance_year_month = '202412'
        AND kyc_id is NOT NULL
      GROUP BY t1.member_id
     ) AS MAIN_QRY
WHERE ((MAIN_QRY.member_id > ?))
ORDER BY t1.member_id ASC
LIMIT 100

This generated remaining query has order by clause with t1.memeber, and valid scope of t1 alias is in MAIN_QRY.

Solution

  • Use getSortKeysWithoutAliases method for building order by clause after MAIN_QRY appended.
public static String generateLimitGroupedSqlQuery(AbstractSqlPagingQueryProvider provider, String limitClause) {
		StringBuilder sql = new StringBuilder();
		sql.append("SELECT * ");
		sql.append(" FROM (");
		sql.append("SELECT ").append(provider.getSelectClause());
		sql.append(" FROM ").append(provider.getFromClause());
		sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause());
		buildGroupByClause(provider, sql);
		sql.append(") AS MAIN_QRY ");
		sql.append("WHERE ");
		buildSortConditions(provider, sql);
		sql.append(" ORDER BY ").append(buildSortClause(provider.getSortKeysWithoutAliases()));
		sql.append(" ").append(limitClause);

		return sql.toString();
	}

pongdangx2 avatar Jan 09 '25 04:01 pongdangx2