Java 从JTable和数据库中删除数据

Java 从JTable和数据库中删除数据,java,database,swing,jtable,delete-row,Java,Database,Swing,Jtable,Delete Row,我已经制作了一个JTable,其中填充了数据库中的数据。它从文本字段中获取数据,并将它们添加到表和数据库中。问题是我有一个delete按钮,我让它从表本身(使用defaultTableModel)中删除所选行,但它不会从实际数据库中删除该数据。一旦我再次运行该程序,删除的行就会再次位于JTable中 这可能会变得混乱,但希望有人能找出我遗漏了什么。非常感谢您的帮助,但请不要这样做,我的时间不多,无法彻底检修我的系统(尽管考虑到“添加”按钮的工作原理,我认为这没有必要) 对于所有的代码,我很抱歉,

我已经制作了一个JTable,其中填充了数据库中的数据。它从文本字段中获取数据,并将它们添加到表和数据库中。问题是我有一个delete按钮,我让它从表本身(使用defaultTableModel)中删除所选行,但它不会从实际数据库中删除该数据。一旦我再次运行该程序,删除的行就会再次位于JTable中

这可能会变得混乱,但希望有人能找出我遗漏了什么。非常感谢您的帮助,但请不要这样做,我的时间不多,无法彻底检修我的系统(尽管考虑到“添加”按钮的工作原理,我认为这没有必要)

对于所有的代码,我很抱歉,不确定哪些位会有用,哪些位不会有用,我认为最有用的是添加和删除按钮,它们位于“UpdateView”方法上方的底部

public class MovieReviewSystem extends JFrame {

/**
 * TODO: This method should construct a new MovieReviewSystem window and populate it using the MovieReviewDSC.
 * Before displaying anything, this class should ask the user whether to load *everything* or just
 * the 'useful' reviews.
 */

// Main method to run the class
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new MovieReviewSystem().setVisible(true);
            }

        });
    }


// Load data method 
private Object[][] loadData()
{
    List<MovieReview> movieData;

    try {
        movieData = MovieReviewDSC.list();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        movieData = new ArrayList<>();
    }

    Object[][] data = new Object[movieData.size()][];

    for (int i = 0; i < movieData.size(); ++i)
    {
        MovieReview temp = movieData.get(i);

        data[i] = new Object[]
                {
                temp.getId(),
                temp.getUser(),
                temp.getMovie(),
                temp.isFeatured(),
                temp.getRating(),
                temp.getHelpful(),
                temp.getUnhelpful(),
                temp.getComments()
                };  
    }
    return data;
}

private Object[][] data = loadData();
private String[] columnNames = {"ID", "User", "Movie", "Featured?", "Rating", "Helpful", "Unhelpful"};

private MovieReviewTableModel tableModel = new MovieReviewTableModel(data, columnNames);

JTable table = new JTable(tableModel);

