jQuery Ajax+JSP批量删除数据触发ORA-01722错误求助
解决批量删除时ORA-01722无效数字的问题
这个错误的根源很明确:前端传递的是逗号拼接的ID字符串,但后端错误地将其当作单个ID处理,导致Oracle无法把带逗号的字符串转换成数字类型。咱们一步步拆解问题并修复:
问题定位
- 前端AJAX代码中,你用
.join()把选中的ID拼成了一个字符串(比如"1,2,3"),然后作为id参数传递给后端。 - 后端用
request.getParameterValues("id")获取参数,但这个方法是用来获取同名多参数的(比如表单里多个同名checkbox的原生提交场景),而你这里只传了一个逗号分隔的字符串,所以checkedid数组里只有一个元素:"1,2,3"。 - 之后循环时,你把这个带逗号的字符串传给
pst.setString(1, check),执行DELETE FROM student_signup WHERE (STUDENT_ID = ?)时,Oracle会尝试把"1,2,3"转换成数字,自然就抛出ORA-01722错误了。
修复方案(两种可选)
方案一:前端传递数组,后端正确接收
修改前端AJAX代码,直接传递ID数组,不用拼接成字符串,jQuery会自动处理为多参数形式:
$(document).ready(function () { $('#trash').click(function (event) { event.preventDefault(); // 直接获取ID数组,跳过join()步骤 var ids = $('.checkitem:checked').map(function () { return $(this).val(); }).get(); if(ids.length > 0) { if (confirm("Are you sure you want to delete these records?")) { $.ajax({ url: 'TeacherStudentDeletion.jsp', type: 'POST', // 传递数组,jQuery会自动转为id=1&id=2&id=3的格式 data: {id: ids}, success: function (result) { $('tbody').html(result); }, error: function () { alert('Error while deletion. Please try again.'); } }) } else { return false; } } else { alert("Please select the user first."); } }) });
后端代码保持request.getParameterValues("id")的逻辑即可,现在checkedid数组里会是每个单独的ID字符串,循环执行删除时就能正确匹配数字类型的STUDENT_ID了。
方案二:后端处理逗号分隔的字符串(更高效的批量删除)
如果不想修改前端,可以在后端把接收到的逗号分隔字符串拆分成数组,并且用批量SQL优化删除操作(避免多次执行DELETE,提升性能):
修改后端JSP代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.sql.*" %> <% boolean success = false; Connection con = null; PreparedStatement pst = null; ResultSet rs = null; try { // 用getParameter获取单个逗号分隔的字符串 String idStr = request.getParameter("id"); if(idStr != null && !idStr.isEmpty()) { String[] checkedid = idStr.split(","); Class.forName("oracle.jdbc.driver.OracleDriver"); con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "SUNILREDDY", "oracle"); // 使用批量PreparedStatement,安全且高效 String s1 = "DELETE FROM student_signup WHERE STUDENT_ID = ?"; pst = con.prepareStatement(s1); for (String id : checkedid) { // 转为int类型,匹配数据库字段的数字类型 pst.setInt(1, Integer.parseInt(id)); pst.addBatch(); } int[] results = pst.executeBatch(); // 检查是否有成功删除的记录 for(int res : results) { if(res > 0) { success = true; break; } } } if (success) { String s2 = "select * from student_signup"; pst = con.prepareStatement(s2); rs = pst.executeQuery(); while (rs.next()) { %> <tr> <th> <div class="pretty p-icon p-curve p-has-indeterminate"> <input type="checkbox" class="checkitem" value="<%= rs.getInt("STUDENT_ID") %>" name="check"/> <div class="state"> <i class="icon mdi mdi-check"></i> <label>Check</label> </div> <div class="state p-is-indeterminate"> <i class="icon mdi mdi-minus"></i> <label>Indeterminate</label> </div> </div> </th> <th scope="row"><%= rs.getInt("ROLLNO") %></th> <th><%= rs.getInt("STUDENT_ID") %></th> <td><%= rs.getString("STUDENT_FIRSTNAME") %></td> <td><%= rs.getString("STUDENT_LASTNAME") %></td> <td><%= rs.getString("COURSE_NAME") %></td> </tr> <% } } } catch (Exception e) { e.printStackTrace(); } finally { // 必须关闭数据库资源,防止连接泄漏 try { if(rs != null) rs.close(); } catch(Exception e) {} try { if(pst != null) pst.close(); } catch(Exception e) {} try { if(con != null) con.close(); } catch(Exception e) {} } %>
额外优化建议
- 把数据库连接代码抽成独立工具类,不要直接写在JSP里,便于维护和复用。
- 永远在
finally块中关闭数据库资源,避免内存泄漏。 - 方案二的批量PreparedStatement能有效防止SQL注入,推荐优先使用。
内容的提问来源于stack exchange,提问作者Sunil Reddy
相关产品推荐
相关产品推荐

