최근 프로젝트를 진행하면서 CDC(Change Data Capture)를 구현할 일이 있었는데, 이때 ResultSetMetaData
와 DatabaseMetaData
를 통해 테이블의 각종정보를 가져오는 일을 진행했었다.
오늘은 관련하여 기록을 하기위해 포스팅을 진행하고자 한다.
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 |