我假设简单的答案是“否”,但是想知道是否有一个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()检查数据库供应商的名称。

这样,您就无需“分析”异常

10-08 08:28
查看更多