org.postgresql.util.PSQLException: 栏位索引超过许可范围:1,栏位数:0。

如果你的SQL语句在数据库中查询的时候是没问题的,但是把他写到代码中的时候如果报org.postgresql.util.PSQLException: 栏位索引超过许可范围:1,栏位数:0。这个错误,你就可以考虑是不是传值的地方加了引号(包括单引号和双引号),就在下图中红色箭头的地方,也就是传值的地方

就删掉这个引号,再次执行,就没有再次出现这个问题了;


另外的几个传值问题:

1. #方式能够很大程度上防止sql注入,而$无法防止sql的注入;

2. $一般用于传入数据库对象,例如传入表名;

3. mybatis排序时使用order by动态参数时是使用$而不是#;

总之能用# 的时候 就不用 $ 这就好了;


<think>我们遇到了一个MyBatis的异常,主要问题是设置参时出错。异常信息指出:在设置参时,由于JdbcType为null,导致无法为非空参设置值,最终引发PSQLException栏位索引超过许可范围1栏位0)。这个错误通常发生在使用PostgreSQL数据库时。 ### 错误分析: 1. **根本原因**:当MyBatis尝试设置一个非空参(这里是一个String类型的参)时,由于没有指定`jdbcType`,而数据库驱动无法处理这种情况(特别是当参值为null时,但这里参值可能不为null,而是类型映射问题)。 2. **关键提示**:异常信息中明确提到`Try setting a different JdbcType for this parameter`,所以我们需要在映射文件中为参指定`jdbcType`。 ### 解决方案: 在SQL映射文件中,为可能为null的String类型参指定`jdbcType`。例如: ```xml <insert id="insertLog"> INSERT INTO log_table (message) VALUES (#{points, jdbcType=VARCHAR}) </insert> ``` 或者,如果参是基本类型(如String)且可能为null,则必须指定`jdbcType`。 ### 其他可能原因及解决: 1. **参量不匹配**:检查SQL语句中的参占位符量是否与方法参量一致。异常中提到“栏位索引超过许可范围1栏位0”,可能是SQL语句中使用了参占位符,但实际传入的参为空(或参0)导致。 - 检查方法调用时传入的参是否正确。 - 检查Mapper接口方法的参列表与XML中的占位符是否匹配。 2. **参名不匹配**(当使用多个参时): - 如果方法有多个参,必须使用`@Param`注解指定参名,以便在XML中使用。 - 例如: ```java void insertLog(@Param("points") String points, @Param("other") String other); ``` 在XML中: ```xml INSERT INTO log_table (message, other) VALUES (#{points, jdbcType=VARCHAR}, #{other, jdbcType=VARCHAR}) ``` 3. **全局配置**:在MyBatis配置文件中,可以设置`jdbcTypeForNull`,指定当参为null时默认使用的jdbcType。例如: ```xml <settings> <setting name="jdbcTypeForNull" value="VARCHAR"/> </settings> ``` 这样,当遇到null参且未指定jdbcType时,会使用VARCHAR(但根据异常信息,这里参可能不是null,而是驱动无法处理未指定jdbcType的情况)。 ### 针对PostgreSQL的注意事项: PostgreSQL驱动对类型要求比较严格。当MyBatis无法推断出参的jdbcType时(比如参为null),就会出错。因此,建议: - 对所有可能为null的参都显式指定`jdbcType`。 - 对于String类型,指定`jdbcType=VARCHAR`。 ### 示例修正: 假设原始映射文件中的SQL可能是这样的: ```xml <insert id="insertLog"> INSERT INTO log_table (message) VALUES (#{points}) </insert> ``` 修正为: ```xml <insert id="insertLog"> INSERT INTO log_table (message) VALUES (#{points, jdbcType=VARCHAR}) </insert> ``` ### 总结: 这个错误通常是由于MyBatis在设置参时无法确定jdbcType(特别是当参值为null时)导致的。通过显式指定`jdbcType`可以解决。同时,检查参传递是否正确,避免参量不匹配。 §§相关问题§§ 1. MyBatis中如何全局配置jdbcTypeForNull以处理null参? 2.PostgreSQL中使用MyBatis时,处理String类型参还有哪些特殊注意事项? 3. 除了指定jdbcType,还有哪些方法可以解决“Could not set parameters”异常? 4. 当MyBatis抛出TypeException时,通常的排查步骤是什么?</think>### 问题分析 该异常是 MyBatis 操作 PostgreSQL 数据库时出现的类型映射错误,核心问题在于: 1. **参类型不匹配**:MyBatis 无法将 Java `String` 类型正确映射到 PostgreSQL 的 JDBC 类型 2. **空值处理缺失**:未指定 `jdbcType` 导致处理非空参时出错 3. **索引越界**:`栏位索引超过许可范围` 表明 SQL占位符与传入参量不匹配 ### 解决方案 #### 1. 显式指定 jdbcType(关键修复) 在参映射中添加 `jdbcType=VARCHAR`: ```xml <update id="updatePoints"> UPDATE user_table SET points = #{points, jdbcType=VARCHAR} <!-- 修复点 --> WHERE user_id = #{userId} </update> ``` #### 2. 检查参映射一致性 确保 Mapper 接口与 XML 参名匹配: ```java // Mapper 接口方法 void updatePoints(@Param("points") String points, @Param("userId") Long userId); ``` #### 3. 全局配置 jdbcTypeForNull 在 `mybatis-config.xml` 中添加: ```xml <settings> <!-- 处理空值类型映射 --> <setting name="jdbcTypeForNull" value="VARCHAR"/> </settings> ``` #### 4. PostgreSQL 特殊处理 在连接字符串中添加类型强制声明: ```diff jdbc:postgresql://localhost/db? + &stringtype=unspecified ``` #### 5. 验证 SQL 语法 检查 PostgreSQL 的列类型是否支持字符串: ```sql ALTER TABLE user_table ALTER COLUMN points TYPE VARCHAR(50); -- 确保列类型为字符串 ``` ### 错误原因深度解析 | 异常信息片段 | 含义 | |---------------------------------------|----------------------------------------------------------------------| | `Could not set parameters` | MyBatis 类型处理器失败 | | `JdbcType null` | 未声明 JDBC 类型 | | `Error setting non null for parameter`| 尝试设置非空值时类型映射失败 | | `PSQLException: 栏位索引超过许可范围` | 参量不匹配(通常因参名为空或占位符量错误) | ### 预防措施 1. **始终声明 jdbcType** ```xml <!-- 所有字符串参都应添加 --> #{param, jdbcType=VARCHAR} ``` 2. **启用 MyBatis 日志** ```xml <settings> <setting name="logImpl" value="SLF4J"/> </settings> ``` 3. **使用参验证工具** ```java SqlSessionFactory.getConfiguration().getMappedStatement(id).getBoundSql(parameterObject) ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值