주요글: 도커 시작하기
반응형

이전글:


드디어 DB에서 변경된 DB 코드(프로시저, 함수, 패키지) 목록을 뽑아주는 쿼리를 전달받았다. 애초에 상상한 쿼리 실행 결과는 아래와 같았다.


[상상속에서 기대했던 쿼리 실행 결과]

OWNER

TYPE 

NAME 

QUERY 

O1

PROCEDURE 

findXXX 

프로시저 코드 

O2

PACKAGE 

somePkg 

패키지 코드 

...

... 

... 

... 


그런데 이게 왠 걸? 실제 쿼리를 실행하지 아래와 같은 결과가 나왔다.


[실제 쿼리 실행 결과]

OWNER

TYPE 

NAME 

QUERY 

O1

PROCEDURE 

findXXX 

프로시저 코드 1번줄

O1

PROCEDURE 

findXXX 

프로시저 코드 2번줄

...

... 

... 

... 

O1

PROCEDURE 

findXXX 

프로시저 코드 n번줄 

O2 

PACKAGE 

somePkg 

패키지 코드 1번줄 


오 마이! 이게 뭐야! 각 PL SQL의 각 코드가 1줄씩 결과로 리턴된다. 


쿼리를 갖고 몇 가지 방법을 쪼물딱 거려 봤으나, 줄 수가 좀(많이) 긴 패키지의 경우 오라클 장비가 먹어주지 못하는 상황이 발생했다. 이런 짜증 날 때를 봤나. 게다가 몇 만 줄이나 되는 패키지가 있다. (실제로 2만 줄이 넘는 패키지가 있다.)


한 번에 모든 쿼리 데이터를 다 읽어올까? 아님 필요할 때 읽어올까? 잠시 고민을 해 봤는데, 최초에 모든 쿼리를 받아서 SVN 리포지토리에 업로드해 주어야 하는 상황이 필요했고. (실DB에 수만 줄에 해당하는 프로시저 덩어리가 얼마나 있는 지 몰라 한방에 모든 DB 코드를 다 읽어오지 않고) DB 코드가 필요한 순간에 코드를 읽어오도록 DbCode 클래스 및 DbCodeFinder 의 코드를 수정했다. 먼저 다음과 같이 getDdl() 메서드를 호출하는 순간에 실제 쿼리 내용을 읽어오는 LazyDbCode 클래스를 추가했다.


public class LazyDbCode extends DbCode {


    private JdbcTemplate jdbcTemplate;


    public LazyDbCode(JdbcTemplate jdbcTemplate) {

        this.jdbcTemplate = jdbcTemplate;

    }


    @Override

    public String getDdl() {

        String query = "SELECT B.TEXT FROM ALL_OBJECTS A, ALL_SOURCE B "

                + "WHERE  A.OWNER = ?  AND A.OBJECT_NAME = ?  "

                + "AND A.OBJECT_TYPE = ?  AND A.OBJECT_NAME = B.NAME  "

                + "AND A.OBJECT_TYPE = B.TYPE  ";


        List<String> queryLines = jdbcTemplate.query(query,

                new PreparedStatementSetter() {

                    public void setValues(PreparedStatement ps) throws SQLException {

                        ps.setString(1, getSchema());

                        ps.setString(2, getName());

                        ps.setString(3, getType().name());

                    }

                }, new RowMapper<String>() {

                    public String mapRow(ResultSet rs, int rowNum) throws SQLException {

                        return rs.getString(1);

                    }

                });

        return queryLinesToString(queryLines);

    }

    

    public String queryLinesToString(List<String> queryLines) {

        ...

    }


}


DbCodeFinder의 구현 클래스인 JdbcDbCodeFinder는 DbCode 대신에 LazyDbCode 객체를 생성해서 리턴하도록 구현했다.


public class JdbcDbCodeFinder implements DbCodeFinder {


    private JdbcTemplate jdbcTemplate;


    public List<DbCode> findUpdatedDbCodesAfter(final Date fromTime, final Date toTime) {

        String query = "SELECT * FROM   ALL_OBJECTS A "

                + "WHERE  SUBSTR(A.OWNER,1,1) IN ('A','B','C','D','E','H')  "

                + "AND    A.OBJECT_TYPE IN ('PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'PROCEDURE', 'TRIGGER')  "

                + "AND    TO_CHAR(A.LAST_DDL_TIME, 'YYYYMMDDHH24MISS')  BETWEEN ? AND ?  "

                + "ORDER BY A.OBJECT_NAME, A.OBJECT_TYPE";

        

        List<DbCode> dbCodeList = jdbcTemplate.query(query,

                new PreparedStatementSetter() {

                    public void setValues(PreparedStatement ps) throws SQLException {

                        ps.setString(1, formatDate(fromTime));

                        ps.setString(2, formatDate(toTime));

                    }

                }, new RowMapper<DbCode>() {

                    public DbCode mapRow(ResultSet rs, int rowNum) throws SQLException {

                        DbCode code = new LazyDbCode(jdbcTemplate);

                        code.setSchema(rs.getString("OWNER"));

                        code.setType(DbCode.Type.valueOf(rs.getString("OBJECT_TYPE")));

                        code.setName(rs.getString("OBJECT_NAME"));

                        return code;

                    }

                });

        return dbCodeList;

    }


SvnClient와 DbCodeFinder의 콘크리트 클래스를 구현이 완료된 시점의 설계는 아래와 같다.



[다음 이야기에서 계속 ...]


+ Recent posts