You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Oracle插入SQL执行结果并在Java GUI中展示?

我来帮你完善这个Oracle INSERT语句执行的GUI程序,让它能把执行状态、影响行数和错误信息都直观展示在界面上~

核心问题分析

你的现有代码已经实现了SQL的批量执行,但缺少两个关键能力:

  1. 无法捕获SQL执行的影响行数(比如"X行已插入"),也没把执行状态反馈到GUI
  2. 异常仅打印到控制台,用户在GUI上看不到错误详情
  3. 数据库操作是耗时任务,直接在事件线程执行会导致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());
}

关键优化点说明

  1. 后台执行:用SwingWorker把数据库操作放到后台线程,避免GUI卡顿,process方法负责在安全线程更新界面
  2. 事务控制:手动设置autoCommit(false),全部SQL执行成功才提交,出错则回滚,避免部分执行导致数据不一致
  3. 结果反馈:通过executeUpdate()获取受影响行数,实时展示每一条SQL的执行状态
  4. 异常可视化:把异常堆栈转为字符串,直接显示在GUI的结果区域,用户无需查看控制台
  5. 空行过滤:自动过滤拆分后的空行,避免执行无效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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:32:30