2016-01-28 2 views
0

Так что я пытаюсь получить текст и кадр (изображение) из базы данных внутри jtable в хорошем смысле. По какой-то причине, когда я пытаюсь извлечь блоб я получаю это:пытается извлечь текст и blob из mysql в jtable

[email protected] 

в любой другой колонке, хотя я указал, что капля находится на 8-м!

вот скриншот:

http://s24.postimg.org/t71o3izlh/Screen_Shot_2016_01_28_at_1_26_55_PM.png

enter image description here

Вот мой код

sql = "SELECT * FROM Products"; 

ResultSet rs = stmt.executeQuery(sql); 

    ResultSetMetaData rsmd = rs.getMetaData(); 
// getting the columns number 
    int columnsNumber = rsmd.getColumnCount(); 

// setting a vector with columns number 
Vector columns = new Vector(columnsNumber); 


// adding column names 
for(int i=1; i<=columnsNumber; i++) 
columns.add(rsmd.getColumnName(i)); 

// setting a vector with row data 
Vector rowdata = new Vector(); 
Vector row; 
JTable table = new JTable(rowdata, columns); 

while(rs.next()) 
{ 

row = new Vector(columnsNumber); 

    for(int i=1; i<=columnsNumber; i++) 
    { 
    // adding the rows in "row vector" 
    InputStream binaryStream = rs.getBinaryStream(i); 
    row.add(rs.getString(i)); 
    row.add(rs.getBinaryStream(8)); 

} 
// adding the rows in the database 
rowdata.add(row); 
} 

Может кто-нибудь объяснить мне, почему этот подход не делает работу?

кстати, если я удалил эту строку:

row.add(rs.getBinaryStream(8)); 

Проблема получение java.io.ByteArrayInputSteam исчезнет, ​​однако, я буду получать только текстовое представление изображения.

Это на самом деле не дубликат, потому что я пытаюсь добавить его в определенный столбец в зависимости от того, сколько строк у меня есть, которые представляют собой ОБА текст и изображение. Так что это динамически сделано, и sql имеет как изображение, так и текст в то же время, в отличие от «возможного дубликата»

Заранее благодарен!

+0

Массив байт является двоичным представлением изображения, то вам необходимо преобразовать это обратно в «образ» своего рода – MadProgrammer

+0

@MadProgrammer на самом деле это не дубликат, потому что я пытаюсь добавить это в определенном столбце в зависимости от того, сколько строк у меня есть. Так что это динамически сделано, и sql имеет как изображение, так и текст в то же время, в отличие от «возможного дубликата» – rullzing

+0

. Итак, вы не знаете, какие данные действительно находятся в столбце, и вы не знаете, как его декодировать?Как общий комментарий к вашим требованиям, это просто звучит безумно. Вам либо нужны два столбца, один для текста и один для изображения, либо вам нужен другой столбец для указания типа данных. В качестве общей концепции столбец должен быть репрезентативным для типа данных, которые он хранит, например 'image' и' text', а не 'data', что исключает возможность когда-либо узнать, какой тип данных он фактически представляет – MadProgrammer

ответ

1

Итак, у вас, похоже, есть ряд сложных проблем. Давайте начнем здесь, где вы загружаете данные из базы данных ...

while(rs.next()) 
    { 
     row = new Vector(columnsNumber); 

     for(int i=1; i<=columnsNumber; i++) 
     { 
      // adding the rows in "row vector" 
      InputStream binaryStream = rs.getBinaryStream(i); 
      row.add(rs.getString(i)); 
      row.add(rs.getBinaryStream(8)); 
     } 
     // adding the rows in the database 
     rowdata.add(row); 
    } 

Таким образом, для каждой строки в ResultSet вы смотрите через колонку, НО, для каждого столбца, добавьте значение String И каплю из последнего столбца, поэтому blob будет добавлен 6 раз (на основе вашего снимка экрана). Это, очевидно, не то, что вы хотите, а также причина, по которой вы получаете [email protected] в каждом другом столбце.

Вместо этого, вы хотите, чтобы петли через колонку 1 - columnsNumbers - 1, потому что мы не хотим, чтобы последний столбец, и добавить изображение в последнюю колонку, может быть что-то вроде ...

