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