Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 查找是否由于重复错误而引发SQLException_Java_Sql_Exception - Fatal编程技术网

Java 查找是否由于重复错误而引发SQLException

Java 查找是否由于重复错误而引发SQLException,java,sql,exception,Java,Sql,Exception,我有一个与数据库无关的Java程序,在插入时,我需要知道是否因为重复的键引发了SQLException 如果我使用一个数据库驱动程序,我只会使用错误代码,但是因为我可以使用非常不同的引擎,所以错误代码是不同的 以前有人这样做过吗?有什么想法吗 很多TIA 编辑:我有一个配置文件,在其中存储驱动程序类(即:org.apache.derby.jdbc.ClientDriver)和一些其他需要的信息(即:用户名、密码、url…)。连接总是以“java.SQL.connection”的形式传递,因此我并

我有一个与数据库无关的Java程序,在插入时,我需要知道是否因为重复的键引发了SQLException

如果我使用一个数据库驱动程序,我只会使用错误代码,但是因为我可以使用非常不同的引擎,所以错误代码是不同的

以前有人这样做过吗?有什么想法吗

很多TIA


编辑:我有一个配置文件,在其中存储驱动程序类(即:org.apache.derby.jdbc.ClientDriver)和一些其他需要的信息(即:用户名、密码、url…)。连接总是以“java.SQL.connection”的形式传递,因此我并不真正关心使用了什么驱动程序。

我认为一种简单可靠的方法是在插入之前检查密钥是否存在。正如您正确指出的,每个数据库都有自己报告错误的方式。

如果您不能依靠异常来告诉您抛出错误的原因,那么您可以在异常之后使用“select count(*)from table where key=@keyfailedtoinsert;”

不幸的是,异常不能保证为您提供表名和键名。在某些情况下,调用JDBC驱动程序的java代码可能从未拥有它们,例如,如果插入发生在存储过程中,或者发生在触发器中


因此,您又不得不信任每个JDBC驱动程序的供应商。

您可以在启动(或配置)时通过插入已知的重复密钥并记录抛出的错误代码来“训练”程序。

我是否遗漏了什么?如果您使用的是JDBC,那么无论使用的是哪个数据库,都应该返回一个重复的密钥异常


或者您是否询问过在尝试插入之前如何确定dupkey?

我假设您没有使用JDBC,或者这将是一个非常简单的错误查找


您是否有一组不同的类来访问不同的数据库?如果是这样,您可以捕获特定于数据库的类中的异常,并抛出您自己的异常类型,该类型在所有数据库类型中共享。

我认为理想的解决方案是让数据层在这种情况下抛出特定的异常,可能是
DuplicateKeyException
的SQLException子类或类似的东西

如果希望能够以不同的方式处理不同的异常,那么首先必须抛出不同的异常类型(或子类型)


我认为Spring框架在这方面做得非常好:它们提供了所有这些扩展,以及“可恢复异常”、“暂时异常”、“数据完整性异常”等类型的子树。这让您的客户机代码可以自由捕获任何(或无)它可以处理或关心的异常类型包括:指示在重新运行事务时可能不可重复的错误的异常、致命的不可恢复错误,或者您可以简单地捕获根类型。

对于基本JDBC,实际上没有一种方法以跨数据库的方式执行您所说的操作。正如您提到的,可以使用getErrorCode,但需要特定于供应商的错误代码

我认为只有三种方法可以解决这个问题:

  • 使用某种框架来完成从错误代码到有意义异常的所有转换(Hibernate可能会这样做,其他人提到Spring会这样做)
  • 在插入之前,请手动(通过选择)检查副本。(这不会是100%,因为技术上可能有人在您的查询后插入)
  • 在insert上出现任何sql异常后,请尝试查询该id。如果确实可以找到匹配项,则可以相当确定收到的错误是由于主键重复造成的。(虽然可能存在多个问题,但实际上并不是抛出的问题)

  • 我的建议是编写代码以尽可能避免问题,然后(如果绝对必要)使用#3。

    这正是SQLException.getSQLState()的用途。根据谷歌的说法,“23000”至少表示一个唯一的约束冲突,并且。

    如果您使用的是spring,请将您的唯一密钥名设置为
    UK\u user\u id
    ,然后捕获
    数据完整性异常
    然后,您可以将
    ex.getCause().getConstraintName()
    UK\u user\u id
    进行比较,也许这不是解决此问题的正确方法,但我有相同的问题,我用以下代码解决了此问题:

    try{
    
       //here goes your code
       //Conection to DB, stmt, ...
    
    
    }catch (SQLException sqlEx){
                
        //Check if the SQLException message contains the words "duplicate entry" and "for key"
        if(sqlEx.getMessage().contains("Duplicate entry") 
            && sqlEx.getMessage().contains("for key")){
    
               System.out.println("This Key already exists in the database");
    
          }else {
    
             //if your Exception is not due to the duplicate key, print your SQLException
               System.out.println("Error SQL:" + sqlEx.getMessage());          
          }
    }
    

    我希望这个解决方案能对某人有所帮助

    这取决于如何在代码中访问数据。这个问题并不清楚,所以我肯定不会说这是“唯一”的方法。我看不出代码中访问的数据会如何影响插入时的重复键。然而,我不能断言这是唯一的解决办法。我的答案已被修改。您如何访问代码中的数据?您是使用JDBC还是有特定于数据库的类?我有一个配置文件,其中存储了驱动程序类和连接参数。这使得我们假设返回的错误确实是insert上的重复键。您无法证明错误事实上是您预期的错误。@wentbackward-您可以接受90%的情况,并假设在执行“连接”、“选择”、“测试”、“选择”和/或仅要求用户阅读错误消息并确认后正确无误。这不是一门精确的科学,但很可能已经足够接近了。您需要支持多少个数据库?它真的是一个无限数吗?您最好弄清楚每个数据库的SQLState/ErrorCode对是什么,然后处理它们。它的性能仍然比提前执行SELECT检查行要好得多