while(rs.next()) 
{ 
    row = new Vector(columnsNumber); 

    for(int i=1; i < columnsNumber; i++) 
    { 
     // adding the rows in "row vector" 
     InputStream binaryStream = rs.getBinaryStream(i); 
     row.add(rs.getString(i)); 
    } 
    row.add(rs.getBinaryStream(8)); 
    // adding the rows in the database 
    rowdata.add(row); 
} 

Следующей проблемы ...

Все еще печатает [email protected] в последней колонке !?

Это просто потому, что все, что вы добавили в rowVector, было двоичным потоком, представляющим двоичные данные в базе данных, JTable не имеет средств для этого.Вы должны начать иметь взгляд на Concepts: Editors and Renderers и Using Custom Renderers для получения более подробной информации о том, как вы можете настроить представление этих компонентов

Во-первых, нужно преобразовать двоичные данные в формат изображения, который мы можем использовать

row.add(ImageIO.read(rs.getBinaryStream(8))); 

и использовать что-то подобное тому, что описано в Rendering BufferedImage in JTable cell

или

row.add(new ImageIcon(ImageIO.read(rs.getBinaryStream(8)))); 

, который должен позволить «по умолчанию» TableCellRenderer, чтобы сделать его

Runnable Пример ...

Предупреждение: Этот пример немного долго, потому что я должен был построить базу данных и заполнить его. Для простоты он использует автономный H2 Database engine, но его следует переводить в большинство других баз данных. В примере также используется тип столбца blob, это преднамеренно, так как это улучшает производительность механизма базы данных.

Проблема с получением изображений для отображения в JTable при использовании DefaultTableModel есть DefaultTableModel возвращает Object.class от метода TableModel#getColumnClass

Даже документация DefaultTableModel делает это к сведению ...

Предупреждения :DefaultTableModel возвращает класс столбцов Object. Когда DefaultTableModel используется с TableRowSorter это приведет к широкому использованию toString, который для не String типов данных стоит дорого. Если вы используете DefaultTableModel с TableRowSorter, настоятельно рекомендуется переопределить getColumnClass, чтобы вернуть соответствующий тип.

я преодолел это, настраивая DefaultTableModel я вернулся из TestPane#makeTableModel ...

DefaultTableModel model = new DefaultTableModel(new String[]{"Name", "Image"}, 0) { 
    @Override 
    public Class<?> getColumnClass(int columnIndex) { 
     return columnIndex == 1 ? Icon.class : super.getColumnClass(columnIndex); 
    } 
}; 

Это позволило JTable использовать правильный TableCellRenderer

Fruits

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.image.BufferedImage; 
import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.IOException; 
import java.io.InputStream; 
import java.sql.Blob; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import javax.imageio.ImageIO; 
import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.table.DefaultTableModel; 

public class Main { 

    public static void main(String[] args) { 
     try { 
      Class.forName("org.h2.Driver"); 
      makeDatabase(); 
      populateDatabase(); 
      new Main(); 
     } catch (ClassNotFoundException | SQLException | IOException exp) { 
      exp.printStackTrace(); 
     } 
    } 

    protected static Connection makeConnection() throws SQLException { 
     String path = "jdbc:h2:./TestDatabase"; 
     return DriverManager.getConnection(path, "sa", ""); 
    } 

    protected static void makeDatabase() throws SQLException { 
     String cmd = "create table if not exists fruits (" 
       + "key BIGINT IDENTITY, " 
       + "name varchar(128), " 
       + "image longblob)"; 
     try (Connection con = makeConnection()) { 
      try (PreparedStatement stmt = con.prepareStatement(cmd)) { 
       System.out.println("> Make fruits table"); 
       stmt.executeUpdate(); 
      } 
     } 
    } 

    protected static void populateDatabase() throws SQLException, IOException { 
     removeAlFruits(); 
     insert("Apple", ImageIO.read(new File("Apple.png"))); 
     insert("Banana", ImageIO.read(new File("Banana.png"))); 
     insert("Cherries", ImageIO.read(new File("Cherries.png"))); 
     insert("Grapes", ImageIO.read(new File("Grapes.png"))); 
     insert("Orange", ImageIO.read(new File("Orange.png"))); 
     insert("Pear", ImageIO.read(new File("Pear.png"))); 
     insert("Pine Apple", ImageIO.read(new File("PineApple.png"))); 
     insert("Strewberry", ImageIO.read(new File("Strewberry.png"))); 
     insert("Water Melon", ImageIO.read(new File("WaterMelon.png"))); 
    } 

