JDBC中依次执行查询与插入报错的解决方案
问题描述
我是JDBC新手,想要在pc表中指定model不存在时插入新记录,但执行两个查询时编译器报错:
"Can not issue executeUpdate() or executeLargeUpdate() for SELECTs"
以下是我的代码:
public class AskUser5 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Manufacturer:"); String Manufacturer = sc.nextLine(); System.out.print("Model:"); String model = sc.nextLine(); System.out.print("Speed:"); int speed = sc.nextInt(); System.out.print("Ram:"); int ram = sc.nextInt(); System.out.print("HD Size:"); int hd_size = sc.nextInt(); System.out.print("Price:"); int price = sc.nextInt(); Connection con = Getconnection.getconnection(); String query = "select * from pc"; boolean flag = false; try { PreparedStatement ps = con.prepareStatement(query); ResultSet rs = ps.executeQuery(); while(rs.next()) { if(model.equals(rs.getString("model"))) { System.out.println("Model Aviable"); flag=true; } } if(flag == false) { System.out.println("There's no such model here"); PreparedStatement ps2 = con.prepareStatement("INSERT into pc (model,speed,ram,hd,price) VALUES (?,?,?,?,?)"); ps2.setString(1, model); ps2.setInt(2, speed); ps2.setInt(3, ram); ps2.setInt(4, hd_size); ps2.setInt(5, price); ps.executeUpdate(); } } catch (SQLException e) { System.out.println("Error due to " + e.getMessage()); } } }
解决方法
1. 修复直接报错的代码问题
你报错的核心原因是调用了错误的Statement对象的executeUpdate()方法:你创建了用于插入操作的ps2,但最后执行的是绑定SELECT语句的ps.executeUpdate(),自然会触发报错。
把代码里的ps.executeUpdate();改成ps2.executeUpdate();,就能解决这个直接的错误。
2. 优化查询逻辑(提升效率)
你当前查询全表再遍历判断的做法效率很低,尤其是表数据量大的时候。可以直接用SQL精准查询指定model是否存在,无需扫描全表:
// 替换原来的全表查询逻辑 String checkQuery = "SELECT COUNT(*) FROM pc WHERE model = ?"; PreparedStatement checkPs = con.prepareStatement(checkQuery); checkPs.setString(1, model); ResultSet rs = checkPs.executeQuery(); rs.next(); int count = rs.getInt(1); flag = count > 0; // 存在则count>0,flag为true
3. 原子化操作(避免并发重复插入)
如果程序可能有多线程同时操作,先查询再插入的两步操作会有并发风险:两个线程可能同时查到model不存在,然后都执行插入,导致重复数据。
可以用SQL的INSERT ... SELECT ...语法,把判断和插入合并成一条原子性语句,由数据库保证操作的唯一性:
// 直接执行这条SQL,无需提前查询 String insertSql = "INSERT INTO pc (model, speed, ram, hd, price) " + "SELECT ?, ?, ?, ?, ? " + "WHERE NOT EXISTS (SELECT 1 FROM pc WHERE model = ?)"; PreparedStatement ps = con.prepareStatement(insertSql); ps.setString(1, model); ps.setInt(2, speed); ps.setInt(3, ram); ps.setInt(4, hd_size); ps.setInt(5, price); ps.setString(6, model); // 对应最后一个判断用的model参数 int affectedRows = ps.executeUpdate(); if (affectedRows > 0) { System.out.println("新记录插入成功"); } else { System.out.println("Model已存在"); }
这种方式减少了JDBC和数据库的交互次数,同时避免了并发场景下的重复数据问题。
4. 资源释放建议(避免泄漏)
作为JDBC新手,记得要关闭ResultSet、PreparedStatement、Connection这些资源,推荐用try-with-resources语法自动管理资源,避免手动关闭遗漏:
// 示例:用try-with-resources包裹所有资源 try (Connection con = Getconnection.getconnection(); PreparedStatement ps = con.prepareStatement(insertSql)) { // 设置参数、执行操作的代码写在这里 } catch (SQLException e) { System.out.println("Error due to " + e.getMessage()); }
内容的提问来源于stack exchange,提问作者Lycan
相关产品推荐
相关产品推荐

