删除或插入

时间:2017-05-08 20:51:25

标签: java swing jtable abstracttablemodel

我有一个使用ResultSet& AbstractTableModel由Access DB填充的JTable。我有一个方法可以正确地从DB中删除记录,但是在刷新表模型的当前视图时遇到问题。我查看了类似的帖子,并尝试使用fireTableRowsDeletedfireTableDataChanged,但没有运气。我还注意到其他帖子提到DefaultTableModel的使用,因为它添加/删除行方法,但我工作的代码来自我去年使用过的Java教科书(教授从未达到过这一点,所以我试过自己学习)...

这是自定义JFrame的类:



class AdministrationFrame extends JFrame
{
	//set variable for location of database
	private static final File DB_FILE = 
			new File("C:\\Eclipse\\EmpInOutBoard - TEMP.accdb");	
	
	//database URL
	private static final String DB_URL = "jdbc:ucanaccess://" + DB_FILE.getAbsolutePath();
	
	//set default query to retrieve all users sorted by last name
	private static final String DEFAULT_QUERY = 
			"SELECT EmployeeNo, FirstName, LastName, DisplayName, GroupName, CompanyName "
		  + "FROM Employees "
		  + "WHERE DisabledState = false "
		  + "ORDER BY LastName";
	
	//layout for window
	private final BorderLayout layout;
	
	//administration window
	private final JFrame adminFrame;
	
	private final JPanel tablePanel;
	private final JPanel tablePanel2;
	private final JPanel buttonPanel;
	
	//items for tablePanel
	private final JLabel filterLabel;
	private final JTextField filterTextField;
	private final JButton filterButton;
	
	//items for buttonPanel
	private final JButton updateButton;
	private final JButton deleteButton;
	
	private String employeeID;
	
	private Connection conn;
	
	private JTable resultTable;
	
	private static ResultSetTableModel tblModel;
	
