Java 跳过JDBC中的异常

Java 跳过JDBC中的异常,java,jdbc,Java,Jdbc,我通过一个java程序运行一个大型的、多样化的数据集,该程序从一个旧模式导入数据,进行转换,然后将数据插入一个新模式。该程序在试点数据上测试成功,但在实际数据上抛出异常 我希望能够计算整个数据集引发的异常数量,并记录引发异常的记录。有人能告诉我怎么做吗? 目前,当程序遇到第一个异常时,程序正在崩溃,因此我不知道如果代码能够在整个数据集中运行,会出现一个异常还是1000个异常 我在下面附上我的代码的相关方面。如何更改它,以便在记录异常的计数和ClientNumber时跳过异常 try {

我通过一个java程序运行一个大型的、多样化的数据集,该程序从一个旧模式导入数据,进行转换,然后将数据插入一个新模式。该程序在试点数据上测试成功,但在实际数据上抛出异常

我希望能够计算整个数据集引发的异常数量,并记录引发异常的记录。有人能告诉我怎么做吗?

目前,当程序遇到第一个异常时,程序正在崩溃,因此我不知道如果代码能够在整个数据集中运行,会出现一个异常还是1000个异常

我在下面附上我的代码的相关方面。如何更改它,以便在记录异常的计数和ClientNumber时跳过异常

try {
    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    Connection sourceConn = DriverManager.getConnection("jdbc:odbc:source_db");
    Statement st = sourceConn.createStatement();
    Connection destinationConn = DriverManager.getConnection("jdbc:odbc:destination_db");

    int ClientNumber;
    String Name;
    ResultSet rest = st.executeQuery("SELECT * FROM sourceTable");
    PreparedStatement ps5 = null;
    PreparedStatement ps6 = null;
    PreparedStatement ps7 = null;
    PreparedStatement ps8 = null;
    while(rest.next()){
        ClientNumber = rest.getInt(1);
        Name = rest.getString(2);//plus other variables skipped here for brevity
        ps5 = destinationConn.prepareStatement(
            "INSERT INTO Clients ("
            + "ClientNumber, Name) "
            +"VALUES (?, ?)"
            );
        ps5.setInt(1, ClientNumber);
        ps5.setString(2, Name);
        ps5.executeUpdate();
        //some other stuff for ps6,ps7,ps8
        destinationConn.commit();
    }
    //ps5.close();
}
catch (ClassNotFoundException cnfe){cnfe.printStackTrace();}
catch (SQLException e) {e.printStackTrace();}

下面的代码给出了一个提示。发生错误时打印ClientNumber取决于要打印的内容。但是您可以在内部catch中添加另一个日志。我故意使用exception而不是SQLException,因为您得到的异常可能是您在帖子中没有提到的任何类型的异常

try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection sourceConn = DriverManager.getConnection("jdbc:odbc:source_db");
Statement st = sourceConn.createStatement();
Connection destinationConn = DriverManager.getConnection("jdbc:odbc:destination_db");

int ClientNumber;
int errCounter = 0; 
String Name;
ResultSet rest = st.executeQuery("SELECT * FROM sourceTable");
PreparedStatement ps5 = null;
PreparedStatement ps6 = null;
PreparedStatement ps7 = null;
PreparedStatement ps8 = null;
while(rest.next()){
    try {
    ClientNumber = rest.getInt(1);
    Name = rest.getString(2);//plus other variables skipped here for brevity
    ps5 = destinationConn.prepareStatement(
        "INSERT INTO Clients ("
        + "ClientNumber, Name) "
        +"VALUES (?, ?)"
        );
    ps5.setInt(1, ClientNumber);
    ps5.setString(2, Name);
    ps5.executeUpdate();
    //some other stuff for ps6,ps7,ps8
    destinationConn.commit();
    }catch (Exception e) {
      e.printStackTrace();
      errCounter++;
    }
} //end while
 if(errCounter > 0) 
   System.out.println(String.format("Error occured %d times", errCounter));

} catch (ClassNotFoundException cnfe){
    cnfe.printStackTrace();}     
}

这样如何,只需以不同的方式编写循环:

try {
    // TODO: write your setup code here

    boolean hasNext = false;
    try {
        hasNext = rest.next();
    }catch (Exception e) {
        // TODO: log exception, increase a counter
    }
    while(hasNext){
        try {
            // TODO: write your processing code here

        }catch (Exception e) {
            // TODO: log exception, increase a counter
        }
        try {
            hasNext = rest.next();
        }catch (Exception e) {
            // TODO: log exception, increase a counter
            hasNext = false; //prevent infinite loops
        }
    }
} catch (Exception e){
    // TODO: this should never happen, handle ClassNotFoundException etc.
}
更新:我们可以避免调用next()两次,如下所示:

try {
    // TODO: write your setup code here

    while(true){
        try {
            if(!rest.next()){
                break;
            }
        }catch (Exception e) {
            // TODO: log exception, increase a counter
            break;
        }
        try {
            // TODO: write your processing code here

        }catch (Exception e) {
            // TODO: log exception, increase a counter
        }
    }
} catch (Exception e){
    // TODO: this should never happen, handle ClassNotFoundException etc.
}

SQLException
catch
块放得更靠近异常实际发生的部分(您没有提到,但我猜是在循环内部)。@qqilihq谢谢。我正在做这件事,因为实际上有大量的代码,这意味着许多try-catch块。while(rest.next)块请求它自己的try-catch块,而不是让我在其中创建几个try-catch块。你能建议一种方法,我可以改变while的定义,这样我就可以把它的组件分成几个try-catch块吗?我已经完成了整合你的建议。我将您的标记为答案并给出+1,因为创建布尔hasNext变量非常有用。最后,我为在rest上运行的每一行代码创建了一个单独的try-catch块,这就产生了所有的不同。但是,在使用hasNext布尔变量后,这变得更加可行。谢谢,我添加了第二个版本,它不再需要调用next()两次,也不再需要hasNext。有什么原因不好调用next()两次吗?+1感谢您的帮助。我最终用了一种不同的方法来解决这个问题。不过,您的计数想法是有帮助的。谢谢,不客气。您的应用程序似乎正在执行经典的迁移或ETL工作。您正在跳过某些不可处理的记录,可能是因为不兼容或输入数据质量差。springbatchframework试图提供一些开箱即用的方法来处理此类问题,如跳过、块读写等。我将研究Spring批处理框架。我使用其他的Spring工具,如果一切都使用Spring就好了。