Mybatis异常解决之:java.sql.SQLException: Parameter index out of range

MyBatis模糊查询异常
本文解决了一个在MyBatis中进行模糊查询时出现的参数索引超出范围的异常问题,详细介绍了错误的原因及正确的配置方式。

mybatis使用过程中遇到下面一个异常:

org.springframework.dao.TransientDataAccessResourceException:
### Error querying database.  Cause: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).
### The error may exist in conf/entitymap/diseaseMapper.xml
### The error may involve diseaseMapper.queryCountByName-Inline
### The error occurred while setting parameters
### SQL: select         count(1)         from tb_disease where 1=1                       AND name like CONCAT('%','?','%')
### Cause: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).
; SQL []; Parameter index out of range (1 > number of parameters, which is 0).; nested exception is java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).
  at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:106) ~[spring-jdbc-3.2.9.RELEASE.jar:3.2.9.RELEASE]
  at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) ~[spring-jdbc-3.2.9.RELEASE.jar:3.2.9.RELEASE]
  at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) ~[spring-jdbc-3.2.9.RELEASE.jar:3.2.9.RELEASE]
  at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) ~[spring-jdbc-3.2.9.RELEASE.jar:3.2.9.RELEASE]
  at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73) ~[mybatis-spring-1.2.2.jar:1.2.2]
  at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:371) ~[mybatis-spring-1.2.2.jar:1.2.2]
  at com.sun.proxy.$Proxy70.selectOne(Unknown Source) ~[na:na]
  at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:163) ~[mybatis-spring-1.2.2.jar:1.2.2]

根据错误信息 

select count(1) from tb_disease where 1=1 AND name like CONCAT('%','?','%')

找到相应配置如下,发现原来是#{diseaseName}用法有误:CONCAT('%','#{diseaseName}','%')

mapper文件配置如下:

select id="queryCountByName" resultType="java.lang.Long" parameterType="java.util.HashMap">
        select
        count(1)
        from tb_disease where 1=1
        <if test="diseaseName!=null and diseaseName!=''">
            AND name like CONCAT('%','#{diseaseName}','%')
        </if>
    </select>

在mapper文件中使用#占位符传参时,一定不要在两侧添加引号,否则会导致参数解析异常。

正确的配置方式应该是以下这样:

<select id="queryCountByName" resultType="java.lang.Long" parameterType="java.util.HashMap">
        select
        count(1)
        from tb_disease where 1=1
        <if test="diseaseName!=null and diseaseName!=''">
            AND name like CONCAT('%',#{diseaseName},'%')
        </if>
    </select>

另外,或者可以把#改成$,但是mapper文件中使用$会有sql注入漏洞,所以不建议使用!

附:Mybatis模糊查询MySQL中记录的的常用三种方法

这个异常: ``` Caused by: java.sql.SQLException: Parameter index out of range (10 > number of parameters, which is 9) ``` 表示你在执行一条 SQL 语句时,**尝试设置了第 10 个参数(索引为10)**,但实际 SQL 中只定义了 **9 个参数占位符**(即 `?`),导致参数索引超出范围。 --- ## 🧠 原因分析 ### 常见原因包括: 1. **SQL 语句中的参数个数与 Java 代码传入的参数个数不一致** 2. 使用了 `@Param("xxx")` 注解,但 SQL 中引用了不存在的参数 3. 动态 SQL(如 `<if>`)导致某些字段和值没有被插入,但 MyBatis 仍然尝试绑定这些参数 4. 使用了错误的参数绑定方式,如 `Map` 中 key 错误,导致某些参数未被使用 --- ## ✅ 示例场景及修复 ### ✅ 场景一:参数数量不匹配 #### 错误示例: ```xml <insert id="insertData"> INSERT INTO users (id, name, age, gender, city, country, phone, email, birth_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) </insert> ``` 上面 SQL 中有 **9 个 `?`**,但 Java 代码传入了 10 个参数,就会报错。 #### 修复方法: 确保参数个数与 SQL 中的 `?` 数量一致。 --- ### ✅ 场景二:使用命名参数但字段名不一致 #### Mapper 接口: ```java void insertData(@Param("user") User user); ``` #### 错误 XML: ```xml <insert id="insertData"> INSERT INTO users (id, name, age, gender, city, country, phone, email, birth_date) VALUES ( #{user.id}, #{user.name}, #{user.age}, #{user.gender}, #{user.city}, #{user.country}, #{user.phone}, #{user.email}, #{user.birthDate} ) </insert> ``` 如果你传入的 `User` 对象中还有一个字段 `createTime`,但在 SQL 中没有使用它,MyBatis 不会报错,但如果你在 XML 中错误引用了 `#{user.createTime}`,而该字段不存在或为 `null`,可能会导致参数绑定异常。 --- ### ✅ 场景三:动态 SQL 导致字段与值不匹配 ```xml <insert id="insertData"> INSERT INTO users <trim prefix="(" suffix=")" suffixOverrides=","> <if test="user.id != null">id,</if> <if test="user.name != null">name,</if> <if test="user.age != null">age,</if> ... </trim> VALUES <trim prefix="(" suffix=")" suffixOverrides=","> <if test="user.id != null">#{user.id},</if> <if test="user.name != null">#{user.name},</if> <if test="user.age != null">#{user.age},</if> ... </trim> </insert> ``` 如果某些字段未被插入,但你仍然尝试传入了对应的值,就会导致参数绑定异常。 #### 修复方法: 确保 `<if>` 条件下字段和值是成对出现的。 --- ## ✅ 解决方案汇总 | 问题类型 | 解决方法 | |----------|----------| | 参数数量不一致 | 检查 SQL 中的 `?` 数量与 Java 传入参数数量 | | 参数名错误 | 使用 `@Param` 注解并检查 XML 中的字段引用 | | 动态 SQL 不匹配 | 确保 `<if>` 条件下的字段与值成对出现 | | 参数为 null | 使用 `jdbcType=XXX` 避免 MyBatis 推断失败 | --- ## ✅ 示例修复:使用命名参数 + 明确字段绑定 ### Mapper 接口: ```java void insertData(@Param("user") User user); ``` ### XML: ```xml <insert id="insertData"> INSERT INTO users (id, name, age, gender, city, country, phone, email, birth_date, create_time) VALUES ( #{user.id, jdbcType=INTEGER}, #{user.name, jdbcType=VARCHAR}, #{user.age, jdbcType=INTEGER}, #{user.gender, jdbcType=VARCHAR}, #{user.city, jdbcType=VARCHAR}, #{user.country, jdbcType=VARCHAR}, #{user.phone, jdbcType=VARCHAR}, #{user.email, jdbcType=VARCHAR}, #{user.birthDate, jdbcType=DATE}, #{user.createTime, jdbcType=TIMESTAMP} ) </insert> ``` --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值