H2 Database - グラフィックなデータを格納してみる。 2008/05/22
2008/09/27

Javaです。
データベースにイメージを格納します。

動機


シナリオ
画像を公開されているwebAPIから取得します。同じ画像を何度も、取得すると提供API側に負荷がかかります。
取得した画像をキャッシュするようにしてください。


というわけで、H2を使って、メモリ上にもたせてみる手習いです。
H2でなければいけないというわけではもちろんないです。

byteの配列を格納します。
その際に、ステートメントのsetBinaryStreamを使っています。
setBytesを使ってもいいようです。

参考

package h2test;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

static class ImageUtils {
public static byte[] getImageBytes(BufferedImage image,
String imageFormat) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BufferedOutputStream os = new BufferedOutputStream(bos);
image.flush();
ImageIO.write(image, imageFormat, os);
os.flush();
os.close();
return bos.toByteArray();
}
}

public static void main(String[] args) throws SQLException,
ClassNotFoundException, IOException {

// 格納用の画像を作成
BufferedImage bufferedImage = new BufferedImage(200, 200,
BufferedImage.TYPE_INT_ARGB);
{
Graphics2D g2d = (Graphics2D) bufferedImage.createGraphics();
g2d.setColor(new Color(24, 65, 199, 30));

g2d.fillRect(0, 0, 200, 200);
g2d.dispose();
}

Test test = new Test();

test.init();

test.update("INSERT INTO imagetable ( id, image ) VALUES(?, ?)",
"1234", ImageUtils.getImageBytes(bufferedImage, "png"));

Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {

connection = test.getConnection();
statement = connection.createStatement();
resultSet = statement
.executeQuery("select id, image from imagetable");
if (resultSet.next()) {
String id = resultSet.getString("id");
Object o = resultSet.getBinaryStream("image");

try {
final BufferedImage image = ImageIO
.read((ByteArrayInputStream) o);

Thread thread = new Thread(new Runnable() {
public void run() {

JPanel p = new JPanel() {

protected void paintChildren(Graphics g) {

g.drawImage(image, 0, 0, null);

}

};
JFrame frame = new JFrame();
frame

.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(p);
frame.setVisible(true);
}
});
thread.start();
} catch (IOException e) {
e.printStackTrace();
}

}
System.out.println();

} catch (SQLException e) {
e.printStackTrace();
} finally {
Test.close(resultSet, statement, connection);
}
}

protected void init() throws SQLException, ClassNotFoundException {
update("CREATE TABLE imagetable ( id VARCHAR (64) NOT NULL,image BLOB)");
}

protected void update(String expression, Object... param)
throws SQLException, ClassNotFoundException {

Connection connection = getConnection();
PreparedStatement st = null;

st = connection.prepareStatement(expression);

int pos = 1;
for (Object o : param) {
if (o instanceof byte[]) {
byte[] bs = (byte[]) o;
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
bs);
st.setBinaryStream(pos, byteArrayInputStream, bs.length);
continue;
}

st.setObject(pos, o);

pos++;
}

int i = st.executeUpdate(); // run the query

if (i == -1) {
System.err.println("update failed....");
}

st.close();

connection.close();
}

protected void update(String expression) throws SQLException,
ClassNotFoundException {

Connection connection = getConnection();
Statement st = null;

st = connection.createStatement(); // statements

int i = st.executeUpdate(expression); // run the query

if (i == -1) {
System.err.println("update failed....");
}

System.out.println("====>" + i);

st.close();

connection.close();
}

// BasicDataSource dataSource = new BasicDataSource();
// {
// dataSource.setUrl("jdbc:h2:mem:mydb");
// dataSource.setUsername("sa");
// dataSource.setPassword("");
// }

protected Connection getConnection() throws SQLException,
ClassNotFoundException {
Connection connection = null;
try {
Class.forName("org.h2.Driver");
connection = DriverManager.getConnection("jdbc:h2:mem:mydb;DB_CLOSE_DELAY=-1",
"sa",
"");
} catch (SQLException e) {
throw e;
} catch (ClassNotFoundException e) {
throw e;
}

return connection;
}

static void close(ResultSet resultSet, Statement statement,
Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
}
}

if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
}
}

if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
}
}
}
}

: