Как управлять большим двоичным объектом в Java?

#java #blob

#java #большой двоичный объект

Вопрос:

У меня есть процедура DB, которая возвращает большой двоичный объект. Кто-нибудь может сказать мне, как управлять большим двоичным объектом? Существует ли какой-либо конкретный API для этого?

Комментарии:

1. Например, API для java.sql.Blob?

Ответ №1:

Существует ли какой-либо конкретный API для этого?

Конечно, API JDBC.


Вы получаете доступ к Blob экземпляру так же, как и к любому значению из результирующего набора. Затем вы должны использовать get... set... для этого методы — and Blob .

Здесь у вас в основном есть два варианта:

  • Работа с байтовым массивом:

    1. Получить byte[] доступ к файлу, содержащему данные, с помощью Blob.getBytes
    2. Манипулировать этим байтовым массивом
    3. Установите его обратно с помощью Blob.setBytes .

  • Работа с InputStream / OutputStream :

    1. Получить удержание InputStream через Blob.getBinaryStream
    2. Управляйте этим потоком по своему усмотрению
    3. Используйте Blob.setBinaryStream .

Альтернативный подход заключается в том, чтобы Blob в первую очередь не связываться с ним, а вместо этого использовать второй подход (с потоками) непосредственно через ResultSet -interface .

Комментарии:

1. Мой опыт показывает, что ResultSet.getBinaryStream() это более надежно, чем работа с экземплярами Blob

2. @aioobe: Спасибо за ответы. Но может кто-нибудь сказать мне, насколько «ResultSet.getBinaryStream ()» надежен по сравнению с «Blob.getBinaryStream»?

3. Если ваш драйвер поддерживает ResultSet.getBlob и Blob.getBinaryStream , и вы достаточно уверены, что не будете переключаться на другую базу данных, просто выберите ту, которую вы считаете наиболее читаемой.

Ответ №2:

Это зависит от того, какой тип большого двоичного объекта содержит (изображение, видео) и его расширение. Я написал простую программу для извлечения изображения из базы данных и отображения его на странице JSP. Надеюсь, это поможет.

Страница JSP

 <html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>JSP Page</title>
</head>
<body>                            
    <image src="blobAction"/> 
</body>
  

Страница сервлета

 byte[] imgData = blobDao.getInstance().getPhoto();
        response.setContentType("image/gif");
        OutputStream o = response.getOutputStream();
        o.write(imgData);
        o.flush();
        o.close();
  

Вызывающая процедура

 public byte[] getPhoto() {

    byte[] imgData = null;
    Blob img = null;
    ResultSet rs = null;
    Statement stmt = null;

    try {

        conn = getConnection();
        String sqlQ = "SELECT CONTENT_FILE FROM CONTENT where id = 'something';
        stmt = conn.createStatement();
        rs = stmt.executeQuery(sqlQ);

        while (rs.next()) {
            img = rs.getBlob("CONTENT_FILE");
            imgData = img.getBytes(1, (int) img.length());
        }
        rs.close();
        stmt.close();
        conn.close();
    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {           
        return imgData;
    }
}
  

Ответ №3:

С помощью простого Java JDBC Api вы можете получить java.sql.Blob ответ от a ResultSet .

  1. ResultSet.getBlob(index) или
  2. ResultSet.getBlob(String columnName) .

Оба возвращают a Blob .

Как только вы получите a Blob , вы можете получить byte[] его обратно из Blob.getBytes() метода или установить с помощью setBytes() метода.

Обновление: видя, что некоторые поставщики драйверов баз данных не поддерживают Blob , вы можете использовать ResultSet.getBinaryStream() .

Комментарии:

1. Почему бессмысленно? Существование типа данных большого двоичного объекта в базе данных не имеет ничего общего с поддержкой драйвером. Не все драйверы поддерживают ResultSet.getBlob() , некоторые поддерживают только ResultSet.getInputStream()

2. @All: Спасибо, ребята, за ответы. Если getBlob() поддерживается не всеми, то какой метод лучше использовать? Blob.getBinaryStream() ?

3. Я обычно делаю ResultSet.getBytes() и работаю byte[] вместо этого.

Ответ №4:

Вы можете использовать javax.sql.rowset.serial.SerialBlob.

Я использую его в своем приложении SpringBoot amp; Angular4 следующим образом:

  • получить Base64String из приложения Angular4
  • декодировать строку base64 в байт[]
  • создайте SerialBlob следующим образом: SerialBlob serialBlob = new SerialBlob(byte[])
  • сохраните его в базе данных с помощью JpaRepository

Ответ №5:

Пример

 public void Insert(Object obj){
        try {
            ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
            ObjectOutputStream oos=new ObjectOutputStream(byteArray);
            oos.writeObject(obj);
            PreparedStatement ps= conn1.prepareStatement("insert into vehiculos values(?)");    
            ps.setBytes(1, byteArray.toByteArray());  
            ps.execute();
            ps.close();
        } catch (SQLException ex) {
            System.out.println("ERROR:al hacer un Insert");   
            ex.printStackTrace();
        } catch (IOException ex) {
            Logger.getLogger(Conexion.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    public void ShowData(){
        try {
            Statement stmt = conn1.createStatement();
            String query = "SELECT * FROM vehiculos";
            ResultSet rs = stmt.executeQuery(query);
            Object obj;
            while(rs.next()){
                //Coche c = (Coche)rs.getBlob("coches");
                Blob blob = rs.getBlob("coches");
                ObjectInputStream ois = new ObjectInputStream(blob.getBinaryStream());
                obj = ois.readObject();
                System.out.println(obj.toString());
                System.out.println("");
                /*Blob blob = rs.getBlob("coches");
                byte[] data = blob.getBytes(1, (int)blob.length());*/
                
            }
            rs.close();
            stmt.close();
        
      } catch (SQLException ex) {
            System.out.println("ERROR:al consultar");
            ex.printStackTrace();
      } catch (IOException ex) {
            Logger.getLogger(Conexion.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(Conexion.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    public void cerrar_Conexion (){
       
        try {  
        conn1.close();
      } catch (SQLException ex) {
            System.out.println("ERROR:al cerrar la conexión");
            ex.printStackTrace();
      }
    }