MySQL テーブル内にバイナリデータを格納する場合、blob 型の列を定義することになります。具体的には blob 型にも複数あり、想定される最大サイズに応じて使うことになります:
格納するデータの内容によって型を決める必要がありますが、例えば画像、音声、動画といったメディア系のファイルを格納しようとすると tinyblob や blob 型では足りないと思われるので、ほぼ mediumblob か largeblob を使うことになると思われます。1データの最大サイズが 16MB を超える想定があるかどうかで使い分けることになります。ただし largeblob でも 4GB が最大となります。
MySQL で mediumblob 型を使う場合のテーブル定義の例としてはこのようになります:
上記例では images テーブル内に mediumblob 型の img 列を定義しました。このテーブルにデータを読み書きする Java のサンプルは後述のようになります。なお後述のサンプル共通で getConnection() という関数を使っていますが、これは java.sql.Connection クラスのインスタンスを返す関数で、具体的には以下のような内容となります:
まずはデータの書き込み(insert)です。格納したいバイナリデータが byte[] 型の変数 data に格納されている場合、以下のようなコードで上述の images テーブルに insert することができます:
一方、読み出し(select)は以下のようになります。ResultSet からバイナリストリームを取得して ByteArrayOutputStream に書き出し、最後に byte[] 型の変数に変換して取り出しています:
バイナリデータをサービスシステム内のどこに格納するべきか、という設計の問題を考慮した上で使うべきだと思いますが、この方法で MySQL に格納しておけば、MySQL のバックアップを取ればバイナリデータもまとめてバックアップすることができ、同様に MySQL をリストアすればバイナリデータごとリストアできる、というメリットがあります。
型 | 最大サイズ(バイト) | 格納するデータの例 |
---|---|---|
tinyblob | 255 | (あまり使われない?) |
blob | 65,535 | (あまり使われない?) |
mediumblob | 16,777,215 | 画像など |
largeblob | 4,294,967,295 | 動画、音声など |
格納するデータの内容によって型を決める必要がありますが、例えば画像、音声、動画といったメディア系のファイルを格納しようとすると tinyblob や blob 型では足りないと思われるので、ほぼ mediumblob か largeblob を使うことになると思われます。1データの最大サイズが 16MB を超える想定があるかどうかで使い分けることになります。ただし largeblob でも 4GB が最大となります。
MySQL で mediumblob 型を使う場合のテーブル定義の例としてはこのようになります:
create table images( id int primary key, img mediumblob );
上記例では images テーブル内に mediumblob 型の img 列を定義しました。このテーブルにデータを読み書きする Java のサンプルは後述のようになります。なお後述のサンプル共通で getConnection() という関数を使っていますが、これは java.sql.Connection クラスのインスタンスを返す関数で、具体的には以下のような内容となります:
public Connection getConnection(){ Connection conn = null; try{ Class.forName( "com.mysql.jdbc.Driver" ); conn = DriverManager.getConnection( "jdbc:mysql://servername/dbname", "user", "pass" ); }catch( Exception e ){ e.printStackTrace(); } return conn; }
まずはデータの書き込み(insert)です。格納したいバイナリデータが byte[] 型の変数 data に格納されている場合、以下のようなコードで上述の images テーブルに insert することができます:
import java.sql.*; : try{ Connection conn = getConnection(); String sql = "insert into images( id, img ) values ( ?, ? )"; PreparedStatement stmt = conn.prepareStatement( sql ); stmt.setInt( 1, id ); stmt.setBytes( 2, data ); //. data は byte[] 型 int r = stmt.executeUpdate(); stmt.close(); conn.close(); }catch( Exception e ){ e.printStackTrace(); }
一方、読み出し(select)は以下のようになります。ResultSet からバイナリストリームを取得して ByteArrayOutputStream に書き出し、最後に byte[] 型の変数に変換して取り出しています:
import java.sql.*; : byte[] r = null; try{ Connection conn = getConnection(); String sql = "select img from images where id = " + id; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( sql ); rs.first(); InputStream is = rs.getBinaryStream( 1 ); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] bs = new byte[1024]; int size = 0; while( ( size = is.read( bs ) ) != -1 ){ baos.write( bs, 0, size ); } r = baos.toByteArray(); //. byte[] 型に変換してデータを取得 stmt.close(); conn.close(); }catch( Exception e ){ e.printStackTrace(); r = null; }
バイナリデータをサービスシステム内のどこに格納するべきか、という設計の問題を考慮した上で使うべきだと思いますが、この方法で MySQL に格納しておけば、MySQL のバックアップを取ればバイナリデータもまとめてバックアップすることができ、同様に MySQL をリストアすればバイナリデータごとリストアできる、というメリットがあります。
コメント