我假设简单的答案是 no ,但想知道是否有一个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的适配器支持一些安全的DROP
(DROP table IF EXISTS
或类似的),但Oracle和DB2却没有。所以我的下一个想法是放弃它并捕获适当的异常。但抛出的异常是java.sql.SQLSyntaxErrorException
(或org.springframework.jdbc.BadSqlGrammarException
因为我使用的是弹簧JdbcTemplate
)。这个例外的家庭似乎远远不能安全地捕获(而且它对我来说似乎并不像语法......)。每个供应商似乎都返回不同的SQLState和ErrorCode,因此除非我也能确定供应商,否则这些帮助不大。那么,我可以吗?我知道spring会以某种方式完成它,最有可能的方法是将它从发出查询的DataSource
中挖出来。只是还没想出来。
---------------------- UPDATE ------------------------ ---
我能够用这段代码实现我的目标:
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;
}
}
}
答案 0 :(得分:3)
您可以使用DatabaseMetaData.getDatabaseProductName()
检查数据库供应商的名称。
这样你就不需要“分析”异常
了