	public AdministrationFrame()
	{
		layout = new BorderLayout(10, 10);
		setLayout(layout);
		
		//place GUI components on JFrame's content pane
		adminFrame = new JFrame("Employee Modification Panel");
		
		//set up JPanels
		tablePanel = new JPanel();
		tablePanel2 = new JPanel();
		
		String tablePanelTitle = "Employee Details";
		tablePanel.setBorder(BorderFactory.createTitledBorder(null, 
				tablePanelTitle, TitledBorder.CENTER, TitledBorder.TOP,
				new Font("Arial", Font.BOLD + Font.ITALIC, 22), Color.BLACK));
		
		tablePanel2.setLayout(new BoxLayout(tablePanel2, BoxLayout.Y_AXIS));
		
		buttonPanel = new JPanel();
		
		//set up items in each JPanel
		filterLabel = new JLabel("Filter:");
		filterLabel.setAlignmentX(LEFT_ALIGNMENT);
		filterTextField = new JTextField();
		filterTextField.setAlignmentX(LEFT_ALIGNMENT);
		filterButton = new JButton("Apply Filter");
		filterButton.setAlignmentX(LEFT_ALIGNMENT);
		
		updateButton = new JButton("Add/Update");
		deleteButton = new JButton("Delete");
		
		//create ResultSetTableModel and display database table
		try
		{
			//create TableModel for results of the default query
			tblModel = new ResultSetTableModel(DB_URL, DEFAULT_QUERY);
			
			//create JTable based on the tblModel
			resultTable = new JTable(tblModel)
			{
				@Override
				public Dimension getPreferredScrollableViewportSize()
				{
					return new Dimension(600, 250);
				}
			};
			
			resultTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
			resultTable.getTableHeader().setResizingAllowed(false); //disable column resizing
			resultTable.getTableHeader().setReorderingAllowed(false); //disable column dragging
			resultTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); //sets table to only allow selection of single row
			resultTable.getSelectionModel().addListSelectionListener(new RowListener()); //register event handlers
			final JScrollPane tablePane = new JScrollPane(resultTable);
			
			//add items to JPanels
			tablePanel2.add(filterLabel);
			tablePanel2.add(Box.createRigidArea(new Dimension(0, 2)));
			tablePanel2.add(filterTextField);
			tablePanel2.add(Box.createRigidArea(new Dimension(0, 10)));
			tablePanel2.add(filterButton);
			
			tablePanel.add(tablePane);
			tablePanel.add(tablePanel2);
						
			buttonPanel.add(updateButton);
			buttonPanel.add(deleteButton);


			//add JPanels to frame
			adminFrame.add(tablePanel, BorderLayout.NORTH);
			adminFrame.add(buttonPanel, BorderLayout.SOUTH);			

			final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(tblModel);
			resultTable.setRowSorter(sorter);
			
			//create listener for filterButton
			filterButton.addActionListener(new ActionListener()
			{
				//pass filter text to Listener
				public void actionPerformed(ActionEvent e)
				{
					String text = filterTextField.getText();
					
					if (text.length() == 0)
						sorter.setRowFilter(null);
					else
					{
						try
						{
							//make filter case-insensitive
							sorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
						}
						catch (PatternSyntaxException pse)
						{
							JOptionPane.showMessageDialog(null, "Bad regex pattern",
									"Bad regex pattern", JOptionPane.ERROR_MESSAGE);
						}
					}
				}
			});
			
			deleteButton.addActionListener(new ActionListener()
			{
				@Override
				public void actionPerformed(ActionEvent e)
				{
					if(employeeID != null && !employeeID.isEmpty())
					{
						try
						{
							deleteFromTable(employeeID);
							JOptionPane.showMessageDialog(null, "User " + employeeID + " deleted from the table",
									"Successful Deletion", JOptionPane.PLAIN_MESSAGE);
							
							//tblModel.fireTableRowsDeleted(resultTable.getSelectedRow(), resultTable.getSelectedRow());

						} 
						catch (SQLException e1) 
						{
							e1.printStackTrace();
						}
					}
					else
					{
						JOptionPane.showMessageDialog(null, "No user selected. Cannot perform delete.",
								"ERROR", JOptionPane.ERROR_MESSAGE);
					}
				}
			});
			
			pack();
			
			//dispose of window when user quits application
			//(do not want to close application)
			adminFrame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
			adminFrame.setSize(800, 400);
			adminFrame.setVisible(true);
			adminFrame.setLocationRelativeTo(null);
			adminFrame.setResizable(false);
			
			//ensure database is closed when user quits application
			adminFrame.addWindowListener(new WindowAdapter()
			{
				//disconnect from database and exit when window has closed
				public void windowClosed(WindowEvent event)
				{
					tblModel.disconnectFromDatabase();
					System.exit(0);
				}
			});
		}
		catch (SQLException sqlException)
		{
			JOptionPane.showMessageDialog(null, sqlException.getMessage(),
					"Database error", JOptionPane.ERROR_MESSAGE);
			tblModel.disconnectFromDatabase();
			System.exit(1); //terminate application
		}
	}
	
	private class RowListener implements ListSelectionListener
	{
		@Override
		public void valueChanged(ListSelectionEvent event)
		{
			if(!event.getValueIsAdjusting())
			{
				int row = resultTable.getSelectedRow();
				if(row == -1) //no row found
					JOptionPane.showMessageDialog(adminFrame, "Selected row not found in filtered set",
							null, JOptionPane.WARNING_MESSAGE);
				else
				{
					employeeID = resultTable.getValueAt(row, resultTable.getColumn("EmployeeNo").getModelIndex()).toString();
				}
			}
		}
	};

	//updates DB to delete selected user/record from the table
	public void deleteFromTable(String empID) throws SQLException
	{
		PreparedStatement prepStmnt = null;
		
		String deleteSQL = "DELETE "
						 + "FROM Employees "
						 + "WHERE EmployeeNo = ?";
		try
		{
			conn = DriverManager.getConnection(DB_URL);
			conn.setAutoCommit(false);
			
			prepStmnt = conn.prepareStatement(deleteSQL);
			prepStmnt.setString(1, empID);
			prepStmnt.executeUpdate();
			conn.commit();
		}
		catch (SQLException sqlExcep)
		{
			sqlExcep.printStackTrace();
			if(conn != null)
			{
				try
				{
					System.err.print("Rolling back transaction");
					conn.rollback();
				}
				catch (SQLException excep)
				{
					excep.printStackTrace();
				}
			}
			System.exit(1); //terminate application
		}
		finally //close the connection
		{
			if(prepStmnt != null)
				prepStmnt.close();
			
			conn.setAutoCommit(true);
			conn.close();
		}
	}
	
}//end class EmpInOutBoard
&#13;
&#13;
&#13;

这里是AbstractTableModel的类(从我的教科书中略微修改):

&#13;
&#13;
class ResultSetTableModel extends AbstractTableModel
{
	private final Connection connection;
	private final Statement statement;
	private ResultSet resultSet;
	private ResultSetMetaData resultSetMetaData;
	private int numRowCount;

	//track DB connection status
	private boolean dbConnStatus = false;
	
	//constructor initializes rSet and obtains its
	//metadata object; also determines number of rows
	public ResultSetTableModel(String url, String query) throws SQLException
	{
		//connect to the database
		connection = DriverManager.getConnection(url);
		
		//create statement to query database
		statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
		
		//update database connection status
		dbConnStatus = true;
		
		//set query and execute it
		setQuery(query);
	}
	
