0

簡単な答えはノーだと思いますが、そこにいるJava忍者の1人が巧妙なハックを知っているのではないかと思います...より具体的には、私の問題は、他のデータベースからデータベースを抽出/復元できる自動化を作成しようとしていることですデータ形式(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を返すように見えるので、ベンダーを特定できない限り、これらはあまり役に立ちません。私も?春はどういうわけかそれをしていることを私は知っています、おそらくそれを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;
        }
    }
}
4

1 に答える 1

3

を使用して、データベース ベンダーの名前を確認できますDatabaseMetaData.getDatabaseProductName()

そうすれば、例外を「分析」する必要はありません

于 2012-08-31T23:16:34.730 に答える