📄 jdbcmodelreader.java
字号:
* Returns the descriptors for the columns to be read from the index meta data result set.
*
* @return The column descriptors
*/
protected List getColumnsForIndex()
{
return _columnsForIndex;
}
/**
* Returns the active connection. Note that this is only set during a call to
* {@link #readTables(String, String, String[])}.
*
* @return The connection or <code>null</code> if there is no active connection
*/
protected Connection getConnection()
{
return _connection;
}
/**
* Reads the database model from the given connection.
*
* @param connection The connection
* @param name The name of the resulting database; <code>null</code> when the default name (the catalog)
* is desired which might be <code>null</code> itself though
* @return The database model
*/
public Database getDatabase(Connection connection, String name) throws SQLException
{
return getDatabase(connection, name, null, null, null);
}
/**
* Reads the database model from the given connection.
*
* @param connection The connection
* @param name The name of the resulting database; <code>null</code> when the default name (the catalog)
* is desired which might be <code>null</code> itself though
* @param catalog The catalog to acess in the database; use <code>null</code> for the default value
* @param schema The schema to acess in the database; use <code>null</code> for the default value
* @param tableTypes The table types to process; use <code>null</code> or an empty list for the default ones
* @return The database model
*/
public Database getDatabase(Connection connection, String name, String catalog, String schema, String[] tableTypes) throws SQLException
{
Database db = new Database();
if (name == null)
{
try
{
db.setName(connection.getCatalog());
if (catalog == null)
{
catalog = db.getName();
}
}
catch (Exception ex)
{
_log.info("Cannot determine the catalog name from connection.", ex);
}
}
else
{
db.setName(name);
}
try
{
_connection = connection;
db.addTables(readTables(catalog, schema, tableTypes));
// Note that we do this here instead of in readTable since platforms may redefine the
// readTable method whereas it is highly unlikely that this method gets redefined
if (getPlatform().isForeignKeysSorted())
{
sortForeignKeys(db);
}
}
finally
{
_connection = null;
}
db.initialize();
return db;
}
/**
* Reads the tables from the database metadata.
*
* @param catalog The catalog to acess in the database; use <code>null</code> for the default value
* @param schemaPattern The schema(s) to acess in the database; use <code>null</code> for the default value
* @param tableTypes The table types to process; use <code>null</code> or an empty list for the default ones
* @return The tables
*/
protected Collection readTables(String catalog, String schemaPattern, String[] tableTypes) throws SQLException
{
ResultSet tableData = null;
try
{
DatabaseMetaDataWrapper metaData = new DatabaseMetaDataWrapper();
metaData.setMetaData(_connection.getMetaData());
metaData.setCatalog(catalog == null ? getDefaultCatalogPattern() : catalog);
metaData.setSchemaPattern(schemaPattern == null ? getDefaultSchemaPattern() : schemaPattern);
metaData.setTableTypes((tableTypes == null) || (tableTypes.length == 0) ? getDefaultTableTypes() : tableTypes);
tableData = metaData.getTables(getDefaultTablePattern());
List tables = new ArrayList();
while (tableData.next())
{
Map values = readColumns(tableData, getColumnsForTable());
Table table = readTable(metaData, values);
if (table != null)
{
tables.add(table);
}
}
final Collator collator = Collator.getInstance();
Collections.sort(tables, new Comparator() {
public int compare(Object obj1, Object obj2)
{
return collator.compare(((Table)obj1).getName().toUpperCase(), ((Table)obj2).getName().toUpperCase());
}
});
return tables;
}
finally
{
if (tableData != null)
{
tableData.close();
}
}
}
/**
* Reads the next table from the meta data.
*
* @param metaData The database meta data
* @param values The table metadata values as defined by {@link #getColumnsForTable()}
* @return The table or <code>null</code> if the result set row did not contain a valid table
*/
protected Table readTable(DatabaseMetaDataWrapper metaData, Map values) throws SQLException
{
String tableName = (String)values.get("TABLE_NAME");
Table table = null;
if ((tableName != null) && (tableName.length() > 0))
{
table = new Table();
table.setName(tableName);
table.setType((String)values.get("TABLE_TYPE"));
table.setCatalog((String)values.get("TABLE_CAT"));
table.setSchema((String)values.get("TABLE_SCHEM"));
table.setDescription((String)values.get("REMARKS"));
table.addColumns(readColumns(metaData, tableName));
table.addForeignKeys(readForeignKeys(metaData, tableName));
table.addIndices(readIndices(metaData, tableName));
Collection primaryKeys = readPrimaryKeyNames(metaData, tableName);
for (Iterator it = primaryKeys.iterator(); it.hasNext();)
{
table.findColumn((String)it.next(), true).setPrimaryKey(true);
}
if (getPlatformInfo().isSystemIndicesReturned())
{
removeSystemIndices(metaData, table);
}
}
return table;
}
/**
* Removes system indices (generated by the database for primary and foreign keys)
* from the table.
*
* @param metaData The database meta data
* @param table The table
*/
protected void removeSystemIndices(DatabaseMetaDataWrapper metaData, Table table) throws SQLException
{
removeInternalPrimaryKeyIndex(metaData, table);
for (int fkIdx = 0; fkIdx < table.getForeignKeyCount(); fkIdx++)
{
removeInternalForeignKeyIndex(metaData, table, table.getForeignKey(fkIdx));
}
}
/**
* Tries to remove the internal index for the table's primary key.
*
* @param metaData The database meta data
* @param table The table
*/
protected void removeInternalPrimaryKeyIndex(DatabaseMetaDataWrapper metaData, Table table) throws SQLException
{
Column[] pks = table.getPrimaryKeyColumns();
List columnNames = new ArrayList();
for (int columnIdx = 0; columnIdx < pks.length; columnIdx++)
{
columnNames.add(pks[columnIdx].getName());
}
for (int indexIdx = 0; indexIdx < table.getIndexCount(); indexIdx++)
{
Index index = table.getIndex(indexIdx);
if (index.isUnique() && matches(index, columnNames) &&
isInternalPrimaryKeyIndex(metaData, table, index))
{
table.removeIndex(indexIdx);
break;
}
}
}
/**
* Tries to remove the internal index for the given foreign key.
*
* @param metaData The database meta data
* @param table The table where the table is defined
* @param fk The foreign key
*/
protected void removeInternalForeignKeyIndex(DatabaseMetaDataWrapper metaData, Table table, ForeignKey fk) throws SQLException
{
List columnNames = new ArrayList();
boolean mustBeUnique = !getPlatformInfo().isSystemForeignKeyIndicesAlwaysNonUnique();
for (int columnIdx = 0; columnIdx < fk.getReferenceCount(); columnIdx++)
{
String name = fk.getReference(columnIdx).getLocalColumnName();
Column localColumn = table.findColumn(name,
getPlatform().isDelimitedIdentifierModeOn());
if (mustBeUnique && !localColumn.isPrimaryKey())
{
mustBeUnique = false;
}
columnNames.add(name);
}
for (int indexIdx = 0; indexIdx < table.getIndexCount(); indexIdx++)
{
Index index = table.getIndex(indexIdx);
if ((mustBeUnique == index.isUnique()) && matches(index, columnNames) &&
isInternalForeignKeyIndex(metaData, table, fk, index))
{
fk.setAutoIndexPresent(true);
table.removeIndex(indexIdx);
break;
}
}
}
/**
* Checks whether the given index matches the column list.
*
* @param index The index
* @param columnsToSearchFor The names of the columns that the index should be for
* @return <code>true</code> if the index matches the columns
*/
protected boolean matches(Index index, List columnsToSearchFor)
{
if (index.getColumnCount() != columnsToSearchFor.size())
{
return false;
}
for (int columnIdx = 0; columnIdx < index.getColumnCount(); columnIdx++)
{
if (!columnsToSearchFor.get(columnIdx).equals(index.getColumn(columnIdx).getName()))
{
return false;
}
}
return true;
}
/**
* Tries to determine whether the index is the internal database-generated index
* for the given table's primary key.
* Note that only unique indices with the correct columns are fed to this method.
* Redefine this method for specific platforms if there are better ways
* to determine internal indices.
*
* @param metaData The database meta data
* @param table The table owning the index
* @param index The index to check
* @return <code>true</code> if the index seems to be an internal primary key one
*/
protected boolean isInternalPrimaryKeyIndex(DatabaseMetaDataWrapper metaData, Table table, Index index) throws SQLException
{
return false;
}
/**
* Tries to determine whether the index is the internal database-generated index
* for the given foreign key.
* Note that only non-unique indices with the correct columns are fed to this method.
* Redefine this method for specific platforms if there are better ways
* to determine internal indices.
*
* @param metaData The database meta data
* @param table The table owning the index and foreign key
* @param fk The foreign key
* @param index The index to check
* @return <code>true</code> if the index seems to be an internal primary key one
*/
protected boolean isInternalForeignKeyIndex(DatabaseMetaDataWrapper metaData, Table table, ForeignKey fk, Index index) throws SQLException
{
return false;
}
/**
* Reads the column definitions for the indicated table.
*
* @param metaData The database meta data
* @param tableName The name of the table
* @return The columns
*/
protected Collection readColumns(DatabaseMetaDataWrapper metaData, String tableName) throws SQLException
{
ResultSet columnData = null;
try
{
columnData = metaData.getColumns(tableName, getDefaultColumnPattern());
List columns = new ArrayList();
while (columnData.next())
{
Map values = readColumns(columnData, getColumnsForColumn());
columns.add(readColumn(metaData, values));
}
return columns;
}
finally
{
if (columnData != null)
{
columnData.close();
}
}
}
/**
* Extracts a column definition from the result set.
*
* @param metaData The database meta data
* @param values The column meta data values as defined by {@link #getColumnsForColumn()}
* @return The column
*/
protected Column readColumn(DatabaseMetaDataWrapper metaData, Map values) throws SQLException
{
Column column = new Column();
column.setName((String)values.get("COLUMN_NAME"));
column.setDefaultValue((String)values.get("COLUMN_DEF"));
column.setTypeCode(((Integer)values.get("DATA_TYPE")).intValue());
column.setPrecisionRadix(((Integer)values.get("NUM_PREC_RADIX")).intValue());
String size = (String)values.get("COLUMN_SIZE");
int scale = ((Integer)values.get("DECIMAL_DIGITS")).intValue();
if (size == null)
{
size = (String)_defaultSizes.get(new Integer(column.getTypeCode()));
}
// we're setting the size after the precision and radix in case
// the database prefers to return them in the size value
column.setSize(size);
if (scale != 0)
{
// if there is a scale value, set it after the size (which probably did not contain
// a scale specification)
column.setScale(scale);
}
column.setRequired("NO".equalsIgnoreCase(((String)values.get("IS_NULLABLE")).trim()));
column.setDescription((String)values.get("REMARKS"));
return column;
}
/**
* Retrieves the names of the columns that make up the primary key for a given table.
*
* @param metaData The database meta data
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -