본문 바로가기

Language/Java

[JAVA] JDBC 메타정보 추출하기

최근 프로젝트를 진행하면서 CDC(Change Data Capture)를 구현할 일이 있었는데, 이때 ResultSetMetaDataDatabaseMetaData 를 통해 테이블의 각종정보를 가져오는 일을 진행했었다.

오늘은 관련하여 기록을 하기위해 포스팅을 진행하고자 한다.

1. 컬럼 리스트 추출

//getConnection은 생략
try(Connection connection = getConnection(), 
    Statement stmt = connection.createStatement()) {
      //데이터는 필요 없기 때문에 where 조건에 1 != 0을 입력
      ResultSet rs = stmt.executeQuery("SELECT * FROM test_table WHERE 1 != 0");
      ResultSetMetaData rsmd = rs.getMetaData();

      // 컬럼의 인덱스가 1부터 시작하기 때문에 for-loop도 1부터 시작하도록 함
      for(int i = 1, i <= rsmd.getColumnCount(); i++) {
        // columnType은 java.sql.Types 에 선언되어있다.
        int columnType = rsmd.getColumnType(i);
        String columnName = rsmd.getColumnName(i);
      }


} catch(Exception e) {...}

2. Primary Key 추출

//getConnection은 생략
try(Connection connection = getConnection()) {

  String catalog = connection.getCatalog();
  DatabaseMetaData metaData = connection.getMetaData();

  ResultSet rs = metaData.getPrimaryKeys(catalog, "", tableName);

  List<org.apache.commons.lang3.tuple.Pair<Integer, String>> pkColumns = new ArrayList();

  while (rs.next()) {
    // 키 순서
    int keySequence = rs.getInt("KEY_SEQ");
    //pk 컬럼 명
    String pkColumnName = rs.getString("COLUMN_NAME");

    pkColumns.add(new org.apache.commons.lang3.tuple.ImmutablePair<>(keySequence, pkColumnName));
  }

  //Primary key가 복합키(Composite key)로 설정되어있을 경우 키 컬럼의 순서가 섞여 나온다.
  //예를들어 PK를 (id, created_at) 두개의 컬럼을 이용해 복합키로 설정해 둔경우 pkColumns List에 순서대로 id, created_at 순으로 들어간다고 보장하지 못한다.
  //따라서 필요하다면 KEY_SEQ를 통해 순서를 보정해 주어야 한다.
  pkColumns.sort(Comparator.comparingInt(org.apache.commons.lang3.tuple.Pair::getKey));


} catch(Exception e) {...}

3. Create DDL 구문 추출

try(Connection connection = getConnection(), 
    Statement stmt = connection.createStatement()) {
      //데이터는 필요 없기 때문에 where 조건에 1 != 0을 입력
      ResultSet rs = stmt.executeQuery("SHOW CREATE TABLE test_table");

      while(rs.next()){
        String createDdl = rs.getString("Create Table");
        break;
      }
} catch(Exception e) {...}

4. java.sql.Types를 JDBCType으로 변경

ResultSetMetaData를 통해 컬럼 리스트 추출을 진행했었는데, 이때 단점은 컬럼의 타입이 java.sql.Types에 정의된 Integer 값으로 리턴된다는데 문제가 있다. 타입을 정수형타입으로 데이터를 받다보니 코드에서 컬럼 타입을 사용할때마다 코드가 복잡하게 되는데, 이를 해결하기 위헤 enum으로 된 java.sql.JDBCType으로 바꾸면 좀더 깔끔하게 코드 작성이 가능하다.

int columnType = ...;
java.sql.JDBCType jdbcType = JDBCType.valueOf(columnType);

5. Spring에서 ResultSetMetaData, DatabaseMetaData 사용하기

//Spring의 JdbcTemplate을 사용하여 처리할 수 있다.
@Autowired
org.springframework.jdbc.core.JdbcTemplate template;

//ResultSetMetaData 사용하기
template.query("SELECT * FROM test_table WHERE 1 != 0", new ResultSetExtractor<List<String>>{
  @Override
  public List<String> extractData(ResultSet rs) throws SQLException, DataAccessException {
    ResultSetMetaData rsmd = rs.getMetaData();
    //생략
  }
});

//DatabaseMetaData 사용하기
try(Connection conn = template.getDataSource().getConnection()) {
    DatabaseMetaData meta = conn.getMetaData();
    ResultSet pkResultSet = meta.getPrimaryKeys(database, "", tableName);
    //생략
}
catch (Exception e) {}

'Language > Java' 카테고리의 다른 글

[Java] AdoptOpenJdk Installation on CentOS  (0) 2020.06.02
[Java] invalid source release 에러 해결  (0) 2020.02.12