简体   繁体   English

Select Provider Mybatis 错误:找不到参数'arg0'。 可用参数为 [productAttributeDto, param1]

[英]Select Provider Mybatis Error: Parameter 'arg0' not found. Available parameters are [productAttributeDto, param1]

I am using Mybatis with the spring boot application.我将 Mybatis 与 spring 引导应用程序一起使用。 Where I used to generate MySql query using ProviderMethodResolver.我曾经使用 ProviderMethodResolver 生成 MySql 查询。 My application supports mybatis annotation processor and XML processor.我的应用程序支持 mybatis 注释处理器和 XML 处理器。

To achieve that I used this Mybatis configuration:为了实现这一点,我使用了这个 Mybatis 配置:

In appication.properties file在 appication.properties 文件中

mybatis.mapper-locations=classpath*:/repository/**/*Repository.xml

and a MybatisConfiguration.java和一个 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的实现之外,一切( @Select, @Insert, @ResultMap )似乎工作正常。

SelectProvider Implemetation is SelectProvider 实现是

VariantRepository.java 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我正在使用org.apache.ibatis.annotations.Param

ProductAttributeDto.java产品属性Dto.java

@Data
public class ProductAttributeDto {

    private Integer productId;

    Map<String, String> attributes;
}

VariantSqlProvider.class 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当我调用findByProductAttribute方法时,我收到这样的错误

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:我期望生成的 SQL 查询是:

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该查询基于 productAttributeDto 中的属性键值对

Here mybatis is looking for arg0 instead of productAttributeDto.这里 mybatis 是在寻找 arg0 而不是 productAttributeDto。 Can anyone help on this.任何人都可以帮助解决这个问题。 What am I doing wrong here?我在这里做错了什么? Thanks in advance.提前致谢。

The error is caused by the parameter name mismatch between the mapper method and the provider method.该错误是由于mapper方法和provider方法的参数名称不匹配造成的。

  • The param name of the mapper method is specified by @Param annotation ie productAttributeDto .映射器方法的参数名称由@Param注释指定,即productAttributeDto
  • The param name is not specified in the provider method, so the default name arg0 is used.提供程序方法中未指定参数名称,因此使用默认名称arg0

These names must match.这些名称必须匹配。


There are two solutions.有两种解决方案。

  1. Add @Param annotation on the provider method parameter.在提供者方法参数上添加@Param注释。
  2. Build your application with -parameters compiler option enabled.在启用-parameters编译器选项的情况下构建您的应用程序。

The solution 1 is pretty straightforward.解决方案 1 非常简单。

public static String getProductAttribute(
  @Param("productAttributeDto") final ProductAttributeDto productAttributeDto) {

The solution 2 depends on how you build your application.解决方案 2 取决于您如何构建应用程序。

If you use Maven, you may need to configure maven-compiler-plugin in the pom.xml.如果使用Maven,可能需要在pom.xml中配置maven-compiler-plugin。 eg例如

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <compilerArgs>
          <arg>-parameters</arg>
        </compilerArgs>
      </configuration>
    </plugin>

When using IDE, you might need to configure the build setting.使用 IDE 时,您可能需要配置构建设置。

This way, MyBatis can retrieve the parameter name from the method signature, so you don't need to use @Param annotation (you can still use @Param if you want, though).这样,MyBatis 可以从方法签名中检索参数名称,因此您不需要使用@Param注解(不过,如果需要,您仍然可以使用@Param )。

As a result, the mapper method can be simpler...结果,mapper方法可以更简单......

@SelectProvider(type = VariantSqlProvider.class, method = "getProductAttribute")
VariantDto findByProductAttribute(ProductAttributeDto productAttributeDto);

...and the provider method in your question should work as-is. ...并且您问题中的提供者方法应该按原样工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM