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

数据库表创建失败求助:基于PreparedStatement与事务的Java代码排查

数据库表创建失败及数据导入问题排查修复

问题场景

练习使用PreparedStatement与事务,需创建n012345_Accounts表并从Accounts.txt导入数据,运行代码时控制台返回unable to create new table for accounts,无法完成表创建。

核心错误点及修复方案

1. DDL语句执行方法错误

  • 问题:创建表属于DDL语句,不能用executeQuery()执行(该方法仅用于SELECT等返回结果集的查询语句),会直接抛出SQLException。
  • 修复:改用executeUpdate()执行建表语句,无需ResultSet接收结果:
    stmt.executeUpdate("CREATE TABLE n012345_Accounts (...)");
    

2. Oracle语法与字段设计问题

  • 问题:
    • Oracle中FLOAT(n)的写法不符合规范,且账号是整数类型,用FLOAT存储不合适;
    • Lock是Oracle关键字,直接作为列名会导致语法错误;
    • 余额字段未保留小数位,不符合金额存储需求。
  • 修复:调整建表语句,修正类型与列名:
    CREATE TABLE n012345_Accounts (
        AccountNumber NUMBER(4),
        Name VARCHAR(25),
        Balance NUMBER(9,2),
        Locked VARCHAR(25)
    )
    
    (将Lock改为Locked,与文件中的列名保持一致,避免关键字冲突)

3. 文件读取逻辑缺陷

  • 问题:
    • 未跳过文件的表头行,直接解析会导致Float.parseFloat(fields[0])抛出异常(表头"Number"无法转成浮点数);
    • 用split(" ")分割会把连续空格拆成空元素,导致数组长度异常。
  • 修复:
    • 先读取一行跳过表头;
    • 用split("\\s+")匹配任意空白字符分割,同时跳过空行:
      // 跳过表头
      reader.readLine();
      String line;
      con.setAutoCommit(false);
      while ((line = reader.readLine()) != null) {
          line = line.trim();
          // 跳过空行
          if (line.isEmpty()) continue;
          String[] fields = line.split("\\s+");
          // 后续插入逻辑...
      }
      

4. 事务与异常处理不严谨

  • 问题:
    • 文件读取或数据插入出错时,未执行事务回滚;
    • 异常捕获过于宽泛,仅打印模糊提示,无法定位具体错误原因。
  • 修复:
    • 在文件读取的异常块中添加回滚操作;
    • 捕获SQLException时打印堆栈信息,便于排查:
      catch (SQLException ex) {
          System.out.println("unable to create new table for accounts");
          ex.printStackTrace(); // 打印具体异常信息
      }
      

5. 笔误问题

代码中打印提示信息写的是n01494108_Accounts,与实际创建的n012345_Accounts不一致,需修正为一致的表名。

修正后的完整代码

//Create a GUI application for a bank
//it should manage fund transfers from one account to another

//1
//Start
//@ the start up it should create a table name YourStudentNumber_Accounts ( n012345)
//it should also populate this table with the information stored in the file provided ("Accounts.txt")

//2
//Then the application will ask for
    //account number the funds are to be transferred from
    //amount to be transferred
    //account number funds are to be transferred to

//3
//Upon exit the application will present the contents of the Accounts table in standard output

//USE PREPARED STATEMENTS and TRANSACTIONS wherever appropriate
//All exceptions must be handled

import oracle.jdbc.pool.OracleDataSource;

import java.io.*;
import java.sql.*;

public class Main {

    public static void main(String[] args) {
        OracleDataSource ods = new OracleDataSource();
        try {
            ods.setURL("jdbc:oracle:thin:n012345/luckyone@calvin.humber.ca:1521:grok");
        } catch (SQLException e) {
            System.out.println("Failed to initialize data source");
            e.printStackTrace();
            return;
        }

        try(Connection con = ods.getConnection()) {
            con.setAutoCommit(false); // 提前设置事务自动提交为false

            try (Statement stmt = con.createStatement()) {
                // 修正建表语句,改用executeUpdate执行
                String createTableSql = "CREATE TABLE n012345_Accounts (" +
                        "AccountNumber NUMBER(4), " +
                        "Name VARCHAR(25), " +
                        "Balance NUMBER(9,2), " +
                        "Locked VARCHAR(25))";
                stmt.executeUpdate(createTableSql);
                System.out.println("Table n012345_Accounts created successfully");

                try (BufferedReader reader = new BufferedReader(new FileReader("Accounts.txt"))) {
                    // 跳过表头行
                    reader.readLine();
                    String line;
                    String insertSql = "INSERT INTO n012345_Accounts (AccountNumber, Name, Balance, Locked) VALUES(?,?,?,?)";
                    while ((line = reader.readLine()) != null) {
                        line = line.trim();
                        if (line.isEmpty()) continue; // 跳过空行
                        String[] fields = line.split("\\s+");
                        try (PreparedStatement pstmt = con.prepareStatement(insertSql)) {
                            pstmt.setInt(1, Integer.parseInt(fields[0])); // 账号用int更合适
                            pstmt.setString(2, fields[1]);
                            pstmt.setDouble(3, Double.parseDouble(fields[2]));
                            pstmt.setString(4, fields[3]);
                            pstmt.executeUpdate();
                        } catch (Exception e) {
                            System.out.println("Error inserting data: " + line);
                            e.printStackTrace();
                            con.rollback(); // 插入出错回滚事务
                            return;
                        }
                    }
                    con.commit();
                    System.out.println("Accounts.txt data was populated into the table n012345_Accounts");
                } catch (Exception e) {
                    System.out.println("unable to read the file.");
                    e.printStackTrace();
                    con.rollback();
                }
            } catch (SQLException ex) {
                System.out.println("unable to create new table for accounts");
                ex.printStackTrace();
                con.rollback();
            }
        } catch (SQLException ex) {
            System.out.println("Failed to connect to database");
            ex.printStackTrace();
        }
    }
}

内容的提问来源于stack exchange,提问作者DevSteph

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:10:32