    protected static void insert(String name, BufferedImage image) throws SQLException, IOException { 
     String cmd = "insert into fruits (name, image) values (?, ?)"; 
     try (Connection con = makeConnection()) { 
      try (PreparedStatement stmt = con.prepareStatement(cmd)) { 
       try (InputStream is = convertImageToInputStream(image)) { 
        System.out.println("> Insert " + name); 
        stmt.setString(1, name); 
        stmt.setBinaryStream(2, is); 
        int rows = stmt.executeUpdate(); 
        System.out.println("> " + rows + " rows updated"); 
       } 
      } 
     } 
    } 

    protected static InputStream convertImageToInputStream(BufferedImage image) throws IOException { 
     ByteArrayOutputStream baos = null; 
     ByteArrayInputStream bais = null; 
     try { 
      baos = new ByteArrayOutputStream(); 
      ImageIO.write(image, "png", baos); 
      baos.close(); 
      bais = new ByteArrayInputStream(baos.toByteArray()); 
     } finally { 
      if (baos != null) { 
       try { 
        baos.close(); 
       } catch (IOException ex) { 
       } 
      } 
     } 
     return bais; 
    } 

    protected static void removeAlFruits() throws SQLException { 
     String cmd = "delete from fruits"; 
     try (Connection con = makeConnection()) { 
      try (PreparedStatement stmt = con.prepareStatement(cmd)) { 
       System.out.println("> Remove all fruits"); 
       int rows = stmt.executeUpdate(); 
       System.out.println("> " + rows + " rows updated"); 
      } 
     } 
    } 

    public Main() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        try { 
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
         ex.printStackTrace(); 
        } 

        JFrame frame = new JFrame("Testing"); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.add(new TestPane()); 
        frame.pack(); 
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true); 
       } catch (SQLException | IOException ex) { 
        ex.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() throws SQLException, IOException { 
      setLayout(new BorderLayout()); 
      DefaultTableModel model = makeTableModel(); 
      JTable table = new JTable(model); 
      table.setRowHeight(100); 
      add(new JScrollPane(table)); 
     } 

     protected DefaultTableModel makeTableModel() throws SQLException, IOException { 
      DefaultTableModel model = new DefaultTableModel(new String[]{"Name", "Image"}, 0) { 
       @Override 
       public Class<?> getColumnClass(int columnIndex) { 
        return columnIndex == 1 ? Icon.class : super.getColumnClass(columnIndex); 
       } 

      }; 
      String cmd = "select name, image from fruits"; 
      try (Connection con = makeConnection()) { 
       try (PreparedStatement stmt = con.prepareStatement(cmd)) { 
        try (ResultSet rs = stmt.executeQuery()) { 
         while (rs.next()) { 
          String name = rs.getString(1); 
          Blob blob = rs.getBlob(2); 
          ImageIcon icon = null; 
          try (InputStream is = blob.getBinaryStream()) { 
           BufferedImage img = ImageIO.read(is); 
           icon = new ImageIcon(img); 
          } 
          model.addRow(new Object[]{name, icon}); 
         } 
        } 
       } 
      } 
      return model; 
     } 

    } 
} 

Альтернативного заключается в использовании пользовательское TableCellRender как показано в Rendering BufferedImage in JTable cell

+0

На самом деле это даже не печать 'java.io.ByteArrayInputStream @ 1cb63183' в последнем столбце. Это похоже на чтение строки изображения так, как если бы вы открыли изображение с помощью блокнота – rullzing

+0

Что это за печать в последнем столбце? Как изображения вставлены в базу данных? – MadProgrammer

+0

получается, что метод ImageIcon действительно работает, и я смог просмотреть изображение с помощью showMessageDialog. Поэтому мне нужно найти способ поместить его в Jtable. Вот скриншот того, что он печатает: http://s21.postimg.org/6ku22ajjr/Screen_Shot_2016_01_28_at_5_30_39_PM.png. Изображение вставляется с помощью JFileChooser и FileInputStream – rullzing

Смежные вопросы