近来很烦,为公司开发的项目中做一个工具,以配合公司的项目管理。该工具具体的功能,主要是用于导入导出数据,并用于系统安装或者升级补丁。我主要是使用了dbunit来实现,但在使用的过程中遇到了一个很难搞的问题,就是导入数据时有某些版本或者复杂的数据库环境下会报AmbiguousTableNameException的错误。
上网查找资料,却发现资料少得可怜,搜索AmbiguousTableNameException,只找到四条记录,而且里面也没有怎么说解决办法。不过,只指出了一些原因,主要是dbunit中使用了schema,因此必须指定schema。之于,schema是什么,在哪里指定根本没有提到。请教了公司的同事,用过的不超过两个,曾遇到过这样的错误,但是似乎没有解决。同时也请教了schema是什么东西,每个人都有不同的解释,搞到一头雾水。
最后,经理建议我还是读原代码自己想办法。经过几个小时的分析,终于有些头绪了。在dbunit的源代码中package org.dbunit.database中有一个DatabaseDataSet.java,发现其中的一个方法:
private void initialize() throws DataSetException
{
if (_nameList != null)
{
return;
}
try
{
Connection jdbcConnection = _connection.getConnection();
String schema = _connection.getSchema();
String[] tableType = (String[])_connection.getConfig().getProperty(
DatabaseConfig.PROPERTY_TABLE_TYPE);
DatabaseMetaData databaseMetaData = jdbcConnection.getMetaData();
ResultSet resultSet = databaseMetaData.getTables(
null, schema, "%", tableType);
try
{
List nameList = new ArrayList();
while (resultSet.next())
{
String schemaName = resultSet.getString(2);
String tableName = resultSet.getString(3);
// String tableType = resultSet.getString(4);
// System.out.println("schema=" + schemaName + ", table=" + tableName + ", type=" + tableType + "");
tableName = getQualifiedName(schemaName, tableName);
// prevent table name conflict
if (_tableMap.containsKey(tableName.toUpperCase()))
{
throw new AmbiguousTableNameException(tableName);
}
nameList.add(tableName);
_tableMap.put(tableName.toUpperCase(), null);
}
_nameList = nameList;
}
finally
{
resultSet.close();
}
}
catch (SQLException e)
{
throw new DataSetException(e);
}
}
里面的ResultSet resultSet = databaseMetaData.getTables(null, schema, "%", tableType);是指定了使用schema,而我的调用函数为:
DBConnectionManager dbManager = new DBConnectionManager();
Connection jdbcConnection = dbManager.getConnection(null);
return new DatabaseConnection(jdbcConnection);
这里构造实例时根据没有把schema传入,因此导致错误。因此,只须传入schame的值就行了。
另外,schema究竟是什么呢?我找一个公司的一位资深oracle数据库人员,终于找到了答案。数据库schema,相当于方案,每个数据库实例,里面可能会有多个用户,每个用户可能都有自己的表,过程等object,那oracle就会为每个用户创建一个与用户名相同的方案,就相当于schema。
因此,问题就解决了。使用以下代码,把用户名传入就解决问题了:
DBConnectionManager dbManager = new DBConnectionManager();
Connection jdbcConnection = dbManager.getConnection(null);
Config myConfig = null;
myConfig = Config.getInstance();
String schame= myConfig.getValue("DB.USER");
return new DatabaseConnection(jdbcConnection,schame);
值得注意的是,schema要求一定要大写的。
到现在,可以总结一下,为什么会出现AmbiguousTableNameException的错误了。主要是因为,在同一个数据库中,存在多个方案(名字不同),但方案则里面的表,视图,过程等可能大部分都是相同的。我们公司就是这样在一个库中创建多个不同的用户进行不同版本的安装测试的。因此,dbunit在导入时就会无法区分,那么就必须在open一个connection时必须指定一个schema,即方案,来正确区分相同的表名。
相关文章
- Python 使用 UTF-8 编码,python代码中包含中文时执行脚本错误的解决办法。
- 如何解决FormView中实现DropDownList连动选择时出现 "Eval()、XPath() 和 Bind() 这类数据绑定方法只能在数据绑定控件的上下文中使用" 的错误
- 实体类中有主键,数据库中主键是自增的,使用linq插入记录时,由于实体类有数据产生报错的解决方法
- 使用Geoprocessor导出ArcSde中的数据,对COM 组件的调用返回了错误 HRESULT E_FAIL 的解决方法
- 使用Geoprocessor导出ArcSde中的数据,对COM 组件的调用返回了错误 HRESULT E_FAIL 的解决方法
- Android studio使用过程中错误的解决方法
- PHP的Yii框架使用中的一些错误解决方法与建议
- VMware提示:此虚拟机似乎正在使用中,取得该虚拟机的所有权失败错误的解决方案
- asp.net中ListView控件动态绑定数据源后,使用DataPager出现错误的原因及解决办法
- myeclipes使用过程中的错误解决方案