如何获取Oracle插入SQL执行结果并在Java GUI中展示?
我来帮你完善这个Oracle INSERT语句执行的GUI程序,让它能把执行状态、影响行数和错误信息都直观展示在界面上~
核心问题分析
你的现有代码已经实现了SQL的批量执行,但缺少两个关键能力:
- 无法捕获SQL执行的影响行数(比如"X行已插入"),也没把执行状态反馈到GUI
- 异常仅打印到控制台,用户在GUI上看不到错误详情
- 数据库操作是耗时任务,直接在事件线程执行会导致GUI卡顿
改进方案(含完整代码)
首先建议在GUI中添加一个JTextArea组件(命名为jTextAreaResult),用来展示执行日志和结果。然后通过SwingWorker后台执行数据库操作,避免阻塞界面,同时收集执行状态和异常信息更新到GUI:
import javax.swing.SwingWorker; import java.io.PrintWriter; import java.io.StringWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Arrays; import java.util.List; private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) { String SQL = jEditorPane1.getText().trim(); if (SQL.isEmpty()) { showResult("⚠️ 请输入有效的SQL语句!"); return; } jEditorPane1.setText(""); // 拆分并过滤空行,避免执行无效SQL String[] arraySQL = Arrays.stream(SQL.split(System.lineSeparator())) .map(String::trim) .filter(line -> !line.isEmpty()) .toArray(String[]::new); // 用SwingWorker后台执行数据库操作,防止GUI冻结 new SwingWorker<Void, String>() { @Override protected Void doInBackground() throws Exception { BasicDataSource dataSource = DatabaseUtility.getDataSource(); try (Connection connection = dataSource.getConnection()) { connection.setAutoCommit(false); // 开启手动事务,保证数据一致性 int totalAffectedRows = 0; publish("🔍 开始执行SQL语句..."); for (String sql : arraySQL) { publish(String.format("📝 正在执行:%s", sql)); try (PreparedStatement ps = connection.prepareStatement(sql)) { // 用executeUpdate获取受影响行数,适合INSERT/UPDATE/DELETE int affectedRows = ps.executeUpdate(); totalAffectedRows += affectedRows; publish(String.format("✅ 执行成功:%d 行已插入/更新", affectedRows)); } catch (SQLException e) { connection.rollback(); // 出错立即回滚所有操作 publish(String.format("❌ 执行失败:%s", e.getMessage())); publish("📋 异常堆栈跟踪:"); // 把堆栈信息转为字符串展示到GUI StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); publish(sw.toString()); throw e; // 终止后续SQL执行 } } connection.commit(); publish(String.format("🎉 所有语句执行完成,共影响 %d 行", totalAffectedRows)); } catch (SQLException e) { publish("💥 数据库连接异常:" + e.getMessage()); } return null; } @Override protected void process(List<String> chunks) { // 在事件调度线程(EDT)中更新GUI,保证线程安全 for (String msg : chunks) { jTextAreaResult.append(msg + System.lineSeparator()); // 自动滚动到最新日志位置 jTextAreaResult.setCaretPosition(jTextAreaResult.getDocument().getLength()); } } }.execute(); } // 辅助方法:快速展示提示信息 private void showResult(String msg) { jTextAreaResult.append(msg + System.lineSeparator()); jTextAreaResult.setCaretPosition(jTextAreaResult.getDocument().getLength()); }
关键优化点说明
- 后台执行:用
SwingWorker把数据库操作放到后台线程,避免GUI卡顿,process方法负责在安全线程更新界面 - 事务控制:手动设置
autoCommit(false),全部SQL执行成功才提交,出错则回滚,避免部分执行导致数据不一致 - 结果反馈:通过
executeUpdate()获取受影响行数,实时展示每一条SQL的执行状态 - 异常可视化:把异常堆栈转为字符串,直接显示在GUI的结果区域,用户无需查看控制台
- 空行过滤:自动过滤拆分后的空行,避免执行无效SQL引发错误
可选:获取Oracle DBMS_OUTPUT信息
如果需要获取Oracle存储过程或脚本的输出信息,可以添加以下辅助方法,并在doInBackground中调用:
// 启用DBMS_OUTPUT private void enableDbmsOutput(Connection conn) throws SQLException { try (PreparedStatement ps = conn.prepareStatement("BEGIN DBMS_OUTPUT.ENABLE(1000000); END;")) { ps.execute(); } } // 获取DBMS_OUTPUT内容 private String getDbmsOutput(Connection conn) throws SQLException { StringBuilder sb = new StringBuilder(); try (CallableStatement cs = conn.prepareCall("DECLARE " + " line VARCHAR2(255); " + " status INTEGER; " + "BEGIN " + " DBMS_OUTPUT.GET_LINE(line, status); " + " :line := line; " + " :status := status; " + "END;")) { cs.registerOutParameter("line", java.sql.Types.VARCHAR); cs.registerOutParameter("status", java.sql.Types.INTEGER); do { cs.execute(); String line = cs.getString("line"); int status = cs.getInt("status"); if (status == 0) { sb.append(line).append(System.lineSeparator()); } } while (cs.getInt("status") == 0); } return sb.toString(); }
调用位置:在获取connection后启用,执行完所有SQL后获取并发布:
enableDbmsOutput(connection); // ... 执行所有SQL后 ... String dbmsOutput = getDbmsOutput(connection); if (!dbmsOutput.isEmpty()) { publish("📌 Oracle输出信息:"); publish(dbmsOutput); }
内容的提问来源于stack exchange,提问作者nullPointer
相关产品推荐
相关产品推荐