	//get class that represents column type
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Class getColumnClass(int column) throws IllegalStateException
	{
		//ensure database connection is available
		if(!dbConnStatus)
			throw new IllegalStateException("No connection to the Database");
		
		//determine Java class of column
		try
		{
			String className = resultSetMetaData.getColumnClassName(column + 1);
			
			//return Class object that represents class Name
			return Class.forName(className);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
		return Object.class; //if problems occur above, assume type Object
	}
	
	//remove row in the ResultSet
	public void removeRow(int row)
	{
//		try
//		{
//			resultSet.absolute(row);
//			resultSet.deleteRow();
//		}
//		catch (SQLException e)
//		{
//			e.printStackTrace();
//		}
//		fireTableRowsDeleted(row, row);
	}
	
	//get the number of columns in the ResultSet
	public int getColumnCount() throws IllegalStateException
	{
		//ensure database connection is available
		if(!dbConnStatus)
			throw new IllegalStateException("No connection to the Database");
		
		//determine number of columns
		try
		{
			return resultSetMetaData.getColumnCount();
		}
		catch (SQLException sqlException)
		{
			sqlException.printStackTrace();
		}
		
		return 0; //if problem occur above, return 0 for number of columns
	}
	
	//get name of a particular column in ResultSet
	public String getColumnName(int column) throws IllegalStateException
	{
		//ensure database connection is available
		if(!dbConnStatus)
			throw new IllegalStateException("No connection to the Database");
		
		//determine column name
		try
		{
			return resultSetMetaData.getColumnName(column + 1);
		}
		catch (SQLException sqlException)
		{
			sqlException.printStackTrace();
		}
		
		return ""; //if problems occur above, return empty string for column name	
	}
	
	//return number of rows in ResultSet
	public int getRowCount() throws IllegalStateException
	{
		//ensure database connection is available
		if(!dbConnStatus)
			throw new IllegalStateException("No connection to the Database");
		
		return numRowCount;	
	}
	
	//obtain value in particular row and column
	public Object getValueAt(int row, int column) throws IllegalStateException
	{
		//ensure database connection is available
		if(!dbConnStatus)
			throw new IllegalStateException("No connection to the Database");
		
		//obtain a value at specified ResultSet row and column
		try
		{
			resultSet.absolute(row + 1);
			return resultSet.getObject(column + 1);
		}
		catch (SQLException sqlException)
		{
			sqlException.printStackTrace();
		}
		
		return ""; //if problems occur above, return empty string object		
	}
	
	//set new database query string
	public void setQuery(String query) throws SQLException, IllegalStateException
	{
		//ensure database connection is available
		if(!dbConnStatus)
			throw new IllegalStateException("No connection to the Database");
		
		//specify query and execute it
		resultSet = statement.executeQuery(query);
		
		//obtain metadata for ResultSet
		resultSetMetaData = resultSet.getMetaData();
		
		//determine number of rows in ResultSet
		resultSet.last(); //move to last row
		numRowCount = resultSet.getRow(); //get row number
		
		//notify JTable that model has changed
		fireTableStructureChanged();
	}
	
	//close Statement and Connection
	public void disconnectFromDatabase()
	{
		//ensure database connection is available
		if(dbConnStatus);
		
		//determine number of columns
		try
		{
			resultSet.close();
			statement.close();
			connection.close();
		}
		catch (SQLException sqlException)
		{
			sqlException.printStackTrace();
		}
		finally
		{
			dbConnStatus = false;
		}
		
	}
} //end class ResultSetTableModel
&#13;
&#13;
&#13;

正如您所看到的,我已尝试在第二个类中添加removeRow方法但最终收到错误:attempt to assign to non-updatable column。刷新我的桌子模型我缺少什么?我愿意将此更改为使用DefaultTableModel及其内置方法,如果这更容易/更简单。感谢

1 个答案:

答案 0 :(得分:0)

我没有使用直接行索引,因为如果用户按任意一列对数据进行排序,则可能会发生变化。我觉得,既然employeeID是独一无二的,那就更好地匹配:

&#13;
&#13;
//remove row in the ResultSet
	public void removeRow(String empID)
	{
		int rsRow = 0;
		try
		{
			//set cursor to beginning of data set (before first row)
			if(!resultSet.isBeforeFirst())
				resultSet.beforeFirst();
			
			//iterate through resultSet to find matching record with
			//correct employee ID. once found delete row
			while(resultSet.next())
			{
				if(resultSet.getString("EmployeeNo") == empID)
				{
					rsRow = resultSet.getRow();
					
					resultSet.deleteRow();
					System.out.println("User: " + empID + " was deleted from row: " + rsRow);
					break;
				}
			}
			
			resultSet.last();
			numRowCount = resultSet.getRow();
			
			fireTableRowsDeleted(rsRow, rsRow);

//			resultSet.absolute(rsRow);
//			resultSet.deleteRow();
		}
		catch (SQLException e)
		{
			e.printStackTrace();
		}
	}
	
&#13;
&#13;
&#13;

当然,现在JTable中的数据正在消失,我不明白。