середа, 14 вересня 2011 р.

Java, Blob и картинки

Стрельнула мне в голову идея попробвать хранить картинки в базе данных (в моем случае это был MySQL, но роли это не играет). Но не просто картинки, а  сканкопии докуменов размером порядка 100-200к. Как обычно в идее и теории все было прекрасно, пока не дошло дело до реализации.
 Ну сделал таблицу в базе, с которой поле mediumblob для самих картинок. И когда дошло до када началось самое интересное. Итак, сначала вставляем картинку:

//Читаем файл
FileInputStream input = new FileInputStream(picFile);
Statement st = new Statement() //Допустим подключение у нас есть
//Делаем запрос, выключив autocommit
String query = "insert into table (id,pic) values (?,?)";
st.getConnection().setAutoCommit(false);
PreparedStatement ps = (PreparedStatement)
st.getConnection().prepareStatement(query);
ps.setInt(1, id);
ps.setBinaryStream(2, input, pic.length());
//Вставляем
ps.executeUpdate();
st.getConnection().commit();
//Уходим
try {
    st.getConnection().setAutoCommit(true);
    st.getConnection().close();
} catch (SQLException ex) {
    Logger.getLogger(ActDB.class.getName()).log(Level.SEVERE, null, ex);
}

Получилось с первого раза. А теперь нужто єту картинку прочесть и вывести на экран. Для убыстрения решил ее вывести в JLabel. И тут я сделал роковую ошибку....Дело в том, что для выводаизображения я истользовал new ImageIcon(URL url), а url передавался через файл приблизительно так:

File f = new File("tmp.jpg")
Blob img = new  Blob() //представим, что он у нас есть
FileOutputStream out = new FileOutputStream(f);
out.write(b.getBytes(0, b.length()), 0, b.length());
return f;

потом соответственно new JLabel(new ImageIcon(f.toURI().toURL)). Первая картинка показывалсь отлично, в отличии от остальных. При следующих вызовах метода показывалась только первая картинка. Мои смутные сомнения по поводу шибко умной ява машины подтвердились когда я добавил рандом в имя файла:

Random r = new Random();
File f = new File("tmp"+r.nextInt()+".jpg");

и все заработало как нужно.
Вот такая вот особенность. Поэтому поразмыслив и почитав документацю я подумал что лучше передавать байт массив.           

Statement st = new Statement();
Blob imgData = null;
byte[] img = null;
if (st != null) {
   String query = "select * from table where id=" + id ";";
   ResultSet rs = null;
   try {
       rs = st.executeQuery(query);
       while (rs.next()) {
       actData = rs.getBlob("pic");
   }
     img = actData.getBytes(1, (int) imgData.length()).clone();
} catch (SQLException ex) {
   Logger.getLogger(ActDB.class.getName()).log(Level.SEVERE, null, ex);
}

try {
    st.getConnection().close();
    } catch (SQLException ex) {
      Logger.getLogger(ActDB.class.getName()).log(Level.SEVERE, null, ex);
    }
}

return img;


ну а потом получив байты делаем иконку: new ImageIcon(img);

Немає коментарів:

Дописати коментар