JAVA核心技术卷2ViewDB程序
setRow showRow dataPanel三个dataPanel的方法是关键.
1 import java.awt.*; 2 import java.awt.event.*; 3 import java.io.*; 4 import java.nio.file.*; 5 import java.sql.*; 6 import java.util.*; 7 import javax.sql.*; 8 import javax.sql.rowset.*; 9 import javax.swing.*; 10 11 /** 12 * This program uses metadata to display arbitrary tables in a database. 13 * @version 1.32 2012-01-26 14 * @author Cay Horstmann 15 */ 16 public class ViewDB 17 { 18 public static void main(String[] args) 19 { 20 EventQueue.invokeLater(new Runnable() 21 { 22 public void run() 23 { 24 JFrame frame = new ViewDBFrame();//这是顶层容器 25 frame.setTitle("ViewDB"); 26 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 27 frame.setVisible(true); 28 } 29 }); 30 } 31 } 32 33 /** 34 * The frame that holds the data panel and the navigation buttons. 35 */ 36 class ViewDBFrame extends JFrame 37 { 38 private JButton previousButton; 39 private JButton nextButton; 40 private JButton deleteButton; 41 private JButton saveButton;//以上为四个按钮 42 private DataPanel dataPanel; 43 private Component scrollPane;//所有组件的父类 带滚动条的窗格容器 44 private JComboBox<String> tableNames; 45 private Properties props; 46 private CachedRowSet crs; 47 48 public ViewDBFrame() 49 { 50 tableNames = new JComboBox<String>(); 51 tableNames.addActionListener(new ActionListener() 52 { 53 public void actionPerformed(ActionEvent event) 54 { 55 showTable((String) tableNames.getSelectedItem()); 56 } 57 }); 58 add(tableNames, BorderLayout.NORTH); 59 60 try 61 { 62 readDatabaseProperties(); 63 try (Connection conn = getConnection()) 64 { 65 DatabaseMetaData meta = conn.getMetaData(); 66 ResultSet mrs = meta.getTables(null, null, null, new String[] { "TABLE" }); 67 while (mrs.next()) 68 tableNames.addItem(mrs.getString(3)); 69 } 70 } 71 catch (SQLException e) 72 { 73 JOptionPane.showMessageDialog(this, e); 74 } 75 catch (IOException e) 76 { 77 JOptionPane.showMessageDialog(this, e); 78 } 79 80 JPanel buttonPanel = new JPanel(); 81 add(buttonPanel, BorderLayout.SOUTH); 82 83 previousButton = new JButton("Previous"); 84 previousButton.addActionListener(new ActionListener() 85 { 86 public void actionPerformed(ActionEvent event) 87 { 88 showPreviousRow(); 89 } 90 }); 91 buttonPanel.add(previousButton); 92 93 nextButton = new JButton("Next"); 94 nextButton.addActionListener(new ActionListener() 95 { 96 public void actionPerformed(ActionEvent event) 97 { 98 showNextRow(); 99 } 100 }); 101 buttonPanel.add(nextButton); 102 103 deleteButton = new JButton("Delete"); 104 deleteButton.addActionListener(new ActionListener() 105 { 106 public void actionPerformed(ActionEvent event) 107 { 108 deleteRow(); 109 } 110 }); 111 buttonPanel.add(deleteButton); 112 113 saveButton = new JButton("Save"); 114 saveButton.addActionListener(new ActionListener() 115 { 116 public void actionPerformed(ActionEvent event) 117 { 118 saveChanges(); 119 } 120 }); 121 buttonPanel.add(saveButton); 122 pack(); 123 } 124 125 /** 126 * Prepares the text fields for showing a new table, and shows the first row. 127 * @param tableName the name of the table to display 128 */ 129 public void showTable(String tableName) 130 { 131 try 132 { 133 try (Connection conn = getConnection()) 134 { 135 // get result set 136 Statement stat = conn.createStatement(); 137 ResultSet result = stat.executeQuery("SELECT * FROM " + tableName); 138 // copy into cached row set 139 RowSetFactory factory = RowSetProvider.newFactory(); 140 crs = factory.createCachedRowSet(); 141 crs.setTableName(tableName); 142 crs.populate(result); 143 } 144 145 if (scrollPane != null) remove(scrollPane); 146 dataPanel = new DataPanel(crs); 147 scrollPane = new JScrollPane(dataPanel); 148 add(scrollPane, BorderLayout.CENTER); 149 validate(); 150 showNextRow(); 151 } 152 catch (SQLException e) 153 { 154 JOptionPane.showMessageDialog(this, e); 155 } 156 } 157 158 /** 159 * Moves to the previous table row. 160 */ 161 public void showPreviousRow() 162 { 163 try 164 { 165 if (crs == null || crs.isFirst()) return; 166 crs.previous(); 167 dataPanel.showRow(crs); 168 } 169 catch (SQLException e) 170 { 171 for (Throwable t : e) 172 t.printStackTrace(); 173 } 174 } 175 176 /** 177 * Moves to the next table row. 178 */ 179 public void showNextRow() 180 { 181 try 182 { 183 if (crs == null || crs.isLast()) return; 184 crs.next(); 185 dataPanel.showRow(crs); 186 } 187 catch (SQLException e) 188 { 189 JOptionPane.showMessageDialog(this, e); 190 } 191 } 192 193 /** 194 * Deletes current table row. 195 */ 196 public void deleteRow() 197 { 198 try 199 { 200 try (Connection conn = getConnection()) 201 { 202 crs.deleteRow(); 203 crs.acceptChanges(conn); 204 if (crs.isAfterLast()) 205 if (!crs.last()) crs = null; 206 dataPanel.showRow(crs); 207 } 208 } 209 catch (SQLException e) 210 { 211 JOptionPane.showMessageDialog(this, e); 212 } 213 } 214 215 /** 216 * Saves all changes. 217 */ 218 public void saveChanges() 219 { 220 try 221 { 222 try (Connection conn = getConnection()) 223 { 224 dataPanel.setRow(crs); 225 crs.acceptChanges(conn); 226 } 227 } 228 catch (SQLException e) 229 { 230 JOptionPane.showMessageDialog(this, e); 231 } 232 } 233 234 private void readDatabaseProperties() throws IOException 235 { 236 props = new Properties(); 237 try (InputStream in = Files.newInputStream(Paths.get("database.properties"))) 238 { 239 props.load(in); 240 } 241 String drivers = props.getProperty("jdbc.drivers"); 242 if (drivers != null) System.setProperty("jdbc.drivers", drivers); 243 } 244 245 /** 246 * Gets a connection from the properties specified in the file database.properties. 247 * @return the database connection 248 */ 249 private Connection getConnection() throws SQLException 250 { 251 String url = props.getProperty("jdbc.url"); 252 String username = props.getProperty("jdbc.username"); 253 String password = props.getProperty("jdbc.password"); 254 255 return DriverManager.getConnection(url, username, password); 256 } 257 } 258 259 /** 260 * This panel displays the contents of a result set. 261 */ 262 class DataPanel extends JPanel 263 { 264 private java.util.List<JTextField> fields; 265 266 /** 267 * Constructs the data panel. 268 * @param rs the result set whose contents this panel displays 269 */ 270 public DataPanel(RowSet rs) throws SQLException 271 { 272 fields = new ArrayList<>(); 273 setLayout(new GridBagLayout()); 274 GridBagConstraints gbc = new GridBagConstraints(); 275 gbc.gridwidth = 1; 276 gbc.gridheight = 1; 277 278 ResultSetMetaData rsmd = rs.getMetaData(); 279 for (int i = 1; i <= rsmd.getColumnCount(); i++) 280 { 281 gbc.gridy = i - 1; 282 283 String columnName = rsmd.getColumnLabel(i); 284 gbc.gridx = 0; 285 gbc.anchor = GridBagConstraints.EAST; 286 add(new JLabel(columnName), gbc); 287 288 int columnWidth = rsmd.getColumnDisplaySize(i); 289 JTextField tb = new JTextField(columnWidth); 290 if (!rsmd.getColumnClassName(i).equals("java.lang.String")) 291 tb.setEditable(false); 292 293 fields.add(tb); 294 295 gbc.gridx = 1; 296 gbc.anchor = GridBagConstraints.WEST; 297 add(tb, gbc); 298 } 299 } 300 301 /** 302 * Shows a database row by populating all text fields with the column values. 303 */ 304 public void showRow(ResultSet rs) throws SQLException 305 { 306 for (int i = 1; i <= fields.size(); i++) 307 { 308 String field = rs == null ? "" : rs.getString(i); 309 JTextField tb = fields.get(i - 1); 310 tb.setText(field); 311 } 312 } 313 314 /** 315 * Updates changed data into the current row of the row set. 316 */ 317 public void setRow(RowSet rs) throws SQLException 318 { 319 for (int i = 1; i <= fields.size(); i++) 320 { 321 String field = rs.getString(i); 322 JTextField tb = fields.get(i - 1); 323 if (!field.equals(tb.getText())) 324 rs.updateString(i, tb.getText()); 325 } 326 rs.updateRow(); 327 } 328 }