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

项目的单元测试用到了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. 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值