无法将数据库Blob格式图片显示到JavaFX TableView的问题求助
问题:数据库Blob图片无法在JavaFX TableView中显示
我尝试将数据库中以Blob格式存储的图片显示到TableView的图片列中,其他数据均能正常展示,唯有图片列无法显示。
现有代码
1. 加载数据到TableView的方法
public void loadPropertyData() throws IOException { try { Connection connection = OracleConnect.getConnection(); String query = "SELECT id, property, image, price, contact, location, status FROM property" + getProfileName().getText(); PreparedStatement statement = connection.prepareStatement(query); ResultSet resultSet = statement.executeQuery(); ObservableList<Property> propertyList = FXCollections.observableArrayList(); while (resultSet.next()) { int id = resultSet.getInt("id"); String property = resultSet.getString("property"); Blob imageBlob = resultSet.getBlob("image"); Image image = null; if (imageBlob != null) { InputStream is = imageBlob.getBinaryStream(); image = new Image(is); } String price = resultSet.getString("price"); String contact = resultSet.getString("contact"); String location = resultSet.getString("location"); String status = resultSet.getString("status"); Property propertyObj = new Property(id, property, image, price, contact, location, status); propertyList.add(propertyObj); } propertyIDColumn.setCellValueFactory(cellData -> cellData.getValue().idProperty().asObject()); propertyColumn.setCellValueFactory(cellData -> cellData.getValue().propertyProperty()); propertyImageColumn.setCellValueFactory(col -> col.getValue().imageProperty()); propertyImageColumn.setCellFactory(col -> { TableCell<Property, Image> cell = new TableCell<Property, Image>() { private final ImageView imageView = new ImageView(); { setContentDisplay(ContentDisplay.GRAPHIC_ONLY); } @Override protected void updateItem(Image item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { imageView.setImage(null); setGraphic(null); } else { imageView.setImage(item); setGraphic(imageView); } } }; return cell; }); propertyPriceColumn.setCellValueFactory(cellData -> cellData.getValue().priceProperty()); propertyContactColumn.setCellValueFactory(cellData -> cellData.getValue().contactProperty()); propertyLocationColumn.setCellValueFactory(cellData -> cellData.getValue().locationProperty()); propertyStatusColumn.setCellValueFactory(cellData -> cellData.getValue().statusProperty()); propertyTableView.setItems(propertyList); resultSet.close(); statement.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); } }
2. Property模型类
public class Property { private IntegerProperty id; private StringProperty property; private ObjectProperty<Image> image; private StringProperty price; private StringProperty contact; private StringProperty location; private StringProperty status; public Property(int id, String property, Image image, String price, String contact, String location, String status) { this.id = new SimpleIntegerProperty(id); this.property = new SimpleStringProperty(property); this.image = new SimpleObjectProperty<>(image); this.price = new SimpleStringProperty(price); this.contact = new SimpleStringProperty(contact); this.location = new SimpleStringProperty(location); this.status = new SimpleStringProperty(status); } public IntegerProperty idProperty() { return id; } public int getId() { return id.get(); } public void setId(int id) { this.id.set(id); } public StringProperty propertyProperty() { return property; } public String getProperty() { return property.get(); } public void setProperty(String property) { this.property.set(property); } public ObjectProperty<Image> imageProperty() { return image; } public Image getImage() { return image.get(); } public void setImage(Image image) { this.image.set(image); } public StringProperty priceProperty() { return price; } public String getPrice() { return price.get(); } public void setPrice(String price) { this.price.set(price); } public StringProperty contactProperty() { return contact; } public String getContact() { return contact.get(); } public void setContact(String contact) { this.contact.set(contact); } public StringProperty locationProperty() { return location; } public String getLocation() { return location.get(); } public void setLocation(String location) { this.location.set(location); } public StringProperty statusProperty() { return status; } public String getStatus() { return status.get(); } public void setStatus(String status) { this.status.set(status); } }
3. 创建数据库表及插入数据的代码
@FXML private void Signup() { Connection connection = null; PreparedStatement createTableStatement = null; PreparedStatement createSequenceStatement = null; PreparedStatement insertStatement = null; try { connection = OracleConnect.getConnection(); // Create table String createTableProperty = "CREATE TABLE property" + signupTF.getText() + " (" + " id NUMBER," + " property VARCHAR2(50)," + " image BLOB," + " price VARCHAR2(50)," + " contact VARCHAR2(50)," + " location VARCHAR2(50)," + " status VARCHAR2(50)" + ")"; createTableStatement = connection.prepareStatement(createTableProperty); createTableStatement.execute(); // Create sequence String createSequenceProperty = "CREATE SEQUENCE property" + signupTF.getText() + "_seq " + "START WITH 1 " + "INCREMENT BY 1 " + "MINVALUE 1 " + "NOCACHE"; createSequenceStatement = connection.prepareStatement(createSequenceProperty); createSequenceStatement.execute(); // Insert data String insertData = "INSERT INTO property" + signupTF.getText() + " (id, property, image, price, contact, location, status)" + " VALUES (property" + signupTF.getText() + "_seq.nextval, ?, ?, ?, ?, ?, ?)"; insertStatement = connection.prepareStatement(insertData); insertStatement.setString(1, "Property Name"); // Set the property name insertStatement.setBlob(2, new FileInputStream(new File("path/to/image.jpg"))); // Set the image file insertStatement.setString(3, "Price"); // Set the price insertStatement.setString(4, "Contact"); // Set the contact insertStatement.setString(5, "Location"); // Set the location insertStatement.setString(6, "Status"); // Set the status insertStatement.execute(); } catch (SQLException e) { if (e.getErrorCode() == 1400) { JOptionPane.showMessageDialog(null, "Please enter required information"); } else { JOptionPane.showMessageDialog(null, "An error occurred: " + e.getMessage()); } } catch (FileNotFoundException e) { JOptionPane.showMessageDialog(null, "Image file not found: " + e.getMessage()); } finally { try { if (insertStatement != null) { insertStatement.close(); } if (createSequenceStatement != null) { createSequenceStatement.close(); } if (createTableStatement != null) { createTableStatement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { JOptionPane.showMessageDialog(null, "An error occurred while closing the resources: " + e.getMessage()); } } }
现状说明
- 数据库表中已存储包含Blob图片的数据,表内图片字段显示有内容
- TableView中ID、名称、价格等列均正常展示,仅图片列无任何内容
排查与解决建议
1. 验证Image对象是否有效
在加载图片的代码块中添加日志,确认从Blob生成的Image对象是否正常:
if (imageBlob != null) { InputStream is = imageBlob.getBinaryStream(); image = new Image(is); // 打印日志验证 System.out.println("Image状态: " + (image != null) + ",宽度: " + (image != null ? image.getWidth() : 0)); }
如果Image宽度为0,说明数据流读取不完整或图片格式不兼容。
2. 关闭Blob输入流
使用try-with-resources自动关闭输入流,避免资源泄漏导致数据读取异常:
if (imageBlob != null) { try (InputStream is = imageBlob.getBinaryStream()) { image = new Image(is); } catch (IOException e) { e.printStackTrace(); } }
3. 设置ImageView显示尺寸
默认ImageView可能尺寸为0,导致图片不可见,在TableCell初始化时添加尺寸设置:
{ setContentDisplay(ContentDisplay.GRAPHIC_ONLY); imageView.setFitWidth(80); imageView.setFitHeight(80); imageView.setPreserveRatio(true); // 保持图片比例 }
4. 确认查询表名正确性
检查查询语句中拼接的表名property + getProfileName().getText()是否和创建的表名完全一致,避免查询错误表导致图片数据为空。
5. 处理JavaFX线程问题
如果loadPropertyData在后台线程执行,需确保Image对象在JavaFX应用线程中创建:
if (imageBlob != null) { byte[] imageBytes = imageBlob.getBytes(1, (int) imageBlob.length()); Platform.runLater(() -> { image = new Image(new ByteArrayInputStream(imageBytes)); }); }
内容的提问来源于stack exchange,提问作者phamnguyen
相关产品推荐
相关产品推荐

