java - 选择提供者 Mybatis 错误:找不到参数 'arg0'。可用参数为 [productAttributeDto, param1]
问题描述
我正在将 Mybatis 与 Spring Boot 应用程序一起使用。我曾经使用 ProviderMethodResolver 生成 MySql 查询的地方。我的应用程序支持 mybatis 注解处理器和 XML 处理器。
为了实现这一点,我使用了这个 Mybatis 配置:
在 appication.properties 文件中
mybatis.mapper-locations=classpath*:/repository/**/*Repository.xml
和一个 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);
}
};
}
}
使用上述配置,一切(@Select, @Insert, @ResultMap
)似乎工作正常,除了@SelectProvider
.
SelectProvider 实现是
VariantRepository.java
@Mapper
public interface VariantRepository {
@SelectProvider(type = VariantSqlProvider.class, method = "getProductAttribute")
VariantDto findByProductAttribute(@Param("productAttributeDto") ProductAttributeDto productAttributeDto);
}
我在用
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();
}
}
当我调用该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)
我期望生成的 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 = ?)
该查询基于 productAttributeDto 中的属性键值对
这里 mybatis 是在寻找 arg0 而不是 productAttributeDto。任何人都可以帮助解决这个问题。我在这里做错了什么?提前致谢。
解决方案
该错误是由于mapper方法和provider方法的参数名称不匹配造成的。
- 映射器方法的参数名称由
@Param
注释指定,即productAttributeDto
。 - 提供程序方法中未指定参数名称,因此使用默认名称
arg0
。
这些名称必须匹配。
有两种解决方案。
- 在提供者方法参数上添加
@Param
注释。 -parameters
在启用编译器选项的情况下构建您的应用程序。
解决方案 1 非常简单。
public static String getProductAttribute(
@Param("productAttributeDto") final ProductAttributeDto productAttributeDto) {
解决方案 2 取决于您如何构建应用程序。
如果使用 Maven,可能需要在 pom.xml 中配置 maven-compiler-plugin。例如
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
使用 IDE 时,您可能需要配置构建设置。
这样,MyBatis 可以从方法签名中检索参数名称,因此您不需要使用@Param
注解(@Param
不过,如果需要,您仍然可以使用)。
结果,mapper方法可以更简单......
@SelectProvider(type = VariantSqlProvider.class, method = "getProductAttribute")
VariantDto findByProductAttribute(ProductAttributeDto productAttributeDto);
...并且您问题中的提供者方法应该按原样工作。
推荐阅读
- angular - 在 angular5 中订阅和获取来自 SNS 的通知
- r - 根据 R 中性别的分布类型替换 NA
- spring-boot - 如何在 Spring Boot 项目的服务中访问实体管理器?
- reactjs - 问 React:类约定的功能
- r - generate variable based on first occurrence of a value
- linux - 是否可以查看由 execute_process 运行的命令的实时输出?
- asp.net-web-api - 如何在 Visual Studio 中将类库项目转换为 Web API 项目?
- match - $match 在 mongoose 5.6+ 中找不到 objectID
- javascript - JavaScript - 变量/对象同时作为字符串和函数
- java - 大规模的 Firebase 管理员 Java 客户端