응용개발

MySQL의 Blob타입을 CUBRID로 변환하기

by cubebridge posted Nov 18, 2009

MySQL에서 CUBRID의 변환을 생각하는 많은 개발자들이 궁금해 하는 MySQL BLOB타입 데이터를 CUBRID로 이전하는 방법에 대해 기술한다. FAQ http://blog.naver.com/windyhan/110052262344 블로그를 참조하여 기술하였음을 밝힌다.

이미 문서를 통하여 MySQL to CUBRID Data Type변경에 대해 소개하고 있다. 대부분의 경우 대응되는 Type으로의 스키마 변경으로 해결되나 Blob의 경우 약간의 작업이 필요하게 된다. 이 약간의 작업에 대해서 설명하도록 한다.

MySQL
에서 사용하는 Blob타입 4종류와 각각의 허용 범위는 아래와 같다.

TinyBlob - maximum length of 255 characters.
Blob - maximum length of 65535 characters.
MediumBlob - maximum length of 16777215 characters.
LongBlob - maximum length of 4294967295 characters.


CUBRID
에서 대응하는 Type Bit Varying의 범위는 아래와 같다.

Bit Varying(n) - n에 대한 값이 생략되면, 디폴트 길이 1,073,741,823이 가정된다. 이는 MySQLLongBlob을 제외한 Blob타입에 대응될 수 있다.
* MySQL LongBlob에 대해서는 CUBRID는 GLO라는 타입으로 대응이 가능하나 이는 다른 Tip으로 정리한다.
 

MySQL Blob CUBRID로 변환하는 과정을 아래의 예를 통하여 확인하고자 한다. 아래의 예시는 test_tbl이라는 테이블로 간단한 이미지를 저장한 저장해 놓은 테이블이다. 이미지의 사이즈는 30~60 byte정도로 MySQL MediumBlob에 해당한다.

mysql> describe test_tbl;

+-----------+--------------+------+-----+---------+----------------+

| Field     | Type         | Null | Key | Default | Extra          |

+-----------+--------------+------+-----+---------+----------------+

| id        | int(11)      | NO   | PRI | NULL    | auto_increment |

| file_name | varchar(255) | YES  |     | NULL    |                |

| file_data | mediumblob   | YES  |     | NULL    |                |

+-----------+--------------+------+-----+---------+----------------+

3 rows in set (0.00 sec)

 

데이터는 아래와 같이 들어있다.

 

mysql> select length(file_data) from test_tbl;

+-------------------+

| length(file_data) |

+-------------------+

|            216492 |

|            321152 |

|            262936 |

|            419584 |

     :       

+-------------------+


데이터를 추출하기 위해 JDBC를 이용한다. file_data칼럼에 있는 이미지를 추출하는 java코드는 아래와 같다.

public void getBlobDataFromMySQL(){

          Connection conn=null;

          Statement stmt=null;

          ResultSet rs=null;

          String file_path = "pic";

 

          try{

               File curr = new File("./" + file_path);

               if( !curr.exists() ){

                  curr.mkdir();

               }

               Class.forName("com.mysql.jdbc.Driver");  //드라이버 로드

               conn = DriverManager.getConnection   // Connection객체 가져오기

                   ("jdbc:mysql://localhost/testdb?user=root&password=root");

 

               String sql = "select id, file_name, file_data from test_tbl";

               stmt = conn.createStatement();

               rs = stmt.executeQuery(sql);

               while(rs.next()){

                 int id = rs.getInt("id");

                 String file_name = rs.getString("file_name");

                 InputStream is = rs.getBinaryStream("file_data");

                 FileOutputStream fos = new FileOutputStream("./pic/" + file_name);

                 byte[] buff = new byte[2048000];

                 int len;

                 while ( (len = is.read(buff)) > 0 )

                      fos.write( buff, 0, len);

                 fos.close();

                 is.close();

               }

               rs.close();

               stmt.close();

               conn.close();

          }catch(Exception e){

              e.printStackTrace();

          }

    }

 

위의 코드를 간략히 설명하면 test_tbl 테이블의 이미지를 select 하여 pic이라는 디렉토리에 file_name 을 이름으로 하는 파일들을 생성한다. 이 파일들을 읽어서 CUBRID에 삽입할 것이다.

 

이제 추출한 데이터를 넣을 CUBRID테이블을 생성한다. CUBRID의 테이블 생성 예는 아래와 같다.