public MovieReviewSystem() {
    setTitle("Movie Review System");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //setMinimumSize(getSize());
    setSize(540,600);

    createTable();
}

    private void createTable()
    {
        final TableRowSorter<TableModel> rowSorter = new TableRowSorter<TableModel>(tableModel);


        //Overall Panel
        JPanel bigPanel = new JPanel(new BorderLayout());
        add(bigPanel);  

        // overall search Panel
        JPanel searchPanel = new JPanel(new BorderLayout());
        searchPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        bigPanel.add(searchPanel, BorderLayout.NORTH);

        // search field panel
        JPanel searchField = new JPanel();
        searchPanel.add(searchField, BorderLayout.NORTH);

        // Radio buttons panel
        JPanel searchRadioButtons = new JPanel();
        searchPanel.add(searchRadioButtons, BorderLayout.SOUTH);

        //Search
        JLabel searchLB = new JLabel("Search with keywords: ");
        searchField.add(searchLB);

        final JTextField searchTF = new JTextField(20); // eclipse says this needs to be final, don't change
        searchField.add(searchTF);

        JButton searchBT = new JButton("Search");
        searchField.add(searchBT);

        JRadioButton allRB = new JRadioButton("All"); 
        searchRadioButtons.add(allRB);
        allRB.setSelected(true); // 'All' selected by default

        JRadioButton usersRB = new JRadioButton("Users");
        searchRadioButtons.add(usersRB);

        JRadioButton moviesRB = new JRadioButton("Movies");
        searchRadioButtons.add(moviesRB);

        // Search Button
        searchBT.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                String searchString = searchTF.getText();
                rowSorter.setRowFilter(RowFilter.regexFilter(searchString, 2)); //Apply search on movie
            }
        });

        // this also allows for pressing enter to search
        searchTF.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                String searchString = searchTF.getText();
                rowSorter.setRowFilter(RowFilter.regexFilter(searchString, 2)); //Apply search on movie

                /*if(moviesRB.isSelected())
                {
                    rowSorter.setRowFilter(RowFilter.regexFilter(searchString, 2)); //Apply search on movie
                }
                else if(usersRB.isSelected())
                {
                    rowSorter.setRowFilter(RowFilter.regexFilter(searchString, 1)); //Apply search on movie
                }
                else
                {
                    rowSorter.setRowFilter(RowFilter.regexFilter(searchString, 1, 2)); //Apply search on movie
                }*/
            }
        });


        // END search field and buttons


        // Three buttons 

        JPanel threeButtonPanel = new JPanel();
        bigPanel.add(threeButtonPanel);

        // Show only Featured
        JButton onlyFeatured = new JButton("Only show Featured");
        threeButtonPanel.add(onlyFeatured);


        // Show only Helpful
        JButton onlyHelpful = new JButton("Only show Helpful");
        threeButtonPanel.add(onlyHelpful);


        // Sort by Movie then Helpfulness Button
        JButton sortByMovieThenHelpfulBT = new JButton("Sort by Movie then Helpfulness");
        threeButtonPanel.add(sortByMovieThenHelpfulBT);

        sortByMovieThenHelpfulBT.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                RowSorter.SortKey sortMovie = new RowSorter.SortKey(2, SortOrder.ASCENDING);
                RowSorter.SortKey sortHelp = new RowSorter.SortKey(5, SortOrder.DESCENDING);

                ArrayList<RowSorter.SortKey> sortKeyList = new ArrayList<RowSorter.SortKey>();
                sortKeyList.add(sortMovie);
                sortKeyList.add(sortHelp);

                rowSorter.setSortKeys(sortKeyList);
            }
        });


        //END Three Buttons


        // *** TABLE ***
        setLayout(new FlowLayout());
        JScrollPane scrollPane = new JScrollPane(table); // table needs to be enclosed in a scrollpane
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // select one row at a time
        table.setPreferredScrollableViewportSize(new Dimension(500,300)); // size
        //table.setFillsViewportHeight(true);
        add(scrollPane);

        setVisible(true);

        // Row Sorter
        table.setRowSorter(rowSorter);

        // *** END Table ***


        //Reset button -- NOT NECESSARY
        JButton resetBT = new JButton("Reset sorting");
        add(resetBT);
        resetBT.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                rowSorter.setSortKeys(null);

            }
        });

        // add button *********************
        JButton addBT = new JButton("Add");
        add(addBT);
        addBT.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                JFrame idFrame = new JFrame();
                String id = JOptionPane.showInputDialog(idFrame, "Enter an ID");


                ReviewEditor editor = new ReviewEditor(MovieReviewSystem.this, id);
                editor.pack();
                editor.setVisible(true);

            }
        });

        // delete button ****************
        JButton deleteBT = new JButton("Delete");
        add(deleteBT, BorderLayout.SOUTH);

        deleteBT.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                int row = table.getSelectedRow();

                if(row != -1)
                {
                    int result = JOptionPane.showConfirmDialog(MovieReviewSystem.this, "Are you sure?");
                    if (result == JOptionPane.OK_OPTION)
                    {
                        tableModel.removeRow(row);

                        MovieReview movieReviewDelete = new MovieReview();
                        movieReviewDelete.setId((String) table.getValueAt(row, 0));
                        movieReviewDelete.setUser((String) table.getValueAt(row, 1));
                        movieReviewDelete.setMovie((String) table.getValueAt(row, 2));
                        movieReviewDelete.setFeatured((boolean) table.getValueAt(row, 3));
                        movieReviewDelete.setRating((int) table.getValueAt(row, 4));
                        movieReviewDelete.setHelpful((int) table.getValueAt(row, 5));
                        movieReviewDelete.setUnhelpful((int) table.getValueAt(row, 6));
                        movieReviewDelete.setComments((String) table.getValueAt(row, 7));



                        try {
                            MovieReviewDSC.delete(movieReviewDelete);
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }

            }
        });


    }


/**
 * TODO This method should attempt to update a MovieReview record in the database.
 * @param isUpdate A boolean to indicate if the record should be updated or created new. If true; the update method should be used.
 * @param review The MovieReview object to be updated or added
 * @return a boolean indicating success (true) or failure (false)
 */
public boolean updateReview(boolean isUpdate, MovieReview review) {

    if (isUpdate = false)
    {
    try {
        MovieReviewDSC.add(review);

    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();

    }

    }
    else
    {
        try {
            MovieReviewDSC.edit(review);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

        }
    }
    return true;

}


}
}

我知道有很多东西要筛选,但我真的很感谢你的帮助

我还需要一些关于编辑按钮的帮助,它会打开ReviewEditor类,它是一个JDialog。我已经让它为我的add工作了,但是我真的不知道如何让它与edit一起工作,它应该在那里获得所选行中的项目,并将它们放在JDialog中相应的文本字段中。但我可能应该把这个留给另一个问题

