【问题标题】:Can you determine which database vendor is used from a SQLException?您能否从 SQLException 中确定使用了哪个数据库供应商?
【发布时间】:2012-08-26 17:35:19
【问题描述】:

我假设简单的答案是,但想知道是否有一个 Java 忍者可能知道一个聪明的黑客...更具体地说,我的问题是我正在尝试创建自动化可以从其他数据格式(xml、另一个数据库供应商、json...)中提取/恢复数据库。我试图将供应商特定代码的范围限制为*Adapter 类。界面为:

public String escapeName( String name );

public ColumnMetaData columnMetaDataFromResultSet( ResultSet resultSet ) throws SQLException;

public SqlQuery getColumnMetaDataSql( String schema, String table );

public String getCreateTableSql( TableMetaData tableMetaData );

public String getDropTableSql( TableMetaData tableMetaData );

public String getRowInsertSql( TableMetaData tableMetaData );

public String getRowSelectSql( TableMetaData tableMetaData );

public SqlQuery getTableMetaDataSql();

public TableMetaData tableMetaDataFromResultSet( ResultSet resultSet ) throws SQLException;

这个问题的重要方法是getDropTableSql( TableMetaData tableMetaData )。该方法理论上将返回一个 SQL 语句,该语句将删除元数据指示的表,以便可以重新创建它(这用于在固定期限的基础上发布完整的数据集,因此,旧的,新的)。 MySQL 和 SQLServer 的适配器都支持某种安全的DROPDROP table IF EXISTS 或类似),但 Oracle 和 DB2 不支持。所以我的下一个想法是放弃它并捕获适当的异常。但是抛出的异常是java.sql.SQLSyntaxErrorException(或org.springframework.jdbc.BadSqlGrammarException,因为我使用的是弹簧JdbcTemplate)。那个异常系列似乎很广泛,可以安全地捕获(而且它对我来说似乎并不像语法......)。每个供应商似乎返回不同的 SQLState 和 ErrorCode,所以除非我也能确定供应商,否则这些并没有多大帮助。那么,我可以吗?我知道spring会以某种方式做到这一点,很可能是从发出查询的DataSource中挖掘出来的。只是还没弄明白。

---------- 更新 ------------- ---

我能够用这段代码实现我的目标:

private void dropTable( JdbcTemplate jdbcTemplate, String dropSql ) {
    try {
        jdbcTemplate.execute( dropSql );
    }
    catch ( BadSqlGrammarException sqle ) {
        try {
            throw sqle.getRootCause();
        }
        catch ( SQLException rootCause ) {
            int errorCode = rootCause.getErrorCode();
            String sqlState = rootCause.getSQLState();

            try {
                String vendor = jdbcTemplate.getDataSource().getConnection().getMetaData().getDatabaseProductName();

                if ( vendor.equalsIgnoreCase( "mysql" ) && errorCode == 1051 && sqlState.equals( "42S02" ) ) {
                    logger.info( "mysql table does not exist, unable to drop ({})", dropSql );
                }
                else if ( vendor.equalsIgnoreCase( "oracle" ) && errorCode == 942 && sqlState.equals( "42000" ) ) {
                    logger.info( "oracle table does not exist, unable to drop ({})", dropSql );
                }
                else {
                    throw( sqle );
                }
            }
            catch ( Exception e ) {
                throw( sqle );
            }
        }
        catch ( Throwable e ) {
            throw sqle;
        }
    }
}

【问题讨论】:

  • 为什么不在运行语句前检查?您通过DatabaseMetaData.getDatabaseProductName()获取供应商名称
  • @a_horse_with_no_name,嘿嘿,我刚刚发现...... java.sql api 相当混乱......将您的评论转换为答案,我会标记它。谢谢大佬。

标签: java sql datasource


【解决方案1】:

您可以使用DatabaseMetaData.getDatabaseProductName() 检查数据库供应商的名称。

这样你就不需要“分析”异常

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 2019-12-01
    • 2011-12-27
    • 2018-09-21
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多