Guest User

Untitled

a guest
Jan 20th, 2019
675
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.43 KB | None | 0 0
  1. public static Connection getConnection() throws SQLException {
  2. if(conn == null || conn.isClosed()) {
  3. conn = DriverManager.getConnection(
  4. "jdbc:derby:MyDB;create=true",
  5. "user", "password");
  6. }
  7. return conn;
  8. }
  9. public void close() {
  10. try {
  11. conn.close();
  12. DriverManager.getConnection("jdbc:derby:;shutdown=true");
  13. } catch (SQLException ex) {}
  14. }
  15.  
  16. Data Models and Data Access Models
  17. As shown before with the creation of tables, we want to be able to choose two different classes
  18. of data. First, we have the albums, information for which can be chosen from the albums table;
  19. and second, we have the genres, found within the genres table. To assist us, we create a data
  20. model (see Listing 13-3 and Listing 13-4). The data model consists of the classes Album and
  21. Genre, which provide relevant setters and getters. Note that no persistence logic is found in
  22. these classes. We will put this logic in a separate class.
  23.  
  24. public class Album {
  25. private int id = 0;
  26. private String title;
  27. private String tracks;
  28. private String cds;
  29. private String year;
  30. private Genre genre;
  31. public Album(
  32. int id, String title, String tracks, String cds, String year, Genre genre) {
  33. this.id = id;
  34. this.title = title;
  35. this.tracks = tracks;
  36. this.cds = cds;
  37. this.year = year;
  38. this.genre = genre;
  39. }
  40. public int getId() {
  41. return id;
  42. }
  43. public String getTitle() {
  44. return title;
  45. }
  46. ...
  47. }
  48.  
  49. The data model for an Album in the Genre class requires overwriting both the toString()
  50. and equals() methods. This is necessary for the correct representation and selection of a genre
  51. in the dialog for creating a new album.
  52.  
  53. public class Genre {
  54. private int id = 0;
  55. private String genre;
  56. public Genre(int id, String genre) {
  57. this.id = id;
  58. this.genre = genre;
  59. }
  60. public int getId() {
  61. return id;
  62. }
  63. public String getGenre() {
  64. return genre;
  65. }
  66. public String toString() {
  67. return genre;
  68. }
  69. public boolean equals(Object obj) {
  70. if(obj instanceof Genre) {
  71. if(((Genre)obj).getId() == id) {
  72. return true;
  73. }
  74. }
  75. return false;
  76. }
  77. }
  78.  
  79.  
  80.  
  81. To let the data model and business logic (which in this case is primarily the user interface
  82. for selecting data) be loosely coupled to the persistence layer, we encapsulate access to the
  83. database and SQL statements in a separate class named DataModel (see Listing 13-5). This class
  84. performs desired changes and requests to the database, while also providing the data via the
  85. Album and Genre data models.
  86. The methods getAlbums() and getGenres(), implemented in the DataModel class, provide
  87. vectors containing the chosen data. We also have the methods insertAlbum(), updateAlbum(),
  88. and deleteAlbum(), with which we enter albums into the database and also use for changing
  89. and deleting them.
  90. Listing 13-5. The DataModel class encapsulates the access to Java DB and makes data available
  91. via the related Album and Genre data models.
  92.  
  93.  
  94.  
  95. public class DataModel {
  96. public static Vector<Album> getAlbums() {
  97. Vector<Album> albums = new Vector<Album>();
  98. try {
  99. Statement stmt = Installer.getConnection().createStatement();
  100. ResultSet rs = stmt.executeQuery("SELECT * FROM albums"+
  101. " INNER JOIN genres ON albums.genre = genres.id");
  102. while(rs.next()) {
  103. albums.add(new Album(rs.getInt(1), rs.getString(2),
  104. rs.getString(3), rs.getString(4), rs.getString(5),
  105. new Genre(rs.getInt(7), rs.getString(8))));
  106. }
  107. rs.close();
  108. stmt.close();
  109. } catch(SQLException e) {
  110. Exceptions.printStackTrace(e);
  111. }
  112. return albums;
  113. }
  114. public static Vector<Genre> getGenres() {
  115. Vector<Genre> genres = new Vector<Genre>();
  116. try {
  117. Statement stmt = Installer.getConnection().createStatement();
  118. ResultSet rs = stmt.executeQuery("SELECT * FROM genres");
  119. while(rs.next()) {
  120. genres.add(new Genre(rs.getInt(1), rs.getString(2)));
  121. }
  122. rs.close();
  123. stmt.close();
  124. } catch(Exception e) {
  125. e.printStackTrace();
  126. }
  127. return genres;
  128. }
  129. public static void updateAlbum(Album a) throws SQLException {
  130. PreparedStatement stmt = Installer.getConnection().prepareStatement(
  131. "UPDATE albums SET title=?, tracks=?, cds=?, years=?, genre=? WHERE id=?");
  132. stmt.setString(1, a.getTitle());
  133. stmt.setString(2, a.getTracks());
  134. stmt.setString(3, a.getCDs());
  135. stmt.setString(4, a.getYear());
  136. stmt.setInt(5, a.getGenre().getId());
  137. stmt.setInt(6, a.getId());
  138. stmt.execute();
  139. }
  140. public static void insertAlbum(Album a) throws SQLException {
  141. PreparedStatement stmt =Installer.getConnection().prepareStatement(
  142. "INSERT INTO albums (title, tracks, cds, years, genre) VALUES(?,?,?,?,?)");
  143. stmt.setString(1, a.getTitle());
  144. stmt.setString(2, a.getTracks());
  145. stmt.setString(3, a.getCDs());
  146. stmt.setString(4, a.getYear());
  147. stmt.setInt(5, a.getGenre().getId());
  148. stmt.execute();
  149. }
  150. public static void deleteAlbum(Album a) throws SQLException {
  151. PreparedStatement stmt = Installer.getConnection().prepareStatement(
  152. "DELETE FROM albums WHERE id = ?");
  153. stmt.setInt(1, a.getId());
  154. stmt.execute();
  155. }
  156. }
  157.  
  158.  
  159.  
  160.  
  161. Displaying and Working with the Data
  162. We now come to components that will display the data, allowing the user to create and edit
  163. music albums. We’ll list the albums in a table within a TopComponent (see Figure 13-3). We begin
  164. by creating the AlbumsTopComponent class, containing a JTable. To enable the table to display
  165. the DataModel of our album, we need a model for the table.
  166. Since the DataModel is only available to this class, we implement it as a private inner class
  167. named AlbumTableModel (see Listing 13-6). The data is obtained from a vector of the type Album.
  168. Since we later need access to the model, we create it as a private data element. We connect the
  169. DataModel with the table via the setModel() method. Typically, table entries can be edited or
  170. viewed via a double-click of the mouse. To create this functionality, we register a MouseListener
  171. or a MouseAdapter with the JTable, which calls the editAlbumActionPerformed() method on
  172. double-click. This will be discussed next.
  173. Figure 13-3. Displaying the database entries in a table
  174. Listing 13-6. TopComponent implementation with AlbumTableModel
  175.  
  176.  
  177.  
  178. final class AlbumsTopComponent extends TopComponent {
  179. private JTable albums;
  180. private AlbumTableModel model = new AlbumTableModel();
  181. private AlbumsTopComponent() {
  182. initComponents();
  183. albums.setModel(model);
  184. albums.addMouseListener(new MouseAdapter() {
  185. public void mouseClicked(MouseEvent event) {
  186. if(event.getClickCount() == 2) {
  187. editAlbumActionPerformed(null);
  188. }
  189. }
  190. });
  191. }
  192. private static final class AlbumTableModel
  193. extends AbstractTableModel {
  194. private String[] columns = {"Title", "Tracks", "CDs", "Year"};
  195. private Vector<Album> data = new Vector<Album>();
  196. public Album getRow(int row) {
  197. return data.get(row);
  198. }
  199. public int getRowCount() {
  200. return data.size();
  201. }
  202. public int getColumnCount() {
  203. return columns.length;
  204. }
  205. public String getColumnName(int col) {
  206. return columns[col];
  207. }
  208. public Object getValueAt(int row, int col) {
  209. Album album = data.get(row);
  210. switch(col) {
  211. case 0: return album.getTitle();
  212. case 1: return album.getTracks();
  213. case 2: return album.getCDs();
  214. case 3: return album.getYear();
  215. }
  216. return "";
  217. }
  218. public Vector<Album> getData() {
  219. return data;
  220. }
  221. }
  222.  
  223.  
  224.  
  225.  
  226. As the TopComponent opens, we need to load and display the current entries from the database. For this reason, we override the method componentOpened(), where we use our data
  227. access model DataModel, which abstracts access to the database to obtain all entries in the
  228. database, via the getAlbums() method. We add these to the DataModel in the table and inform
  229. the view, which is the JTable, via the fireTableDataChanged() method, that the data has
  230. changed.
  231. Finally, we implement three action methods that enable the user to add, edit, and delete
  232. entries. For the creation of new albums, we have the newAlbumActionPerformed() method. We
  233. use it to call a static method that opens a dialog where the user can enter the required data. We
  234. create this dialog in the final step. If the method returns an Album instance, the dialog is immediately closed and the data is added to the database. If that code can be run without an
  235. exception being thrown, we add the album to the table.
  236.  
  237.  
  238.  
  239.  
  240. public void componentOpened() {
  241. model.getData().addAll(DataModel.getAlbums());
  242. model.fireTableDataChanged();
  243. }
  244. private void newAlbumActionPerformed(ActionEvent evt) {
  245. Album album = AlbumEditDialog.newAlbum();
  246. if(album != null) {
  247. try {
  248. DataModel.insertAlbum(album);
  249. model.getData().add(album);
  250. model.fireTableDataChanged();
  251. } catch(SQLException e) {
  252. Exceptions.printStackTrace(e);
  253. }
  254. }
  255. }
  256.  
  257.  
  258.  
  259.  
  260.  
  261. The method editAlbumActionPerformed() is invoked by means of the Edit button or by a
  262. double-click. Similar to the way new entries are created, we again call up a dialog. However, we
  263. need editAlbum() for that purpose, to which we pass an Album instance, allowing data to be
  264. edited in the dialog. The currently selected row in the table invokes the getSelectedRow()
  265. method, with the returned value allowing related data to be found in the JTable’s data model.
  266. The user can now change the data. If the OK button is clicked, the editAlbum() method is
  267. called, which returns the changed Album instance (see Listing 13-7). The changes are saved in
  268. the database with the updateAlbum() method.
  269. Finally, we need to address situations where the user deletes an entry from the database.
  270. That will be handled by the deleteAlbumActionPerformed() method. To prevent unintended
  271. deletion, the user is asked to confirm that the entry should be deleted. The dialog that is
  272. required for this functionality is created in a very simple way, via the NetBeans Dialogs API (see
  273. Chapter 8). We use the NotifyDescriptor.Confirmation instance. We show the dialog via the
  274. notify() method. Once the user has confirmed the deletion request, the entry is removed from
  275. the database via the deleteAlbum() method. Only when the operation can be completed
  276. successfully do we delete the album from the JTable and update with its current entries.
  277. Listing 13-7. TopComponent for displaying and working with the albums in the database
  278.  
  279.  
  280.  
  281.  
  282.  
  283. private void editAlbumActionPerformed(ActionEvent evt) {
  284. Album album = AlbumEditDialog.editAlbum(
  285. model.getRow(albums.getSelectedRow()));
  286. if(album != null) {
  287. try {
  288. DataModel.updateAlbum(album);
  289. model.fireTableDataChanged();
  290. } catch(SQLException e) {
  291. Exceptions.printStackTrace(e);
  292. }
  293. }
  294. }
  295. private void deleteAlbumActionPerformed(ActionEvent evt) {
  296. Album album = model.getRow(albums.getSelectedRow());
  297. NotifyDescriptor d = new NotifyDescriptor.Confirmation(
  298. "Are you sure you want delete the album " + album.getTitle(),
  299. "Confirm Album Deletion");
  300. if(DialogDisplayer.getDefault().notify(d) == NotifyDescriptor.YES_OPTION) {
  301. try {
  302. DataModel.deleteAlbum(album);
  303. model.getData().remove(album);
  304. model.fireTableDataChanged();
  305. } catch(SQLException e) {
  306. Exceptions.printStackTrace(e);
  307. }
  308. }
  309. }
  310. }
  311.  
  312.  
  313.  
  314.  
  315. Our last task is the creation of a dialog with which the data can be created and edited.
  316. Again, we need to use the classes of the Dialogs API; so we need not create a complete dialog of
  317. our own, but simply the panel with required fields (see Figure 13-4). We therefore create a
  318. simple JPanel class, via File ➤ New File ➤ Java GUI Forms ➤ JPanel Form.
  319. Figure 13-4. Dialog for working with entries
  320. In the constructor of the panel, we load all the genres from the database and add them to
  321. the combo box. Additionally, we require the methods newAlbum() and editAlbum(), which you
  322. were introduced to in the previous section. To simplify things, implement these as static
  323. methods (see Listing 13-8). These methods are therefore factories that are concerned with the
  324. creation of the dialog. First, create an instance of the AlbumEditDialog class. Create a dialog
  325. with the help of a DialogDescriptor, pass the recently created panel, and that’s everything
  326. needed for creating a dialog. As per usual, we show the dialog via the notify() method.
  327. As soon as the user clicks the OK button, we use the data to create an Album object and pass
  328. it back to the user; otherwise, we simply return null and indicate an error. In the case of the
  329. editAlbum() method, we take the same approach with creating the dialog. Simply fill the fields
  330. with the values of the selected album. However, when the dialog is completed, don’t create a
  331. new Album object; simply update the data via the relevant setters and pass the updated instance
  332. back to the user.
  333. Listing 13-8. Dialog for editing and creating new music albums
  334.  
  335.  
  336.  
  337.  
  338.  
  339.  
  340.  
  341. public class AlbumEditDialog extends Jpanel {
  342. private AlbumEditDialog() {
  343. initComponents();
  344. for(Genre g : DataModel.getGenres()) {
  345. genre.addItem(g);
  346. }
  347. }
  348. public static Album newAlbum() {
  349. AlbumEditDialog d = new AlbumEditDialog();
  350. DialogDescriptor desc = new DialogDescriptor(d, "New...");
  351. if(DialogDisplayer.getDefault().notify(desc) == DialogDescriptor.OK_OPTION) {
  352. Album album = new Album(0,
  353. d.title.getText(),
  354. d.tracks.getText(),
  355. d.cds.getText(),
  356. d.year.getText(),
  357. (Genre)d.genre.getModel().getSelectedItem());
  358. return album;
  359. } else {
  360. return null;
  361. }
  362. }
  363. public static Album editAlbum(Album album) {
  364. AlbumEditDialog d = new AlbumEditDialog();
  365. d.title.setText(album.getTitle());
  366. d.tracks.setText(album.getTracks());
  367. d.cds.setText(album.getCDs());
  368. d.year.setText(album.getYear());
  369. d.genre.getModel().setSelectedItem(album.getGenre());
  370. DialogDescriptor desc = new DialogDescriptor(d, "Edit...");
  371. if(DialogDisplayer.getDefault().notify(desc) == DialogDescriptor.OK_OPTION) {
  372. album.setTitle(d.title.getText());
  373. album.setTracks(d.tracks.getText());
  374. album.setCDs(d.cds.getText());
  375. album.setYear(d.year.getText());
  376. album.setGenre((Genre)d.genre.getModel().getSelectedItem());
  377. return album;
  378. } else {
  379. return null;
  380. }
  381. }
  382. }
  383.  
  384.  
  385.  
  386. At this point, we have explained everything relating to data access and display of data
  387. found within Java DB databases. We also looked at an example application, showing how to set
  388. up and use Java DB within the NetBeans Platform.
Add Comment
Please, Sign In to add comment