I am using Mybatis with the spring boot application. Where I used to generate MySql query using ProviderMethodResolver. My application supports mybatis annotation processor and XML processor.
To achieve that I used this Mybatis configuration:
In appication.properties file
mybatis.mapper-locations=classpath*:/repository/**/*Repository.xml
and a MybatisConfiguration.java
@Configuration
@EnableTransactionManagement
public class MybatisConfiguration {
    @Bean
    ConfigurationCustomizer mybatisConfigurationCustomizer() {
        return new ConfigurationCustomizer() {
            @Override
            public void customize(org.apache.ibatis.session.Configuration configuration) {
                configuration.setMapUnderscoreToCamelCase(true);
                configuration.setCacheEnabled(true);
            }
        };
    }
}
With above configuration, everything(@Select, @Insert, @ResultMap) seems working fine except implementation of @SelectProvider.
SelectProvider Implemetation is
VariantRepository.java
@Mapper
public interface VariantRepository {
    @SelectProvider(type = VariantSqlProvider.class, method = "getProductAttribute")
    VariantDto findByProductAttribute(@Param("productAttributeDto") ProductAttributeDto productAttributeDto);
}
I am using
org.apache.ibatis.annotations.Param
ProductAttributeDto.java
@Data
public class ProductAttributeDto {
    private Integer productId;
    Map<String, String> attributes;
}
VariantSqlProvider.class
  public class VariantSqlProvider implements ProviderMethodResolver {
    @SuppressWarnings("unused")
    public static String getProductAttribute(final ProductAttributeDto productAttributeDto) {
        return new SQL() {{
            SELECT("*");
            FROM("ec_product_variant AS pv");
            if (Objects.nonNull(productAttributeDto.getAttributes())) {
                for (Entry<String, String> entry : productAttributeDto.getAttributes().entrySet()) {
                    if(Objects.nonNull(entry.getValue())) {
                        INNER_JOIN(
                                new StringBuilder("ec_attributes AS ")
                                .append(entry.getKey())
                                .append(" ON ")
                                .append(entry.getKey()).append(".id = pv.").append(entry.getKey())
                                .append(" AND ")
                                .append(entry.getKey()).append(".value=#{productAttributeDto.attributes.").append(entry.getKey())
                                .append("}").toString()
                        );
                    } else {
                        WHERE("pv." + entry.getKey() + " IS NULL");
                    }
                }
            }
            if(Objects.nonNull(productAttributeDto.getProductId())) {
                WHERE("pv.product_id = #{productAttributeDto.productId}");
            }
        }}.toString();
    }
}
When I invoke the findByProductAttribute method, I get an error like this
org.apache.juli.logging.DirectJDKLog: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method 'public static java.lang.String com.ecommerce.app.repository.product.sqlprovider.VariantSqlProvider.getProductAttribute(com.ecommerce.app.model.product.ProductAttributeDto)' with specify parameter 'class org.apache.ibatis.binding.MapperMethod$ParamMap'.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'arg0' not found. Available parameters are [productAttributeDto, param1]] with root cause
org.apache.ibatis.binding.BindingException: Parameter 'arg0' not found. Available parameters are [productAttributeDto, param1]
        at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:212)
        at org.apache.ibatis.builder.annotation.ProviderSqlSource.extractProviderMethodArguments(ProviderSqlSource.java:223)
The SQL query I am expecting to generate is:
SELECT *
FROM ec_product_variant AS pv 
INNER JOIN ec_attributes AS color ON color.id = pv.color AND color.value=? 
WHERE (pv.size IS NULL AND pv.product_id = ?)
The query is based on the attributes key-value pair in productAttributeDto
Here mybatis is looking for arg0 instead of productAttributeDto. Can anyone help on this. What am I doing wrong here? Thanks in advance.