서로 다른 DBMS 마다 원하는 메타정보를 조회해야 될 때가 있습니다.
그리고 당연히 서로 다른 DBMS 는 이에 대한 조회 방식이 모두 다릅니다.
이런 경우에는 JDBC 표준을 구현한 각 DBMS 별 JDBC 를 사용해서
메타정보를 조회하면 좋습니다. 지금부터 방법을 좀 알아봅시다.
더 알아내는 게 있으면 추가로 작성될 예정입니다.
Spring boot 3.3.x
사용dependency
spring-boot-stater-data-jdbc
Lombok
jdk
: temurin-21
사용지금부터 볼 예시 코드에서 사용되는 모든 dataSource 를 만든 방법은 아래와 같습니다.
// import org.springframework.jdbc.datasource.DriverManagerDataSource;
DriverManagerDataSource dataSource
= new DriverManagerDataSource(
"jdbc:postgresql://localhost:5432/postgres",
"postgres",
"postgres");
여기에 작성된 것에 만족하지 못하시겠으면
https://docs.oracle.com/javase/8/docs/api/java/sql/DatabaseMetaData.html
를 한번 참조하시기 바랍니다.
try (
Connection conn = dataSource.getConnection();
) {
DatabaseMetaData metaData = conn.getMetaData();
try (ResultSet rs = metaData.getPrimaryKeys("", "coding_toast", "somesome")) {
ResultSetMetaData resultSetMetaData = rs.getMetaData();
int columnCount = resultSetMetaData.getColumnCount();
// primary key 가 없을 수도 있으니까 if 문으로 꼭 확인!
if(rs.next()) {
System.out.println("======================");
for (int i = 1; i <= columnCount; i++) {
System.out.printf("%s : %s\n",
resultSetMetaData.getColumnName(i), rs.getObject(i));
}
}
}
}
출력 예시
======================
table_cat : null
table_schem : coding_toast
table_name : somesome
column_name : id
key_seq : 1
pk_name : somesome_pkpk
======================
table_cat : null
table_schem : coding_toast
table_name : somesome
column_name : name
key_seq : 2
pk_name : somesome_pkpk
pk_name
으로 2개의 값이 조회되고 있습니다.try (
Connection conn = dataSource.getConnection();
) {
DatabaseMetaData metaData = conn.getMetaData();
try (ResultSet rs = metaData.getIndexInfo(
"",
"coding_toast", // 스키마 명
"somesome", // 테이블 명
true, // 인덱스 유니크 여부, false 를 하면 모든 인덱스 조회
false)) // 정확히 뭔진 모르겠습다. true 든 false 든 결과가 같네용...
{
ResultSetMetaData resultSetMetaData = rs.getMetaData();
int columnCount = resultSetMetaData.getColumnCount();
while (rs.next()) {
System.out.println("======================");
for (int i = 1; i <= columnCount; i++) {
System.out.printf("%s : %s\n",
resultSetMetaData.getColumnName(i), rs.getObject(i));
}
}
}
}
테이블 형태
-- auto-generated definition
create table coding_toast.somesome
(
id bigint not null,
name varchar(255) not null,
number1 numeric(10, 2) not null
constraint somesome_number_unique
unique,
number2 integer,
constraint somesome_pkpk
primary key (id, name)
);
somesome_pkpk => (id, name)
somesome_number_unique => number1
출력방식
(출력이 너무 길어서 출력 결과를 조금 편집했습니다!)
INDEX_NAME
으로 그룹핑을 할 수 있다는 것을 알 수 있습니다.참고 링크: ResultSetMetaData javadocs
try (
Connection conn = dataSource.getConnection();
PreparedStatement preparedStatement =
conn.prepareStatement("select * from coding_toast.sample_copy limit 0");
ResultSet resultSet = preparedStatement.executeQuery()) {
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
System.out.println("======================");
System.out.println("ColumnName : " + metaData.getColumnName(i));
System.out.println("ColumnTypeName : " + metaData.getColumnTypeName(i));
System.out.println("ColumnClassName : " + metaData.getColumnClassName(i));
System.out.println("Nullable : " + metaData.isNullable(i));
System.out.println("Precision : " + metaData.getPrecision(i));
System.out.println("Scale : " + metaData.getScale(i));
}
}
// 출력 예시
/*
======================
ColumnName : tracking_id
ColumnTypeName : serial
ColumnClassName : java.lang.Integer
Nullable : 0 ==> Not Null 이라는 의미입니다.
Precision : 10
Scale : 0
======================
ColumnName : id
ColumnTypeName : varchar
ColumnClassName : java.lang.String
Nullable : 1 ==> Null 이 가능하다는 의미입니다.
Precision : 2147483647
Scale : 0
=====================
... 생략 ...
*/
try (Connection conn = dataSource.getConnection();
ResultSet rs = conn.getMetaData().getColumns(
null, //db명
"sample_schema", // 스키마 명
"sample_table", // 테이블 명
"%" // 검색하고자 하는 컬럼 (% = 모두 조회)
)) {
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
while (rs.next()) {
System.out.println("============================");
for (int i = 1; i <= columnCount; i++) {
System.out.printf("""
%s : %s
""", metaData.getColumnName(i), rs.getObject(i));
}
}
}
// 출력 예시 - 출력된 결과에 대한 것들이 궁금하면
// 위에 작성된 링크 : [javadoc - DatabaseMetaData.getIndexInfo] 를 확인해주세요.
/*
============================
... (너무 많아서 부분 생략) ...
COLUMN_NAME : code
DATA_TYPE : 12
TYPE_NAME : varchar
COLUMN_SIZE : 254
DECIMAL_DIGITS : 0
NULLABLE : 1
REMARKS : null
COLUMN_DEF : null
CHAR_OCTET_LENGTH : 254
ORDINAL_POSITION : 2
IS_NULLABLE : YES
... (너무 많아서 부분 생략) ...
============================
... 생략...
*/
핵심 key
COLUMN_NAME
: 컬럼명DATA_TYPE
: JDBC 내부에서 사용되는 타입의 코드값 java.sql.Types
참고)java.sql.JDBCType.valueOf(코드값);
통해서 JDBCType ENUM
으로 변환 가능TYPE_NAME
: 타입 명칭 (영문)DECIMAL_DIGITS
: numeric
의 경우 SCALE
값COLUMN_DEF
: default 값IS_NULLABLE
: 널 여부REMARKS
: 컬럼 주석