csql> create table test_tbl ( id integer auto_increment primary key not null, file_name varchar(255), file_data bit varying);

csql> ;x

 

Current transaction has been committed.

 

1 command(s) successfully processed.

csql> ;sc test_tbl

 

=== <Help: Schema of a Class> ===

 

 <Class Name>

 

     test_tbl

 

 <Attributes>

 

     id                   INTEGER AUTO_INCREMENT  NOT NULL

     file_name            CHARACTER VARYING(255)

     file_data            BIT VARYING(1073741823)

 

 <Constraints>

 

     PRIMARY KEY pk_test_tbl_id ON test_tbl (id)

 

Current transaction has been committed.


MySQL BLOB 타입에서 빼낸 이미지 파일들을 CUBRID test_tbl bit varying 타입인 file_data 컬럼에 넣는다.

public void setBlobDataToCUBRID_bit(){

           File curr = new File("./pic");                         

           String[] filelist = curr.list(new BlobFileNameFilter());              -------------------------  1

           cubrid.jdbc.driver.CUBRIDConnection conn=null;

           cubrid.jdbc.driver.CUBRIDPreparedStatement stmt=null;

 

           try{

               Class.forName("cubrid.jdbc.driver.CUBRIDDriver");

               conn = (cubrid.jdbc.driver.CUBRIDConnection)DriverManager.getConnection                    

("jdbc:cubrid:127.0.0.1:33004:testdb1:dba::");          ------------------------- 2

 

               for( int i = 0; i < filelist.length ; i++){

                  String filename  = filelist[i];

                  File file = new File("./pic/" + filename);

                  FileInputStream in = new FileInputStream(file);           ------------------------- 3

 

                  String sql = "insert into test_tbl(file_name, file_data) values ( ?,?)";

                  stmt=(cubrid.jdbc.driver.CUBRIDPreparedStatement)conn.prepareStatement(sql);

                  stmt.setString(1,filename);

                  stmt.setBinaryStream(2,in,(int)file.length());               ------------------------- 4

                  stmt.executeUpdate();                                 ------------------------- 5

                  stmt.close();        

                  in.close();

               }

               conn.commit();

               conn.close();

 

         }catch(Exception e){

            e.printStackTrace();

         }

}

 각각의 설명은 아래와 같다.

1. Bit varying 컬럼에 저장할 파일들의 리스트를 생성한다.

2. CUBRID DB Connection 을 가져온다.

3. 입력할 FILE InputStream 을 생성한다.

4. Bit Varying 타입인 file_data 컬럼에 setBinaryStream() 함수를 이용해 파라미터 바인딩을 한다.

5. insert 문을 실행한다.

 

위의 java파일을 컴파일 후 실행하면 test_tbl 테이블에 데이터가 삽입된다. 데이터가 제대로 들어갔는지 확인한다.

csql> select file_name, bit_length(file_data)/8 from test_tbl

csql> ;x

 

=== <Result of SELECT Command in Line 1> ===

 

  file_name              bit_length(file_data)/8

================================================

  'DSC_0193_007.JPG'                      329216

  'DSC_0199_010.JPG'                      266272

  'DSC_0202_011.JPG'                      329382

  'DSC_0190_004.JPG'                      419584

  'DSC_0206_013.JPG'                      319426

  'DSC_0187_002.JPG'                      321152

  'DSC_0197_008.JPG'                      273747

  'DSC_0191_005.JPG'                      391503

  'DSC_0192_006.JPG'                      291880

  'DSC_0198_009.JPG'                      169344

  'DSC_0183_001.JPG'                      216492

  'DSC_0208_014.JPG'                      345924

  'DSC_0203_012.JPG'                      333349

  'DSC_0189_003.JPG'                      262936

 

14 rows selected.

데이터가 잘 들어가 있는지 확인해 보았다. 질의에서 Bit_length(file_data)/8 을 한 이유는 저장된 데이터의 byte 수를 알기 위해 한 것이다. 특별히 다른 점은 없고, JDBC 표준 인터페이스를 사용하여 저장을 한 것이다.

 

CUBRID에 저장된 데이터를 추출하는 방법은 위의 MySQL에서 추출한 방법과 거의 같다 아래의 두가지 부분만 변경해 주면 된다

 1. 함수 이름을 변경한다.

 2. MySQL Connection 연결하는 방법을 CUBRID용으로 변경한다.


Articles

1 2 3