文章目录

  • 1. 复现问题
  • 2. 分析问题
  • 3. 解决问题
  • 4. 出现该错误的其他可能

1. 复现问题

今天在调试接口时,突然报出如下错误:

org.springframework.jdbc.BadSqlGrammarException: ### Error querying database.Cause: java.sql.SQLException: No value specified for parameter 1### The error may exist in com/test/cloud/lowcode/mapper/AppCustomComponentVersionMapper.java (best guess)### The error may involve com.test.cloud.lowcode.mapper.AppCustomComponentVersionMapper.getMaxVersion-Inline### The error occurred while setting parameters### SQL: SELECT IFNULL(MAX(version),1.0) from app_custom_component_version WHERE app_custom_component_id = " />;### Cause: java.sql.SQLException: No value specified for parameter 1; bad SQL grammar []; nested exception is java.sql.SQLException: No value specified for parameter 1at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:101)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:79)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:79)at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:91)at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:441)at com.sun.proxy.$Proxy157.selectOne(Unknown Source)at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:160)at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:89)at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148)at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)at com.sun.proxy.$Proxy182.getMaxVersion(Unknown Source)at com.test.cloud.lowcode.service.AppCustomComponentService.getMaxVersion(AppCustomComponentService.java:35)at com.test.cloud.lowcode.service.AppCustomComponentService$$FastClassBySpringCGLIB$$a271163e.invoke(<generated>).....

Error querying database. Cause: java.sql.SQLException: No value specified for parameter 1的错误。

2. 分析问题

正赶上最近ChatGPT很火,于是借助ChatGPT来解决我的问题,如下所示:

This error generally occurs when a parameter is not supplied in the query or when an incorrect number of parameters are provided. To fix this error, check that the correct number of parameters are supplied and that all parameters have a value specified. Additionally, ensure that the values passed as parameters match the data type of the associated column.

可惜的是,ChatGPT给出英文的结果,不妨将其翻译成中文,如下所示:

当查询中未提供参数或提供的参数数量不正确时,通常会发生此错误。若要修复此错误,请检查是否提供了正确数量的参数,以及是否指定了所有参数的值。此外,请确保作为参数传递的值与关联列的数据类型匹配。

根据翻译结果可知未提供参数或提供的参数数量不正确

再回头看我的错误栈信息,如下图所示:

定位是AppCustomComponentVersionMapper类的getMaxVersion方法出现了错误,如下代码所示:

@Mapperpublic interfaceAppCustomComponentVersionMapper extends BaseMapper<AppCustomComponentVersion> {/** * 获取当前组件下最大的版本号 * * @author super先生 * @datetime 2023/2/17:16:53 * @param componentId 组件ID * @return */@Select("SELECT "+ " IFNULL( MAX( version ), 1.0 ) "+ "FROM "+ "app_custom_component_version "+ "WHERE "+ "app_custom_component_id = " />+ "AND deleted = 0")float getMaxVersion(@Param("componentId") Long componentId);}

仔细排查@Select注解中的SQL语句,突然发现app_custom_component_id = ?这里语法错误。

我使用的是mybatis框架,即便参数componentId有实际值,mybatis将也无法将值传进去。

因为mybatis表示占位符的语法是#{变量},而非问号(?),因而,mybatis生成的SQL语句如下:

SELECTIFNULL(MAX(version), 1.0)FROMapp_custom_component_versionWHEREapp_custom_component_id = ?AND deleted = 0

这样的SQL语句,jdbc无法执行(mybatis的底层是jdbc),才会报出 No value specified for parameter 1错误。

3. 解决问题

既然知道我的变量语法错误,按照mybatis的语法修改即可,

也就是将app_custom_component_id = ?修改为app_custom_component_id = #{componentId},如下代码所示:

@Mapperpublic interfaceAppCustomComponentVersionMapper extends BaseMapper<AppCustomComponentVersion> {/** * 获取当前组件下最大的版本号 * * @author super先生 * @datetime 2023/2/17:16:53 * @param componentId 组件ID * @return */@Select("SELECT "+ " IFNULL( MAX( version ), 1.0 ) "+ "FROM "+ "app_custom_component_version "+ "WHERE "+ "app_custom_component_id = #{componentId} "+ "AND deleted = 0")float getMaxVersion(@Param("componentId") Long componentId);}

此时,重新启动spring boot服务,调用getMaxVersion方法,SQL即可成功运行。

4. 出现该错误的其他可能

正如上文所述,出现这种错误,一般情况下是变量语法的错误,导致框架无法获取到实参。

因而,我们在开发时,一定要注意变量语法。

如果你使用的是jdbcexecuteQuery()方法,一定不要忘了传参,如下图所示:

你会看到:statement.setString(1,username)已被注释,自然无参数可传。

因而,我们需要取消注释,如下图所示:

jdbc才能正常执行sql语句。