查找是否因为重复而抛出了SQLException

时间:2009-04-07 17:44:43

标签: java sql exception

我有一个与数据库无关的Java程序,我需要知道,在插入时,如果由于重复键而抛出了SQLException。

如果我使用单个数据库驱动程序,我只会使用ErrorCode,但由于我可以使用非常不同的引擎,因此ErrorCode不一样。

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

许多TIA!

编辑:我有一个配置文件,我存储驱动程序类(即:org.apache.derby.jdbc.ClientDriver)和一些其他所需信息(即:用户名,密码,网址。 ..)。连接始终作为“java.SQL.Connection”传递,因此我并不关心正在使用的驱动程序。

10 个答案:

答案 0 :(得分:8)

这正是SQLException.getSQLState()的用途。根据Google的说法,“23000”表示至少在MySQLPostgreSQLOracle中存在唯一约束违规。

答案 1 :(得分:7)

使用基本的JDBC,实际上没有办法以跨数据库的方式执行您所说的内容。如您所述,可以使用 getErrorCode ,但需要特定于供应商的错误代码。

我认为解决这个问题的唯一三种方法是:

  1. 使用某种框架来完成从错误代码到有意义的异常的所有转换(Hibernate可能会这样做,其他人提到Spring会这样做)。
  2. 在插入之前手动检查重复(使用选择)。 (这不是100%,因为技术上可能有人可能在你的查询后完成插入)。
  3. 在插入上获得任何sql异常后,尝试查询该id。如果您确实可以找到匹配项 - 您可以相当确定您收到的错误是由于重复的主键造成的。 (虽然可能存在多个问题,而实际上并不是那个问题)。
  4. 我的建议是编写代码以尽可能避免问题,然后(如果绝对必要)使用#3。

答案 2 :(得分:2)

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

答案 3 :(得分:2)

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

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

我认为这是一个Spring框架使事情变得非常正确的领域:它们提供了a very rich hierarchy of "database exceptions"所有扩展DataAccessException,其中包含了“可恢复异常”类型的子树,“瞬态异常” “,”数据完整性异常“等等。这使您的客户端代码可以自由地捕获它可以处理或关注的任何(或没有)异常类型:异常表示如果您重新发送可能不可重复的错误运行事务,一个致命的不可恢复的错误,或者你可以简单地捕获根类型。

答案 4 :(得分:1)

好吧,如果您不能依赖异常来告诉您抛出它的原因,您可以通过使用“select count(*)from table from key = @keyfailedtoinsert;”来检测异常。

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

所以你必须要相信每个JDBC驱动程序的供应商。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

我错过了什么吗?如果您正在使用JDBC,则无论使用何种DB,都应该返回重复的密钥异常。

或者您是否曾尝试在尝试插入之前如何确定双键?

答案 7 :(得分:0)

如果使用spring,则将唯一的KEY名称设置为UK_user_id,并捕获DataIntegrityViolationException
然后可以将ex.getCause().getConstraintName()UK_user_id进行比较。

答案 8 :(得分:0)

也许这不是解决这个问题的正确方法,但我遇到了同样的问题,我使用以下代码解决了:

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());          
      }
}

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

答案 9 :(得分:-1)

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

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