表格模型

import javax.swing.table.DefaultTableModel;


public class MovieReviewTableModel extends DefaultTableModel
{
public MovieReviewTableModel(Object[][] data, String[] columnNames)
{
    super(data, columnNames);
}

@Override
public Class getColumnClass(int columnIndex)
{
    return getValueAt(0, columnIndex).getClass();
}

@Override
public boolean isCellEditable(int row, int column)
{
    return false;
}


// Ripped this from Tools.java ***
public static void log(Object... args) {
    StringBuilder builder = new StringBuilder();

    for (Object o: args) {
        builder.append(o);
    }

    System.out.println(builder);
}


public void display()
{
    for (int i = 0; i < getRowCount(); i++)
    {
        log(
                "ID: ", getValueAt(i,0),
                "User: ", getValueAt(i,1),
                "Movie: ", getValueAt(i,2),
                "Featured: ", getValueAt(i,3),
                "Rating: ", getValueAt(i,4),
                "Helpful: ", getValueAt(i,5),
                "Unhelpful: ", getValueAt(i,6),
                "Comments: ", getValueAt(i,7));
    }
}

在delete方法中,我建议先从数据库中删除条目,然后再从表中删除条目。假设您有以下简单的表格:

1 A
2 B
3 C
…您删除了第2行。如果我们将数字视为行索引而不是内容,那么您现在拥有的是:

1 A
2 C
当您使用第2行的数据构建要删除的MovieReview记录时(正如您在代码中所做的那样),它实际上将使用数据库中引用第3行的数据

同样,请注意,表格模型行和表格行不一定相同。如果你有一张基本的桌子,你就没事了。但是,如果希望允许用户以任何方式对表进行排序或筛选,则会遇到麻烦。当用户与可见的JTable交互时,将表模型视为位于用户所见内容后面的数据的主副本是有帮助的。用户可以改变其外观,但其数据存储在其背后的原始模型中。如果要从表模型中删除行,以下是一种更安全的方法:

tableModel.removeRow(table.convertRowIndexToModel(row))

最后,我建议只将基本字符串ID传递给delete函数,因为它是您似乎正在使用的记录的唯一部分。这样做可以省去MovieReview实例的构造,简化代码。

在delete方法中,我建议在从表中删除条目之前,先从数据库中删除该条目。假设您有以下简单的表格:

1 A
2 B
3 C
…您删除了第2行。如果我们将数字视为行索引而不是内容,那么您现在拥有的是:

1 A
2 C
当您使用第2行的数据构建要删除的MovieReview记录时(正如您在代码中所做的那样),它实际上将使用数据库中引用第3行的数据

同样,请注意,表格模型行和表格行不一定相同。如果你有一张基本的桌子,你就没事了。但是,如果希望允许用户以任何方式对表进行排序或筛选,则会遇到麻烦。当用户与可见的JTable交互时,将表模型视为位于用户所见内容后面的数据的主副本是有帮助的。用户可以改变其外观,但其数据存储在其背后的原始模型中。如果要从表模型中删除行,以下是一种更安全的方法:

tableModel.removeRow(table.convertRowIndexToModel(row))

最后,我建议只将基本字符串ID传递给delete函数,因为它是您似乎正在使用的记录的唯一部分。这样做可以省去MovieReview实例的构造,简化代码。

很难说,因为我们无法测试。您的db delete方法看起来正常。为什么我觉得这可能与您的筛选功能有关,即在表筛选之后,表视图和表模型数据索引不再相同。这就是为什么我们使用
table.convertRowIndexToModel
,以便
getSelectedRow()
可以转换为实际的模型行。您是否使用打印语句(或调试器)进行过任何调试,以查看正在使用的值?我注意到的另一件事是,您在尝试获取值之前调用
model.deleteRow()
。一旦调用remove row,这些值将不再存在。所以有两件事需要考虑也是,不是原因,但是为什么我们需要创建新的
movieview
的所有字段集,而我们只使用
id
来删除?:-)只是一个观察(似乎不是问题)我不明白你在说什么。是否要同时删除数据库记录和表行?如果是这样的话,那么先删除db记录,然后删除表行是否有意义?此外,您还需要查看
convertRowIndexToModel
。这是一个很好的实践,尤其是在您进行过滤的情况下。关键是,您正在尝试从一行数据中获取值,而这行数据在调用
removeow()
之前已不再是相同的数据,因为我们无法测试。您的db delete方法看起来正常。为什么我觉得这可能与您的筛选功能有关,即在表筛选之后,表视图和表模型数据索引不再相同。这就是为什么我们使用
table.convertRowIndexToModel
,以便
getSelectedRow()
可以转换为实际的模型行。您是否使用打印语句(或调试器)进行过任何调试,以查看正在使用的值?我注意到的另一件事是,您在尝试获取值之前调用
model.deleteRow()