您的位置:首页 > 其它

org.dbunit.database.AmbiguousTableNameException 终极解决方案

2013-02-22 15:57 701 查看
项目的单元测试用到了dbunit进行数据组装,最近遇到了org.dbunit.database.AmbiguousTableNameException: XXXX数据库表 问题,在网上查找了不少资料,最终还是通过同事的帮助(数据库工程师)一起把问题解决。网上通常的解决方案是对connection增加schema问题即可解决,原因是不同的schema可能会遇到相同的表名,导致抛出错误。 但是这个问题好解决(schema设置为null也可以解决),如下代码: properties.put(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES,
"true");databaseConnection.getConfig().setPropertiesByString(stringProperties) 即可解决。 (由于导入数据库的一个xml里有不同的schema,所有connction不能指定schema)

那问题是什么呢? 由于是测试数据库,最后把"XXXX数据库表"删除掉,问题解决。最后通过数据库工程师分析,通过select * from dba_tables where owner='schmae' and table_name='XXXX数据库表' 可以查询出两条记录,可能是oracle数据库的问题, 从而可推出dbunit源代码里(“罪魁祸首”代码)应该是通过此sql语句进行预加载的,由于有两条重复的表,导致报错。所以数据库工程师将此“垃圾表”清除掉,问题解决。

问题整理:

1.dbunit问题的核心代码如下:

private void initialize() throws DataSetException
{
logger.debug("initialize() - start");

if (_tableMap != null)
{
return;
}

try
{
logger.debug("Initializing the data set from the database...");

Connection jdbcConnection = _connection.getConnection();
DatabaseMetaData databaseMetaData = jdbcConnection.getMetaData();

String schema = _connection.getSchema();

if(SQLHelper.isSybaseDb(jdbcConnection.getMetaData()) && !jdbcConnection.getMetaData().getUserName().equals(schema) ){
logger.warn("For sybase the schema name should be equal to the user name. " +
"Otherwise the DatabaseMetaData#getTables() method might not return any columns. " +
"See dbunit tracker #1628896 and http://issues.apache.org/jira/browse/TORQUE-40?page=all"); }

DatabaseConfig config = _connection.getConfig();
String[] tableType = (String[])config.getProperty(DatabaseConfig.PROPERTY_TABLE_TYPE);
IMetadataHandler metadataHandler = (IMetadataHandler) config.getProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER);

ResultSet resultSet = metadataHandler.getTables(databaseMetaData, schema, tableType);

if(logger.isDebugEnabled())
{
logger.debug(SQLHelper.getDatabaseInfo(jdbcConnection.getMetaData()));
logger.debug("metadata resultset={}", resultSet);
}

try
{
OrderedTableNameMap tableMap = super.createTableNameMap();
while (resultSet.next())
{
String schemaName = metadataHandler.getSchema(resultSet);
String tableName = resultSet.getString(3);

if(_tableFilter != null && !_tableFilter.accept(tableName))
{
logger.debug("Skipping table '{}'", tableName);
continue;
}
if(!_oracleRecycleBinTableFilter.accept(tableName))
{
logger.debug("Skipping oracle recycle bin table '{}'", tableName);
continue;
}

QualifiedTableName qualifiedTableName = new QualifiedTableName(tableName, schemaName);
tableName = qualifiedTableName.getQualifiedNameIfEnabled(config);

// Put the table into the table map
tableMap.add(tableName, null);
}

_tableMap = tableMap;
}
finally
{
resultSet.close();
}
}
catch (SQLException e)
{
throw new DataSetException(e);
}
}


分析:

1.ResultSet resultSet = metadataHandler.getTables(databaseMetaData, schema, tableType);

oracle用户下指定的schema的表可全部查询处理(如果schema为null,则可查询所有权限的表)

2.tableMap.add(tableName,null)

此add方法会先将map里是否有重复的schema.table ,如果有则会抛出

org.dbunit.database.AmbiguousTableNameException: XXXX数据库表 异常。

3.通过select * from dba_tables where owner='schema' and table_name='XXXX数据库表' 分析,有两条记录(一个大写的表,一个是小写的表),删除掉一个解决。

刨根问底:

为什么会出现数据库里有两条表的记录呢? 上网查询后得知,有个笨蛋用户在建表时,通过双引号建的表,比如 create table "XXX数据库表",建好表后估计是发现查不到此表,然后又重新建了一个,最终导致Exception.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