You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:21:08