Mając odwrotnej inżynierii faktycznie komunikacji między klientem a serwerem Mogę ujawnić, że DatabaseMetaData.getColumns Oracle() metody wysyła następujące zapytanie SQL (choć to może się zmienić z wersji sterowników ODBC i ustawień):
declare
in_owner varchar2(128);
in_name varchar2(128);
in_column varchar2(128);
xyzzy SYS_REFCURSOR;
begin
in_owner := :1; // Which resolves to the schema (user) name supplied
in_name := :2; // Which resolves to the table name supplied
in_column := :3; // Which gets set to '%';
open xyzzy for
SELECT NULL AS table_cat,
t.owner AS table_schem,
t.table_name AS table_name,
t.column_name AS column_name,
DECODE( (SELECT a.typecode
FROM ALL_TYPES A
WHERE a.type_name = t.data_type),
'OBJECT', 2002,
'COLLECTION', 2003,
DECODE(substr(t.data_type, 1, 9),
'TIMESTAMP',
DECODE(substr(t.data_type, 10, 1),
'(',
DECODE(substr(t.data_type, 19, 5),
'LOCAL', -102, 'TIME ', -101, 93),
DECODE(substr(t.data_type, 16, 5),
'LOCAL', -102, 'TIME ', -101, 93)),
'INTERVAL ',
DECODE(substr(t.data_type, 10, 3),
'DAY', -104, 'YEA', -103),
DECODE(t.data_type,
'BINARY_DOUBLE', 101,
'BINARY_FLOAT', 100,
'BFILE', -13,
'BLOB', 2004,
'CHAR', 1,
'CLOB', 2005,
'COLLECTION', 2003,
'DATE', 93,
'FLOAT', 6,
'LONG', -1,
'LONG RAW', -4,
'NCHAR', -15,
'NCLOB', 2011,
'NUMBER', 2,
'NVARCHAR', -9,
'NVARCHAR2', -9,
'OBJECT', 2002,
'OPAQUE/XMLTYPE', 2009,
'RAW', -3,
'REF', 2006,
'ROWID', -8,
'SQLXML', 2009,
'UROWI', -8,
'VARCHAR2', 12,
'VARRAY', 2003,
'XMLTYPE', 2009,
1111)))
AS data_type,
t.data_type AS type_name,
DECODE (t.data_precision, null,
DECODE(t.data_type, 'NUMBER',
DECODE(t.data_scale, null, 0 , 38),
DECODE (t.data_type, 'CHAR', t.char_length, 'VARCHAR', t.char_length, 'VARCHAR2', t.char_length, 'NVARCHAR2', t.char_length, 'NCHAR', t.char_length, 'NUMBER', 0, t.data_length)), t.data_precision)
AS column_size,
0 AS buffer_length,
DECODE (t.data_type, 'NUMBER', DECODE(t.data_precision, null, DECODE(t.data_scale, null, -127 , t.data_scale), t.data_scale), t.data_scale) AS decimal_digits,
10 AS num_prec_radix,
DECODE (t.nullable, 'N', 0, 1) AS nullable,
NULL AS remarks,
t.data_default AS column_def,
0 AS sql_data_type,
0 AS sql_datetime_sub,
t.data_length AS char_octet_length,
t.column_id AS ordinal_position,
DECODE (t.nullable, 'N', 'NO', 'YES') AS is_nullable,
null as SCOPE_CATALOG,
null as SCOPE_SCHEMA,
null as SCOPE_TABLE,
null as SOURCE_DATA_TYPE,
'NO' as IS_AUTOINCREMENT,
t.virtual_column as IS_GENERATEDCOLUMN
FROM all_tab_cols t
WHERE t.owner LIKE in_owner ESCAPE '/'
AND t.table_name LIKE in_name ESCAPE '/'
AND t.column_name LIKE in_column ESCAPE '/'
AND t.user_generated = 'YES'
ORDER BY table_schem, table_name, ordinal_position;
end;
Można docenić, dlaczego może to być nieco powolne, zwłaszcza, że tabele ALL_TAB_COLS i ALL_TYPES mogą mieć po 1000 rekordów. Niemniej jednak, podczas gdy Oracle stara się wykonać pierwszą inwokację (minuty), kolejne połączenia zwracają wyniki niemal natychmiast. Jest to klasyczny problem z wydajnością łączenia tabel, w którym mimo że wymagany jest podzbiór danych, silnik łączy się z całym zestawem danych przed obliczeniem i dostarczeniem wymaganego podzbioru. Następnie buforowanie danych/wyników działa w celu poprawy wydajności kolejnych zapytań.
Lepszym rozwiązaniem może być użycie get_ddl() i przeanalizowanie zwróconej definicji tabeli zgodnie z this thread.
Alternatywnie może być w stanie do kwerendy metadane na stole szybciej wykonując obojętne zapytanie następnie używając resultSetMetadata następująco (Uwaga: Metadane Uwagi kolumn nie mogą być natychmiast dostępne):
ResultSet rs = connection.CreateStatement.executeQuery("SELECT * from MyTable WHERE 1=0");
ResultSetMetaData md = rs.getMetaData();
for (int ix = 1; ix <= md.getColumnCount(); ix++)
{
int colSize = md.getPrecision(ix);
String nativeType = md.getColumnTypeName(ix);
int jdbcType = md.getColumnType(ix);
// and so on....
}
Czy jesteś czy to wina Springs? Czy możesz uruchomić tę samą kwerendę za pomocą zwykłego JDBC lub może bezpośrednio w konsoli bazy danych? –
Nie sądzę, że to jest błąd sprężyny. Problem polega na tym, że nie jest to zapytanie jako takie. Sterownik JDBC ukrywa rzeczywiste zapytanie za pomocą metody 'getColumns()', więc nie widzę, co naprawdę się dzieje. –
@FranzKafka - Czy możesz prześledzić SQL, który generuje Spring, aby dokładnie określić, które tabele słownika danych są sprawdzane? Czy zebrano statystyki w słowniku danych? –