在同一个数据库服务器上,针对于不同的表空间中,可能存在名字相同的表!此时使用hibernate的自动建表,可能导致More than one table found in namespace(,):table_name 这类问题!
通过查看hibernate源码了解到,hibernate在扫描完实体之后,在创建表时会去当前用户所能访问到的所有表空间去寻找是否有相同名字的表,如果有 就会返回不同表空间的表名,然后执行alert操作,从而导致报错!
InformationExtractorJdbcDatabaseMetaDataImpl.class
public TableInformation getTable(Identifier catalog, Identifier schema, Identifier tableName) {
if (catalog == null && schema == null) {
TableInformation tableInfo = null;
if (this.extractionContext.getJdbcEnvironment().getCurrentCatalog() != null || this.extractionContext.getJdbcEnvironment().getCurrentSchema() != null) {
tableInfo = this.locateTableInNamespace(this.extractionContext.getJdbcEnvironment().getCurrentCatalog(), this.extractionContext.getJdbcEnvironment().getCurrentSchema(), tableName);
if (tableInfo != null) {
return tableInfo;
}
}
if (this.extractionContext.getDefaultCatalog() != null || this.extractionContext.getDefaultSchema() != null) {
tableInfo = this.locateTableInNamespace(this.extractionContext.getDefaultCatalog(), this.extractionContext.getDefaultSchema(), tableName);
if (tableInfo != null) {
return tableInfo;
}
}
try {
String tableNameFilter = this.toMetaDataObjectName(tableName);
ResultSet resultSet = this.extractionContext.getJdbcDatabaseMetaData().getTables((String)null, (String)null, tableNameFilter, this.tableTypes);
TableInformation var7;
try {
var7 = this.processTableResults((Identifier)null, (Identifier)null, tableName, resultSet);
} finally {
try {
resultSet.close();
} catch (SQLException var15) {
;
}
}
return var7;
} catch (SQLException var17) {
throw this.convertSQLException(var17, "Error accessing table metadata");
}
} else {
return this.locateTableInNamespace(catalog, schema, tableName);
}
}
通过上述代码可以看出在没有查找到指定表空间之后,会通过用户名去扫描能够扫描的所有表空间,然后返回新的表空间信息。
就比如说 我有表空间 dbA,dbB,并且使用同一用户进行访问,而daA中有了表user,但是我在运行我的代码时,我想在dbB中在生成一个user,如果此时userEntity的@Table注解如果只有name,那么就会引起上述的问题。因为hibernate将所有实体装载如内存之后,然后就去会判断我应该是insert还是alert还是drop啊?这个时候就会去扫描当前jdbc用户所能访问的所有表空间了。这个时候就发现,咦!这里有个user了,拿走!hibernate一拿到就发现,哦!有这个实体了!执行alert!但是你程序的上下文所存在的jdbc是dbB的,这个时候一执行alert!我去,我没这个表啊!然后就报错了 !
此时,我们要么就将jdbc的user从新分配,一个用户只能访问一个表空间,要么在实体的@Table的注解上加上catalog=databaseName 即可!
网友评论