使用Spring MVC JdbcTemplate查询数据库时遇DataIntegrityViolationException求助
嘿,这个问题我之前排查过类似的,咱们先从异常信息入手拆解:
org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [select * from cyberabadpolice where fir_date between '2020-01-01' and '2020-12-31' and current_status='UI']; The column index is out of range: 1, number of columns: 0.; nested exception is org.postgresql.util.PSQLException: The column index is out of range: 1, number of columns: 0.
这个异常的核心是PostgreSQL驱动找不到你要绑定的参数位置——你提到业务需要接收用户的两个输入参数,但你的SQL语句里全是硬编码的固定值('2020-01-01'、'2020-12-31'、'UI'),没有预留任何参数占位符?。当你调用JdbcTemplate的查询方法并传入用户参数时,框架会尝试把参数绑定到SQL的第1个占位符上,但SQL里根本没有?,自然就报“列索引越界”了。
正确的解决步骤:
用占位符替换SQL中的硬编码参数
根据你需要接收的两个用户输入参数,调整SQL语句,用?代替固定值。比如:- 如果两个参数是「起始日期」和「结束日期」:
select * from cyberabadpolice where fir_date between ? and ? - 如果两个参数是「指定日期范围」和「当前状态」:
select * from cyberabadpolice where fir_date between '2020-01-01' and '2020-12-31' and current_status = ?
(根据你的实际业务需求选择对应写法,核心是把用户输入的部分换成
?)- 如果两个参数是「起始日期」和「结束日期」:
调用JdbcTemplate时传入对应参数
确保参数的数量、顺序和SQL里的占位符完全匹配,示例代码如下:// 假设你的实体类是CyberabadPolice String sql = "select * from cyberabadpolice where fir_date between ? and ?"; List<CyberabadPolice> result = jdbcTemplate.query( sql, new Object[]{userInputStartDate, userInputEndDate}, // 对应用户输入的两个参数 new BeanPropertyRowMapper<>(CyberabadPolice.class) );
额外提醒:
- 千万别直接在SQL里拼接用户输入的字符串,不仅容易触发这类参数绑定错误,还会带来SQL注入的安全风险,用占位符是最安全规范的做法。
- 这里的
DataIntegrityViolationException有点误导人,它本质不是数据库数据完整性的问题(比如主键冲突、非空约束违反),而是底层JDBC PreparedStatement的参数绑定失败导致的,根源是SQL写法不对。
内容的提问来源于stack exchange,提问作者Mantramurthy saishankar




