JavaFX:获取表格行按钮所在行数据并执行SQL删除
JavaFX表格行内按钮获取行数据执行删除的解决方案
问题背景
在JavaFX项目里,点击表格行内的归还按钮时,需要拿到该行对应的借阅记录数据来执行SQL删除操作,但现在点击按钮根本拿不到行数据。已经用FXML搭好了表格和列,通过MainController和HomeController填数据、加按钮,试了好几种方法都没解决。
解决思路
当前代码的问题在于,创建按钮时没把它和对应的行数据绑定起来,导致点击时不知道对应哪条记录。我们需要让按钮事件能关联到这条记录的关键信息(比如数据库里的借阅ID),或者直接拿到当前行的BorrowedBook对象。
具体步骤
1. 给BorrowedBook实体补全字段
首先得让BorrowedBook能存数据库里borrowed_books表的id,毕竟删除需要这个主键。修改实体类:
public class BorrowedBook { private int borrowId; // 新增:对应borrowed_books的id private String title; private String dateStart; private String dateEnd; private int remainingDays; private Button button; // 构造方法要加上borrowId参数 public BorrowedBook(int borrowId, String title, String dateStart, String dateEnd, int remainingDays, Button button) { this.borrowId = borrowId; this.title = title; this.dateStart = dateStart; this.dateEnd = dateEnd; this.remainingDays = remainingDays; this.button = button; } // 加个getter方法 public int getBorrowId() { return borrowId; } // 原来的getter方法保留... }
2. 修改HomeController,绑定按钮和行数据
在getBorrowedBooks方法里,创建按钮的时候直接把当前行的借阅ID捕获到事件里,这样点击按钮就能直接用这个ID删数据:
public ObservableList<BorrowedBook> getBorrowedBooks(int userId){ DatabaseConnection connectionNew = new DatabaseConnection(); Connection connectDB = connectionNew.getConnection(); String books = "SELECT b.Title,a.borrowDate,a.returnDate,a.id FROM borrowed_books a INNER JOIN books b on a.bookId = b.Id INNER JOIN users c on a.userId = c.Id WHERE a.userId = " + userId; try{ Statement statement = connectDB.createStatement(); ResultSet rs = statement.executeQuery(books); while(rs.next()){ int remainingDays = getDaysDiff(rs.getString("ReturnDate")); int borrowId = rs.getInt("id"); // 拿到这条借阅记录的ID String bookTitle = rs.getString("Title"); Button returnOnClick = new Button("Inapoiaza"); // 事件里直接用borrowId returnOnClick.setOnAction(event -> { System.out.println("要删除的借阅记录ID:" + borrowId); // 调用删除方法 deleteBorrowedRecord(borrowId); // 删完之后把列表里的这条记录去掉,UI自动更新 recordsBorrowedBooks.removeIf(book -> book.getBorrowId() == borrowId); }); // 创建BorrowedBook时传入borrowId BorrowedBook borrowedBook = new BorrowedBook(borrowId, bookTitle, rs.getString("BorrowDate"), rs.getString("ReturnDate"), remainingDays, returnOnClick); recordsBorrowedBooks.add(borrowedBook); } }catch (Exception e) { throw new RuntimeException("unhandled", e); } return recordsBorrowedBooks; } // 新增删除方法 private void deleteBorrowedRecord(int borrowId) { DatabaseConnection connectionNew = new DatabaseConnection(); try (Connection connectDB = connectionNew.getConnection()) { String deleteSql = "DELETE FROM borrowed_books WHERE id = ?"; PreparedStatement pstmt = connectDB.prepareStatement(deleteSql); pstmt.setInt(1, borrowId); pstmt.executeUpdate(); } catch (SQLException e) { throw new RuntimeException("删除借阅记录失败", e); } }
3. 另一种方法:通过表格单元格获取行数据
如果你想拿到完整的BorrowedBook对象,可以在MainController的setBorrowedData里改列的单元格工厂,让按钮事件通过表格API拿当前行数据:
public void setBorrowedData(){ colBorrowedTitle.setCellValueFactory(new PropertyValueFactory<>("Title")); colBorrowedDateStart.setCellValueFactory(new PropertyValueFactory<>("DateStart")); colBorrowedDateEnd.setCellValueFactory(new PropertyValueFactory<>("DateEnd")); colBorrowedRemainingDays.setCellValueFactory(new PropertyValueFactory<>("RemainingDays")); // 改colActions的单元格工厂,在这里绑定按钮事件 colActions.setCellFactory(column -> new TableCell<BorrowedBook, Button>() { @Override protected void updateItem(Button item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setGraphic(null); } else { setGraphic(item); item.setOnAction(event -> { // 拿到当前行的BorrowedBook对象 BorrowedBook currentBook = getTableView().getItems().get(getIndex()); System.out.println("要归还的书:" + currentBook.getTitle() + ",记录ID:" + currentBook.getBorrowId()); // 调用删除方法 new HomeController().deleteBorrowedRecord(currentBook.getBorrowId()); // 刷新表格 getTableView().getItems().remove(currentBook); }); } } }); HomeController homeController = new HomeController(); tableViewBorrowed.setRowFactory( tv -> { TableRow<BorrowedBook> row = new TableRow<>(){ @Override public void updateItem(BorrowedBook item, boolean empty) { super.updateItem(item, empty) ; if (item == null) { setStyle(""); } else if (item.getRemainingDays() < 0) { setStyle("-fx-background-color: #ff5d5d;"); } else { setStyle(""); } } }; return row ; }); tableViewBorrowed.setItems(homeController.getBorrowedBooks(Global.getUserId())); }
注意:用这种方法的话,HomeController里创建按钮时就别绑定事件了,不然会重复触发。
要点总结
- 要么在创建按钮时直接捕获当前行的关键数据(比如借阅ID),要么通过表格的API获取当前行对象。
- 删除数据库记录后,一定要把ObservableList里对应的元素删掉,这样表格UI才会同步更新。
内容的提问来源于stack exchange,提问作者Kratos
相关产品推荐
相关产品推荐

